diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index 3c64b9f6ad..f88a891b39 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -64,8 +64,8 @@ /turf/closed/wall, /area/maintenance/port/fore) "aam" = ( -/obj/structure/table, -/obj/item/storage/box/lights/mixed, +/obj/structure/rack, +/obj/item/storage/toolbox/emergency, /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, /area/maintenance/port/fore) @@ -90,15 +90,13 @@ /turf/open/floor/plasteel/airless/solarpanel, /area/solar/starboard/fore) "aap" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, -/area/maintenance/port/fore) +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/turf/closed/wall, +/area/crew_quarters/observatory) "aaq" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/emergency, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/maintenance/port/fore) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/closed/wall/r_wall, +/area/crew_quarters/observatory) "aar" = ( /obj/machinery/conveyor/auto{ dir = 8; @@ -664,14 +662,6 @@ }, /turf/open/floor/plating/airless, /area/router/aux) -"abF" = ( -/obj/machinery/mass_driver{ - dir = 8; - id = "sb_out"; - name = "Router Driver" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "abG" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -709,13 +699,6 @@ /obj/item/paper/fluff/cogstation/cluwne, /turf/open/floor/plating, /area/crew_quarters/theatre/clown) -"abJ" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "sb_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "abK" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -819,17 +802,10 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) -"abZ" = ( -/obj/machinery/conveyor{ - dir = 1; - id = "sb_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "aca" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 5; - id = "pb_off" + id = "pb" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -858,17 +834,9 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "ace" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "pb_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) -"acf" = ( -/obj/machinery/mass_driver{ - dir = 4; - id = "pb_out"; - name = "Router Driver" + id = "pb" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -898,9 +866,9 @@ name = "Medical Booth" }) "acj" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "solar_off" + id = "solar" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -973,8 +941,8 @@ /obj/structure/disposalpipe/junction{ dir = 4 }, -/obj/machinery/conveyor{ - id = "solar_off" +/obj/machinery/conveyor/auto{ + id = "solar" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1052,25 +1020,10 @@ /obj/structure/rack, /turf/open/floor/plasteel, /area/ai_monitored/security/armory) -"acz" = ( -/obj/machinery/mass_driver{ - dir = 4; - id = "sb_in"; - name = "Router Driver" - }, -/turf/open/floor/plating/airless, -/area/router/aux) -"acA" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "sb_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "acB" = ( /obj/machinery/conveyor{ dir = 6; - id = "sb_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1109,9 +1062,9 @@ /turf/closed/wall, /area/crew_quarters/lounge) "acG" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "pb_off" + id = "pb" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1142,8 +1095,8 @@ /area/crew_quarters/lounge) "acJ" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/conveyor{ - id = "solar_off" +/obj/machinery/conveyor/auto{ + id = "solar" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1297,18 +1250,11 @@ }, /turf/closed/wall/r_wall, /area/security/brig) -"adc" = ( -/obj/machinery/conveyor{ - id = "sb_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "add" = ( -/obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 6 }, -/turf/open/floor/plating, +/turf/closed/wall, /area/crew_quarters/observatory) "ade" = ( /obj/machinery/atmospherics/components/binary/valve/digital/on, @@ -1332,11 +1278,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/lounge) "adh" = ( -/obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 10 }, -/turf/open/floor/plating, +/turf/closed/wall, /area/crew_quarters/observatory) "adi" = ( /turf/open/floor/plasteel, @@ -1349,8 +1294,8 @@ /obj/structure/disposalpipe/segment{ dir = 5 }, -/obj/machinery/conveyor{ - id = "solar_off" +/obj/machinery/conveyor/auto{ + id = "solar" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1494,9 +1439,8 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/observatory) "adG" = ( -/obj/machinery/mass_driver{ - id = "serv_in"; - name = "Router Driver" +/obj/machinery/mass_driver/pressure_plate{ + id = "hydro_in" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -1535,13 +1479,6 @@ /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/stairs/medium, /area/security/brig) -"adL" = ( -/obj/machinery/mass_driver{ - id = "starboard_in"; - name = "Router Driver" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "adM" = ( /turf/closed/wall, /area/crew_quarters/observatory) @@ -2671,8 +2608,9 @@ /turf/open/floor/plating, /area/construction) "agy" = ( -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/table, +/obj/item/storage/box/lights/mixed, +/obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, /area/maintenance/port/fore) "agz" = ( @@ -4478,6 +4416,7 @@ /obj/structure/plasticflaps, /obj/structure/fans/tiny, /obj/machinery/door/poddoor{ + id = "security_out"; name = "Security Router" }, /turf/open/floor/plating, @@ -4661,7 +4600,7 @@ "als" = ( /obj/machinery/mass_driver{ dir = 1; - id = "sec_out"; + id = "security_out"; name = "Router Driver" }, /turf/open/floor/plating, @@ -5525,16 +5464,15 @@ dir = 8 }, /obj/item/destTagger, -/obj/machinery/button/door{ - id = "secblock"; - name = "Router Access Control"; - pixel_x = 8; - pixel_y = 24; - req_access_txt = "1" - }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 8 }, +/obj/machinery/button/massdriver{ + id = "security_out"; + name = "Security Driver Control"; + pixel_x = 8; + pixel_y = 24 + }, /turf/open/floor/plasteel, /area/router/sec) "ant" = ( @@ -5817,9 +5755,9 @@ /turf/open/floor/plating, /area/maintenance/solars/port) "anW" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "sec_off" + id = "sec" }, /turf/open/floor/plating, /area/router/sec) @@ -6276,20 +6214,20 @@ "aoS" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/conveyor{ - id = "serv_off" - }, /obj/machinery/door/poddoor{ - id = "servblock"; + id = "hydro_in"; name = "Service Router" }, +/obj/machinery/conveyor/auto{ + id = "service" + }, /turf/open/floor/plating, /area/router/service) "aoT" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, /obj/machinery/door/poddoor{ - id = "servblock"; + id = "hydro_out"; name = "Service Router" }, /turf/open/floor/plating, @@ -6478,11 +6416,6 @@ /obj/structure/cable{ icon_state = "2-8" }, -/obj/machinery/button/massdriver{ - id = "sec_out"; - pixel_x = 24; - pixel_y = 24 - }, /turf/open/floor/plasteel, /area/router/sec) "aps" = ( @@ -6792,8 +6725,8 @@ }, /area/chapel/main) "aqe" = ( -/obj/machinery/conveyor{ - id = "serv_off" +/obj/machinery/conveyor/auto{ + id = "service" }, /turf/open/floor/plating, /area/router/service) @@ -6933,7 +6866,7 @@ "aqy" = ( /obj/machinery/mass_driver{ dir = 1; - id = "serv_out"; + id = "hydro_out"; name = "Router Driver" }, /turf/open/floor/plating, @@ -7497,11 +7430,6 @@ light_color = "#ffc1c1" }, /obj/item/destTagger, -/obj/machinery/button/massdriver{ - id = "serv_out"; - pixel_x = 8; - pixel_y = -4 - }, /obj/machinery/requests_console{ department = "Service Router"; name = "Service Router RC"; @@ -7510,9 +7438,9 @@ /turf/open/floor/plasteel, /area/router/service) "arL" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "serv_off" + id = "service" }, /turf/open/floor/plating, /area/router/service) @@ -7962,12 +7890,11 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, -/obj/machinery/button/door{ - id = "servblock"; - name = "Router Access Control"; +/obj/machinery/button/massdriver{ + id = "hydro_out"; + name = "Service Driver Control"; pixel_x = 8; - pixel_y = 24; - req_one_access_txt = "12;25;26;28;35;46" + pixel_y = 24 }, /turf/open/floor/plasteel, /area/router/service) @@ -8538,7 +8465,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, -/obj/effect/landmark/xeno_spawn, /turf/open/floor/carpet/purple, /area/crew_quarters/dorms/purple) "atZ" = ( @@ -9047,9 +8973,9 @@ dir = 8 }, /obj/machinery/turnstile{ - name = "Genpop Entrance Turnstile"; - icon_state = "turnstile_map"; dir = 8; + icon_state = "turnstile_map"; + name = "Genpop Entrance Turnstile"; req_access_txt = "69" }, /turf/open/floor/plasteel, @@ -9730,9 +9656,9 @@ name = "Brig Lockdown" }, /obj/machinery/turnstile{ - name = "Genpop Entrance Turnstile"; - icon_state = "turnstile_map"; dir = 8; + icon_state = "turnstile_map"; + name = "Genpop Entrance Turnstile"; req_access_txt = "69" }, /turf/open/floor/plasteel, @@ -10134,9 +10060,6 @@ /turf/open/floor/plasteel, /area/hydroponics) "axt" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -10473,12 +10396,6 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, /turf/open/floor/engine, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -11341,10 +11258,9 @@ /turf/open/floor/plasteel, /area/security/prison) "azO" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/blobstart, -/turf/open/floor/plasteel, -/area/hydroponics/lobby) +/obj/structure/reagent_dispensers/watertank, +/turf/open/floor/plating, +/area/maintenance/port/fore) "azP" = ( /obj/effect/turf_decal/bot, /obj/machinery/vending/cola/random, @@ -11515,6 +11431,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/solars/port) "aAj" = ( @@ -12941,9 +12858,6 @@ "aCZ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/electricshock, -/obj/structure/cable{ - icon_state = "1-2" - }, /turf/open/floor/plating, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -15408,7 +15322,7 @@ icon_state = "0-4" }, /obj/machinery/power/apc{ - areastring = "/area/maintenance/central"; + areastring = "/area/security/main"; dir = 1; name = "Security Office APC"; pixel_y = 24 @@ -18668,6 +18582,9 @@ }) "aOl" = ( /obj/effect/turf_decal/delivery, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/open/floor/engine, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -18988,6 +18905,9 @@ /turf/open/floor/plating, /area/crew_quarters/fitness/cogpool) "aOV" = ( +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/open/floor/plasteel/stairs, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -19401,7 +19321,7 @@ icon_state = "0-8" }, /turf/open/floor/plating, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "aPO" = ( /obj/machinery/atmospherics/pipe/manifold/supply/visible{ dir = 8 @@ -19667,16 +19587,10 @@ icon_state = "4-8" }, /turf/open/floor/plating/airless, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "aQq" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/closed/wall/r_wall, -/area/space/nearstation) +/turf/open/floor/plating/airless, +/area/crew_quarters/fitness/cogpool) "aQr" = ( /obj/structure/grille, /obj/structure/disposalpipe/segment{ @@ -19689,7 +19603,7 @@ icon_state = "0-4" }, /turf/open/floor/plating, -/area/space/nearstation) +/area/crew_quarters/lounge/jazz) "aQs" = ( /obj/machinery/firealarm{ dir = 1; @@ -20145,6 +20059,9 @@ /area/crew_quarters/heads/hop) "aRp" = ( /obj/structure/sign/warning/fire, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/closed/wall/r_wall, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -20304,7 +20221,9 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/structure/cable, +/obj/structure/cable/yellow{ + icon_state = "0-2" + }, /turf/open/floor/engine, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -21439,6 +21358,9 @@ dir = 1; pixel_y = -26 }, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/engine/engineering{ name = "Engine Room" @@ -21744,10 +21666,6 @@ /turf/open/floor/plating, /area/maintenance/department/eva) "aUR" = ( -/obj/machinery/atmospherics/pipe/simple/general/hidden{ - dir = 8; - icon_state = "intact" - }, /obj/structure/cable{ icon_state = "4-8" }, @@ -21936,19 +21854,14 @@ dir = 8; pixel_y = -22 }, -/obj/machinery/button/massdriver{ - id = "public_out"; - pixel_x = 24; - pixel_y = -6 - }, /obj/effect/turf_decal/stripes/corner{ dir = 1 }, -/obj/machinery/button/door{ - id = "pubblock"; - name = "Router Access Control"; +/obj/machinery/button/massdriver{ + id = "public_out"; + name = "Public Router Control"; pixel_x = 24; - pixel_y = 24 + pixel_y = -8 }, /turf/open/floor/plasteel, /area/router/public) @@ -25118,9 +25031,11 @@ /turf/open/space/basic, /area/space/nearstation) "bcc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 8 + }, /turf/closed/wall/r_wall, -/area/space/nearstation) +/area/crew_quarters/lounge/jazz) "bcd" = ( /obj/item/kirbyplants{ icon_state = "plant-14" @@ -25134,8 +25049,8 @@ id = "public" }, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "cargoblock"; +/obj/machinery/door/poddoor{ + id = "public_in"; name = "Public Router" }, /turf/open/floor/plating, @@ -25148,8 +25063,8 @@ "bcg" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "cargoblock"; +/obj/machinery/door/poddoor{ + id = "public_out"; name = "Public Router" }, /turf/open/floor/plating, @@ -25426,7 +25341,7 @@ dir = 5 }, /turf/closed/wall/r_wall, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "bcP" = ( /obj/structure/cable{ icon_state = "4-8" @@ -25447,9 +25362,6 @@ /area/hallway/primary/central) "bcS" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Courtroom" - }, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/security/courtroom) @@ -25492,10 +25404,12 @@ /turf/closed/wall, /area/hallway/primary/central) "bcY" = ( -/obj/machinery/power/smes, /obj/structure/cable{ icon_state = "0-2" }, +/obj/machinery/power/smes{ + charge = 5e+006 + }, /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload_foyer) "bcZ" = ( @@ -25775,15 +25689,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bdE" = ( -/obj/machinery/atmospherics/pipe/simple/general/hidden{ - dir = 8; - icon_state = "intact" - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark, -/area/bridge) +/obj/effect/landmark/xeno_spawn, +/turf/open/floor/grass, +/area/hydroponics/garden{ + name = "Nature Preserve" + }) "bdF" = ( /obj/effect/turf_decal/tile/purple{ dir = 4 @@ -26013,6 +25923,7 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plasteel, /area/science/mixing) "bel" = ( @@ -26079,7 +25990,7 @@ dir = 8 }, /turf/closed/wall/r_wall, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "bet" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -26128,7 +26039,7 @@ dir = 8 }, /turf/closed/wall/r_wall/rust, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "bez" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -26165,7 +26076,7 @@ dir = 10 }, /turf/closed/wall/r_wall, -/area/space/nearstation) +/area/crew_quarters/lounge/jazz) "beE" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -26173,6 +26084,10 @@ }, /obj/structure/fans/tiny, /obj/structure/plasticflaps, +/obj/machinery/door/poddoor{ + id = "starboardbelthell_in"; + name = "Belt Hell" + }, /turf/open/floor/plating, /area/maintenance/disposal) "beF" = ( @@ -26874,11 +26789,15 @@ /turf/open/space/basic, /area/space/nearstation) "bgi" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 +/obj/machinery/door/firedoor, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, -/turf/open/space/basic, -/area/space) +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "bgj" = ( /obj/structure/table, /obj/item/weldingtool/mini, @@ -27474,6 +27393,7 @@ id = "sec" }, /obj/machinery/door/poddoor{ + id = "security_in"; name = "Security Router" }, /turf/open/floor/plating, @@ -27570,8 +27490,12 @@ /turf/open/floor/plasteel, /area/maintenance/department/chapel) "bhI" = ( -/turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/obj/machinery/door/firedoor, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "bhJ" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 @@ -27847,12 +27771,6 @@ /area/quartermaster/storage) "bim" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/button/massdriver{ - id = "router_in"; - name = "mass driver button (Router)"; - pixel_x = 24; - pixel_y = -8 - }, /turf/open/floor/plating, /area/maintenance/disposal) "bin" = ( @@ -27966,9 +27884,6 @@ /area/quartermaster/storage) "bix" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Courtroom" - }, /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 @@ -28112,9 +28027,10 @@ /turf/open/floor/plating, /area/maintenance/disposal) "biO" = ( -/obj/effect/landmark/xeno_spawn, -/turf/open/floor/plating, -/area/maintenance/solars/starboard/fore) +/obj/structure/grille, +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/turf/closed/wall/r_wall, +/area/engine/atmos) "biP" = ( /obj/machinery/light{ dir = 4; @@ -28721,6 +28637,11 @@ dir = 9; id = "mail" }, +/obj/structure/window/reinforced{ + dir = 8; + layer = 2.9 + }, +/obj/structure/window/reinforced, /turf/open/floor/plating, /area/quartermaster/sorting) "bkc" = ( @@ -29042,6 +28963,9 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/engine/engineering{ name = "Engine Room" @@ -29936,10 +29860,13 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bmz" = ( -/obj/structure/closet/firecloset, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/storage/primary) +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/turf/open/space/basic, +/area/space/nearstation) "bmA" = ( /obj/item/stack/tile/plasteel{ pixel_x = 10; @@ -30321,6 +30248,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "bng" = ( @@ -30448,6 +30378,9 @@ /area/crew_quarters/lounge/jazz) "bnp" = ( /obj/effect/turf_decal/delivery, +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "bnq" = ( @@ -30608,7 +30541,6 @@ /obj/structure/cable{ icon_state = "1-8" }, -/obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/fore) "bnI" = ( @@ -31542,7 +31474,7 @@ }) "bpL" = ( /obj/structure/cable{ - icon_state = "1-4" + icon_state = "1-2" }, /turf/closed/wall/r_wall, /area/engine/engine_smes{ @@ -31555,10 +31487,7 @@ "bpN" = ( /obj/structure/grille, /obj/machinery/power/terminal, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ +/obj/structure/cable/yellow{ icon_state = "0-4" }, /turf/open/floor/plating, @@ -32182,9 +32111,9 @@ }, /area/maintenance/central) "brf" = ( -/obj/effect/landmark/xeno_spawn, -/turf/open/floor/plating, -/area/maintenance/starboard/central) +/obj/machinery/atmospherics/pipe/manifold/green/visible, +/turf/open/floor/plasteel, +/area/engine/atmos) "brg" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -32770,7 +32699,6 @@ name = "Station Intercom (Common)"; pixel_x = 26 }, -/obj/effect/landmark/xeno_spawn, /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, /area/maintenance/disposal) @@ -33277,8 +33205,8 @@ "bts" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/light_construct/small{ - icon_state = "bulb-construct-stage1"; - dir = 1 + dir = 1; + icon_state = "bulb-construct-stage1" }, /turf/open/floor/plasteel, /area/maintenance/aft) @@ -33519,17 +33447,21 @@ "btZ" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "public_in"; + name = "Public Router" + }, /turf/open/floor/plating, /area/router) "bua" = ( /turf/closed/wall/r_wall, /area/science/robotics/mechbay) "bub" = ( -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, /obj/machinery/light, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/machinery/portable_atmospherics/scrubber, /turf/open/floor/plasteel, /area/hallway/primary/aft) "buc" = ( @@ -33543,6 +33475,10 @@ /obj/machinery/conveyor{ id = "router_off" }, +/obj/machinery/door/poddoor{ + id = "public_out"; + name = "Public Router" + }, /turf/open/floor/plating, /area/router) "bue" = ( @@ -33644,10 +33580,9 @@ /area/maintenance/department/chapel) "bus" = ( /obj/structure/window/reinforced/spawner/east, -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 1; - id = "public_in"; - name = "Router Driver" + id = "public_in" }, /turf/open/floor/plating, /area/router) @@ -34430,17 +34365,6 @@ name = "Routing Depot RC"; pixel_y = 28 }, -/obj/machinery/button/massdriver{ - id = "eva_in"; - name = "mass driver button (EVA)"; - pixel_x = -24 - }, -/obj/machinery/button/massdriver{ - id = "public_in"; - name = "mass driver button (Public)"; - pixel_x = -24; - pixel_y = 8 - }, /turf/open/floor/plasteel, /area/router) "bwi" = ( @@ -34783,9 +34707,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -35059,6 +34983,12 @@ pixel_x = 3; pixel_y = 1 }, +/obj/machinery/button/massdriver{ + id = "trash"; + name = "Trash Driver"; + pixel_x = -24; + pixel_y = -8 + }, /turf/open/floor/plating, /area/maintenance/disposal) "bxt" = ( @@ -35105,7 +35035,6 @@ /area/tcommsat/computer) "bxy" = ( /obj/item/trash/candle, -/obj/effect/landmark/xeno_spawn, /turf/open/floor/plating{ icon_state = "platingdmg3" }, @@ -35122,6 +35051,9 @@ dir = 1 }, /obj/item/paper/guides/cogstation/letter_eng, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "bxA" = ( @@ -35536,7 +35468,6 @@ /area/maintenance/starboard/central) "byu" = ( /obj/structure/disposalpipe/segment, -/obj/effect/landmark/blobstart, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plating, /area/maintenance/starboard/central) @@ -35616,11 +35547,6 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/machinery/button/massdriver{ - id = "eva_out"; - pixel_x = 24; - pixel_y = 24 - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 9 }, @@ -35633,7 +35559,7 @@ }, /obj/machinery/conveyor/auto{ dir = 4; - id = "EVA" + id = "eva" }, /turf/open/floor/plating, /area/router/eva) @@ -35954,7 +35880,7 @@ dir = 4; id = "MiningConveyer" }, -/turf/open/floor/plating/airless, +/turf/open/floor/plating, /area/quartermaster/miningoffice) "bzv" = ( /obj/effect/turf_decal/stripes/line, @@ -35966,7 +35892,7 @@ id = "MiningConveyer" }, /obj/structure/plasticflaps, -/turf/open/floor/plating/airless, +/turf/open/floor/plating, /area/quartermaster/miningoffice) "bzw" = ( /obj/structure/disposalpipe/segment{ @@ -36032,8 +35958,8 @@ "bzD" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "evablock"; +/obj/machinery/door/poddoor{ + id = "eva_out"; name = "EVA Router" }, /turf/open/floor/plating, @@ -36041,17 +35967,21 @@ "bzE" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/conveyor{ +/obj/machinery/door/poddoor{ + id = "eva_out"; + name = "EVA Router" + }, +/obj/machinery/conveyor/auto{ dir = 4; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) "bzF" = ( /obj/structure/window/reinforced/spawner, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -36067,6 +35997,7 @@ "bzH" = ( /obj/structure/disposalpipe/segment, /obj/structure/grille/broken, +/obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/disposal) "bzI" = ( @@ -37032,9 +36963,12 @@ "bBE" = ( /obj/structure/grille, /obj/machinery/power/terminal, -/obj/structure/cable{ +/obj/structure/cable/yellow{ icon_state = "0-8" }, +/obj/structure/cable/yellow{ + icon_state = "0-4" + }, /turf/open/floor/plating, /area/engine/engine_smes{ name = "Power Monitoring" @@ -37392,6 +37326,12 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/button/massdriver{ + id = "eva_out"; + name = "EVA Driver Control"; + pixel_x = 24; + pixel_y = -22 + }, /turf/open/floor/plasteel, /area/router/eva) "bCv" = ( @@ -37433,9 +37373,8 @@ dir = 4 }, /obj/effect/turf_decal/tile/yellow, -/obj/structure/closet/secure_closet/engineering_personal, -/obj/item/clothing/under/misc/overalls, /obj/structure/window/reinforced/spawner/east, +/obj/structure/closet/firecloset, /turf/open/floor/plasteel, /area/storage/primary) "bCA" = ( @@ -37471,8 +37410,8 @@ }, /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "evablock"; +/obj/machinery/door/poddoor{ + id = "eva_in"; name = "EVA Router" }, /turf/open/floor/plating, @@ -37561,10 +37500,9 @@ "bCR" = ( /obj/structure/window/reinforced/spawner/north, /obj/effect/turf_decal/stripes/line, -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 8; - id = "airbridge_in"; - name = "Router Driver" + id = "eva_in" }, /turf/open/floor/plating, /area/router) @@ -37580,9 +37518,9 @@ /obj/structure/window/reinforced/spawner/north, /obj/effect/turf_decal/stripes/line, /obj/structure/disposalpipe/sorting/mail/flip, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -37636,13 +37574,13 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "bCZ" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "router_off" - }, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/conveyor/auto{ + dir = 8; + id = "router" + }, /turf/open/floor/plating, /area/router) "bDa" = ( @@ -37909,14 +37847,14 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/machinery/conveyor{ - dir = 8; - id = "router_off" - }, /obj/structure/disposalpipe/junction/flip{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/conveyor/auto{ + dir = 8; + id = "router" + }, /turf/open/floor/plating, /area/router) "bDE" = ( @@ -38139,12 +38077,13 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/conveyor{ - dir = 8; - id = "router_off" - }, /obj/structure/disposalpipe/sorting/mail{ - dir = 4 + dir = 4; + sortType = 9 + }, +/obj/machinery/conveyor/auto{ + dir = 8; + id = "router" }, /turf/open/floor/plating, /area/router) @@ -38167,9 +38106,9 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -38359,9 +38298,9 @@ }, /obj/effect/turf_decal/stripes/line, /obj/structure/disposalpipe/segment, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -38491,7 +38430,9 @@ /area/crew_quarters/bar) "bEK" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible, -/obj/machinery/space_heater, +/obj/machinery/space_heater{ + anchored = 1 + }, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, @@ -39424,18 +39365,6 @@ pixel_x = 26 }, /obj/effect/decal/cleanable/dirt, -/obj/machinery/button/massdriver{ - id = "eng_in"; - name = "mass driver button (Engineering)"; - pixel_x = 24; - pixel_y = -8 - }, -/obj/machinery/button/massdriver{ - id = "router_out"; - name = "mass driver button (Other)"; - pixel_x = 24; - pixel_y = 12 - }, /turf/open/floor/plasteel, /area/router) "bGz" = ( @@ -39527,12 +39456,6 @@ /obj/item/clothing/gloves/color/grey, /turf/open/floor/plating, /area/maintenance/starboard/central) -"bGK" = ( -/obj/machinery/conveyor{ - id = "starboard_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "bGL" = ( /obj/structure/chair{ dir = 1 @@ -39574,14 +39497,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) -"bGP" = ( -/obj/machinery/mass_driver{ - dir = 1; - id = "secserv"; - name = "Router Driver" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "bGQ" = ( /obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment{ @@ -39696,13 +39611,6 @@ name = "EVA Router APC"; pixel_x = 24 }, -/obj/machinery/button/door{ - id = "evablock"; - name = "Router Access Control"; - pixel_x = 24; - pixel_y = 10; - req_access_txt = "19" - }, /turf/open/floor/plasteel, /area/router/eva) "bHb" = ( @@ -40583,8 +40491,9 @@ /area/maintenance/department/chapel) "bIY" = ( /obj/machinery/atmospherics/pipe/simple/violet/hidden, +/obj/structure/lattice, /turf/open/space/basic, -/area/space) +/area/space/nearstation) "bIZ" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -42717,20 +42626,12 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 4; - id = "router_out"; - name = "Router Driver" + id = "starboardbelthell_out" }, /turf/open/floor/plating, /area/router) -"bNo" = ( -/obj/machinery/conveyor{ - dir = 1; - id = "starboard_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "bNp" = ( /obj/machinery/light{ dir = 1 @@ -42756,6 +42657,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) "bNr" = ( @@ -43726,7 +43628,6 @@ /turf/open/space/basic, /area/space/nearstation) "bPB" = ( -/obj/machinery/meter, /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, @@ -43736,13 +43637,12 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bPC" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 4; - name = "Waste In" - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPD" = ( @@ -43963,7 +43863,7 @@ dir = 8 }, /obj/structure/disposalpipe/sorting/mail{ - sortType = 1 + sortType = 2 }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, @@ -44382,7 +44282,6 @@ /obj/structure/chair/office/dark{ dir = 4 }, -/obj/effect/landmark/start/atmospheric_technician, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, @@ -45195,6 +45094,7 @@ /area/science/mixing) "bSm" = ( /obj/machinery/modular_computer/console/preset/engineering, +/obj/structure/cable/yellow, /turf/open/floor/plasteel, /area/engine/engine_smes{ name = "Power Monitoring" @@ -45207,12 +45107,12 @@ name = "Power Monitoring" }) "bSo" = ( -/obj/structure/cable{ - icon_state = "1-4" +/obj/structure/cable/yellow{ + icon_state = "1-2" }, -/turf/open/floor/plating, -/area/engine/engine_smes{ - name = "Power Monitoring" +/turf/open/floor/engine, +/area/engine/supermatter{ + name = "Thermo-Electric Generator" }) "bSp" = ( /obj/structure/cable{ @@ -45325,7 +45225,7 @@ }, /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1; - sortType = 11 + sortType = 9 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -45837,6 +45737,7 @@ "bTF" = ( /obj/structure/grille/broken, /obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plating, /area/router) "bTG" = ( @@ -46008,15 +45909,15 @@ /turf/open/space/basic, /area/space/nearstation) "bUa" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, /obj/machinery/camera{ c_tag = "Atmospherics - Entrance" }, /obj/machinery/firealarm{ pixel_y = 26 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bUb" = ( @@ -47053,10 +46954,10 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, -/obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/simple/supplymain/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bVY" = ( @@ -47260,9 +47161,6 @@ /turf/open/floor/engine/n2o, /area/engine/atmos) "bWq" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /obj/machinery/airalarm{ dir = 8; @@ -47414,12 +47312,10 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bWG" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/manifold/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bWH" = ( @@ -48037,9 +47933,9 @@ /area/maintenance/aft) "bXM" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "router_off" + id = "router" }, /turf/open/floor/plating, /area/router) @@ -48060,11 +47956,11 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "bXP" = ( -/obj/structure/cable{ - icon_state = "0-4" +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/turf/open/floor/plasteel, +/area/engine/atmos) "bXQ" = ( /obj/structure/closet/l3closet/scientist, /obj/effect/turf_decal/tile/purple, @@ -48117,11 +48013,12 @@ name = "Research Sector" }) "bXV" = ( -/obj/structure/cable{ - icon_state = "4-8" +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Pure to Mix" }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/turf/open/floor/plasteel, +/area/engine/atmos) "bXW" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -48197,11 +48094,9 @@ name = "Research Sector" }) "bYd" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/closed/wall/r_wall, -/area/hallway/primary/central) +/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible, +/turf/open/floor/plasteel, +/area/engine/atmos) "bYe" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, @@ -48220,6 +48115,10 @@ id = "router" }, /obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "starboardbelthell_in"; + name = "Belt Hell" + }, /turf/open/floor/plating, /area/router) "bYg" = ( @@ -48576,14 +48475,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bYP" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, /obj/structure/cable{ - icon_state = "0-8" + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Distro to Waste" }, /turf/open/floor/plasteel, -/area/hallway/primary/central) +/area/engine/atmos) "bYQ" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -49034,12 +48934,22 @@ /turf/open/floor/engine/co2, /area/engine/atmos) "bZQ" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 5 +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_y = -30 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel, -/area/hallway/primary/central) +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_y = -30 + }, +/obj/structure/tank_dispenser{ + pixel_x = -1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "bZR" = ( /obj/effect/spawner/structure/window/plasma/reinforced, /turf/open/floor/plating, @@ -49174,6 +49084,7 @@ /turf/open/floor/plasteel, /area/engine/break_room) "cai" = ( +/obj/machinery/atmospherics/pipe/simple/dark/visible, /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, @@ -49194,7 +49105,7 @@ "cak" = ( /obj/structure/sign/warning/fire, /turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cal" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 10 @@ -49206,7 +49117,7 @@ "cam" = ( /obj/machinery/door/poddoor/incinerator_atmos_main, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "can" = ( /obj/machinery/power/turbine{ dir = 8 @@ -49215,7 +49126,7 @@ icon_state = "0-4" }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cao" = ( /obj/machinery/power/compressor{ dir = 4 @@ -49227,7 +49138,7 @@ icon_state = "0-4" }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cap" = ( /obj/structure/cable{ icon_state = "4-8" @@ -49238,7 +49149,7 @@ }, /obj/machinery/igniter/incinerator_atmos, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "caq" = ( /obj/machinery/door/airlock/public/glass/incinerator/atmos_exterior, /obj/effect/mapping_helpers/airlock/locked, @@ -49249,7 +49160,7 @@ dir = 4 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "car" = ( /obj/machinery/atmospherics/pipe/manifold/yellow/visible, /turf/open/floor/plasteel, @@ -49263,7 +49174,6 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/engine/vacuum, /area/engine/atmos) "cat" = ( @@ -49273,7 +49183,7 @@ "cau" = ( /obj/machinery/door/poddoor/incinerator_atmos_aux, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cav" = ( /turf/closed/wall/r_wall, /area/science/explab) @@ -49545,6 +49455,7 @@ "cbe" = ( /obj/structure/table/reinforced, /obj/item/clothing/mask/gas, +/obj/effect/landmark/blobstart, /turf/open/floor/engine, /area/science/explab) "cbf" = ( @@ -49926,13 +49837,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/central) -"cbS" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "starboard_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "cbT" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ dir = 4 @@ -49940,28 +49844,28 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, -/obj/machinery/firealarm{ - dir = 1; - pixel_x = -2; - pixel_y = -27 - }, /obj/structure/cable{ icon_state = "1-8" }, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cbU" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 8; - name = "Air to Distro" - }, /obj/machinery/power/apc/highcap/ten_k{ areastring = "/area/engine/atmos"; name = "Atmospherics APC"; - pixel_y = -28 + pixel_y = -24 }, /obj/structure/cable, -/turf/open/floor/plasteel, +/obj/machinery/atmospherics/pipe/manifold/supplymain/visible, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/machinery/vending/wardrobe/atmos_wardrobe, +/turf/open/floor/plasteel/dark, /area/engine/atmos) "cbV" = ( /obj/structure/disposalpipe/segment, @@ -50055,9 +49959,9 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "starboard_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -50084,9 +49988,8 @@ /area/router) "cci" = ( /obj/structure/window/reinforced/spawner/west, -/obj/machinery/mass_driver{ - id = "workshop_in"; - name = "Router Driver" +/obj/machinery/mass_driver/pressure_plate{ + id = "portbelthell_out" }, /turf/open/floor/plating, /area/router) @@ -50184,9 +50087,9 @@ /area/router/aux) "ccs" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "starboard_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -50247,6 +50150,10 @@ id = "router" }, /obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "portbelthell_in"; + name = "Airbridge Router" + }, /turf/open/floor/plating, /area/router) "ccz" = ( @@ -50320,11 +50227,10 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "ccE" = ( -/obj/machinery/mass_driver{ - id = "eng_in"; - name = "Router Driver" - }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/mass_driver/pressure_plate{ + id = "engi_in" + }, /turf/open/floor/plating, /area/router) "ccF" = ( @@ -50349,10 +50255,9 @@ /turf/open/floor/plasteel, /area/engine/atmos) "ccH" = ( -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 8; - id = "disposal_in"; - name = "Router Driver" + id = "recycle_in" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -50368,13 +50273,6 @@ }, /turf/open/floor/plating, /area/maintenance/disposal) -"ccJ" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "starboard_off" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "ccK" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 9 @@ -50409,7 +50307,8 @@ "ccO" = ( /obj/structure/grille, /obj/structure/disposalpipe/sorting/mail{ - dir = 8 + dir = 8; + sortType = 21 }, /turf/open/floor/plating/airless, /area/router/aux) @@ -50673,10 +50572,7 @@ /turf/open/space/basic, /area/space/nearstation) "cdq" = ( -/obj/machinery/mass_driver{ - id = "sq_in"; - name = "Router Driver" - }, +/obj/machinery/mass_driver/pressure_plate, /turf/open/floor/plating/airless, /area/router/aux) "cdr" = ( @@ -50820,8 +50716,8 @@ "cdG" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "engblock"; +/obj/machinery/door/poddoor{ + id = "engi_out"; name = "Engineering Router" }, /turf/open/floor/plating, @@ -50961,8 +50857,8 @@ id = "eng" }, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "engblock"; +/obj/machinery/door/poddoor{ + id = "engi_in"; name = "Engineering Router" }, /turf/open/floor/plating, @@ -51172,7 +51068,7 @@ /obj/structure/window/reinforced/spawner/east, /obj/machinery/mass_driver{ dir = 1; - id = "eng_out"; + id = "engi_out"; name = "Router Driver" }, /obj/structure/window/reinforced/spawner/west, @@ -51391,17 +51287,11 @@ dir = 1 }, /obj/machinery/button/massdriver{ - id = "eng_out"; + id = "engi_out"; + name = "Engineering Driver Control"; pixel_x = -24; pixel_y = 24 }, -/obj/machinery/button/door{ - id = "engblock"; - name = "Router Access Control"; - pixel_x = -24; - pixel_y = 32; - req_access_txt = "31" - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 }, @@ -51483,12 +51373,12 @@ /turf/open/floor/plasteel, /area/router/eng) "ceU" = ( -/obj/machinery/atmospherics/pipe/simple/dark/visible{ - dir = 9 - }, /obj/structure/fireaxecabinet{ pixel_y = -32 }, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ + dir = 9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "ceV" = ( @@ -51888,15 +51778,15 @@ name = "Canister Storage" }) "cfM" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /obj/structure/cable{ icon_state = "2-8" }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/manifold/supplymain/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cfN" = ( @@ -51921,13 +51811,14 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "cfP" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Mix to Distro" + }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cfQ" = ( @@ -51954,10 +51845,16 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "cfT" = ( -/obj/machinery/atmospherics/pipe/manifold/orange/visible, /obj/structure/cable{ icon_state = "2-8" }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Air to Mix" + }, +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cfU" = ( @@ -52061,6 +51958,10 @@ id = "disposal" }, /obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "starboardbelthell_out"; + name = "Belt Hell" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cge" = ( @@ -52097,20 +51998,14 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cgg" = ( -/obj/effect/landmark/start/atmospheric_technician, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 10 - }, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/manifold4w/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cgh" = ( /obj/machinery/pipedispenser, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, /obj/effect/turf_decal/stripes/end{ dir = 1 }, @@ -52260,10 +52155,12 @@ /turf/open/floor/plasteel/dark, /area/engine/teg_hot) "cgx" = ( -/obj/machinery/atmospherics/pipe/manifold4w/cyan/visible, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cgy" = ( @@ -52271,10 +52168,10 @@ /turf/closed/wall/rust, /area/maintenance/solars/starboard/aft) "cgz" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, /obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Port to Filter" + }, /turf/open/floor/plasteel, /area/engine/atmos) "cgA" = ( @@ -52629,37 +52526,23 @@ name = "Nature Preserve" }) "chn" = ( -/obj/machinery/atmospherics/pipe/manifold/orange/visible{ - dir = 1 - }, /obj/machinery/light{ dir = 8 }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/disposal/incinerator"; - dir = 8; - name = "Incinerator APC"; - pixel_x = -24 - }, -/obj/structure/cable{ - icon_state = "0-4" - }, +/obj/machinery/atmospherics/pipe/manifold4w/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cho" = ( /turf/closed/wall/r_wall/rust, /area/maintenance/department/eva) "chp" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, /turf/open/floor/plasteel, /area/engine/atmos) "chq" = ( @@ -52712,10 +52595,10 @@ /turf/open/floor/plating, /area/maintenance/disposal) "chx" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "chy" = ( @@ -52826,21 +52709,21 @@ /turf/open/floor/plating, /area/engine/teg_cold) "chL" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 6 - }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "chM" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 4 - }, /obj/structure/cable{ icon_state = "1-8" }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "chN" = ( @@ -52919,11 +52802,13 @@ /turf/open/floor/engine, /area/science/storage) "chS" = ( -/obj/machinery/suit_storage_unit/atmos, /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 6 + }, +/obj/machinery/portable_atmospherics/pump, /turf/open/floor/plasteel/dark, /area/engine/atmos) "chT" = ( @@ -53102,12 +52987,11 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/machinery/mass_driver{ - dir = 8; - id = "router_in"; - name = "Router Driver" - }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/mass_driver/pressure_plate{ + dir = 8; + id = "starboardbelthell_in" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cil" = ( @@ -53127,7 +53011,7 @@ "cim" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1; - sortType = 11 + sortType = 9 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -53150,11 +53034,10 @@ /turf/closed/wall, /area/science/robotics/mechbay) "cip" = ( -/obj/machinery/mass_driver{ - id = "cargo_in"; - name = "Router Driver" - }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/mass_driver/pressure_plate{ + id = "cargo_in" + }, /turf/open/floor/plating, /area/maintenance/disposal) "ciq" = ( @@ -53187,6 +53070,7 @@ /obj/structure/cable{ icon_state = "2-4" }, +/obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/port/fore) "ciu" = ( @@ -53242,7 +53126,7 @@ "ciB" = ( /obj/structure/frame/computer, /obj/structure/disposalpipe/segment, -/turf/open/floor/plating/airless, +/turf/open/floor/plating, /area/maintenance/port/fore) "ciC" = ( /obj/structure/table, @@ -53280,12 +53164,13 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "ciG" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "disposal_off" +/obj/structure/cable/yellow{ + icon_state = "1-2" }, -/turf/open/floor/plating, -/area/maintenance/disposal) +/turf/closed/wall/r_wall, +/area/engine/engineering{ + name = "Engine Room" + }) "ciH" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 6 @@ -53351,10 +53236,9 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/kitchen) "ciO" = ( -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 4; - id = "disposal_out"; - name = "Router Driver" + id = "recycle_out" }, /turf/open/floor/plating, /area/maintenance/disposal) @@ -53487,7 +53371,8 @@ /obj/structure/fans/tiny, /obj/structure/plasticflaps, /obj/machinery/door/poddoor{ - name = "Disposal Router" + id = "recycle_out"; + name = "Belt Hell" }, /turf/open/floor/plating, /area/maintenance/disposal) @@ -53539,6 +53424,10 @@ dir = 1; id = "disposal" }, +/obj/machinery/door/poddoor{ + id = "cargo_out"; + name = "Cargo Router" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cjj" = ( @@ -53897,9 +53786,6 @@ /area/engine/teg_cold) "cjV" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Engineering Sector" - }, /obj/structure/disposalpipe/segment, /obj/structure/disposalpipe/segment{ dir = 4 @@ -53929,8 +53815,8 @@ /obj/machinery/button/door{ id = "hos"; name = "HoS Office Shutters"; - pixel_y = -32; - pixel_x = -5 + pixel_x = -5; + pixel_y = -32 }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) @@ -55207,8 +55093,8 @@ "cmH" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "cargoblock"; +/obj/machinery/door/poddoor{ + id = "cargo_out"; name = "Cargo Router" }, /turf/open/floor/plating, @@ -55275,14 +55161,18 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "cmL" = ( -/obj/effect/landmark/blobstart, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/machinery/light, +/obj/machinery/suit_storage_unit/atmos, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "cmM" = ( /obj/structure/sign/poster/official/safety_internals{ pixel_x = -32 }, -/obj/effect/landmark/blobstart, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plating, /area/maintenance/starboard/aft) "cmN" = ( @@ -55421,6 +55311,9 @@ /area/quartermaster/qm) "cmX" = ( /obj/machinery/light/small, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, /turf/open/floor/engine, /area/engine/supermatter{ name = "Thermo-Electric Generator" @@ -55535,9 +55428,11 @@ /turf/open/floor/plasteel, /area/engine/teg_cold) "cni" = ( -/obj/effect/landmark/xeno_spawn, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/obj/machinery/atmospherics/components/binary/pump{ + name = "Port to Fuel Pipe" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "cnj" = ( /obj/machinery/camera{ c_tag = "Research - Observatory"; @@ -55570,7 +55465,6 @@ dir = 1; pixel_x = 5 }, -/obj/effect/landmark/xeno_spawn, /turf/open/floor/plasteel/dark, /area/science/xenobiology) "cnm" = ( @@ -55646,7 +55540,8 @@ id = "disposal" }, /obj/machinery/door/poddoor{ - name = "Disposal Router" + id = "recycle_in"; + name = "Belt Hell" }, /turf/open/floor/plating, /area/maintenance/disposal) @@ -55815,14 +55710,6 @@ /obj/item/target/clown, /turf/open/floor/plasteel, /area/science/mixing) -"cnM" = ( -/obj/machinery/mass_driver{ - dir = 8; - id = "pb_in"; - name = "Router Driver" - }, -/turf/open/floor/plating/airless, -/area/router/aux) "cnN" = ( /obj/structure/bookcase/random/fiction, /obj/effect/turf_decal/tile/neutral, @@ -56008,13 +55895,15 @@ name = "Electrical Substation" }) "coh" = ( -/obj/machinery/power/smes, /obj/structure/cable{ icon_state = "0-4" }, /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/power/smes{ + charge = 5e+006 + }, /turf/open/floor/plating, /area/engine/storage_shared{ name = "Electrical Substation" @@ -56203,8 +56092,8 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 +/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ + dir = 1 }, /turf/open/floor/plasteel, /area/hallway/primary/aft) @@ -56248,7 +56137,7 @@ /obj/structure/cable{ icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden, +/obj/machinery/atmospherics/pipe/manifold4w/orange/hidden, /turf/open/floor/plasteel, /area/hallway/primary/aft) "coE" = ( @@ -56679,8 +56568,8 @@ id = "cargo" }, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "cargoblock"; +/obj/machinery/door/poddoor{ + id = "cargo_in"; name = "Cargo Router" }, /turf/open/floor/plating, @@ -56792,6 +56681,10 @@ "cpE" = ( /obj/structure/fans/tiny, /obj/structure/plasticflaps, +/obj/machinery/door/poddoor{ + id = "cargo_in"; + name = "Cargo Router" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cpF" = ( @@ -56901,12 +56794,18 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 6 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "cpO" = ( /obj/structure/closet/secure_closet/atmospherics, /obj/item/cartridge/atmos, /obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "cpP" = ( @@ -56917,14 +56816,12 @@ /turf/open/floor/plasteel/white, /area/gateway) "cpQ" = ( -/obj/machinery/vending/wardrobe/atmos_wardrobe, /obj/effect/turf_decal/stripes/line{ dir = 6; layer = 2.03 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/pipe/manifold/orange/visible, +/obj/machinery/portable_atmospherics/pump, /turf/open/floor/plasteel/dark, /area/engine/atmos) "cpR" = ( @@ -57238,6 +57135,9 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "cqt" = ( @@ -57260,6 +57160,9 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "cqv" = ( @@ -57273,6 +57176,9 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/break_room) "cqw" = ( @@ -57617,11 +57523,6 @@ name = "\improper KEEP CLEAR: HIGH SPEED DELIVERIES"; pixel_y = 32 }, -/obj/machinery/button/massdriver{ - id = "cargo_out"; - pixel_x = -8; - pixel_y = -4 - }, /turf/open/floor/plasteel, /area/quartermaster/sorting) "cre" = ( @@ -58608,9 +58509,9 @@ /obj/machinery/button/door{ id = "robotics"; name = "Shutters Control Button"; + pixel_x = -24; pixel_y = 8; - req_access_txt = "29"; - pixel_x = -24 + req_access_txt = "29" }, /turf/open/floor/plasteel/dark/side{ dir = 8 @@ -58648,8 +58549,6 @@ dir = 8; light_color = "#e8eaff" }, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/xeno_spawn, /turf/open/floor/engine, /area/science/explab) "ctc" = ( @@ -58998,6 +58897,10 @@ /area/science/explab) "ctJ" = ( /obj/structure/plasticflaps, +/obj/machinery/door/poddoor{ + id = "portbelthell_in"; + name = "Airbridge Router" + }, /turf/open/floor/plating, /area/engine/workshop) "ctK" = ( @@ -59005,6 +58908,10 @@ /obj/machinery/conveyor{ id = "workshop_off" }, +/obj/machinery/door/poddoor{ + id = "portbelthell_out"; + name = "Airbridge Router" + }, /turf/open/floor/plating, /area/engine/workshop) "ctL" = ( @@ -59474,7 +59381,7 @@ dir = 4 }, /turf/open/floor/plating/airless, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "cuy" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -59685,17 +59592,16 @@ /area/router/air) "cuS" = ( /obj/structure/window/reinforced/spawner/east, -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 1; - id = "workshop_out"; - name = "Router Driver" + id = "portbelthell_in" }, /turf/open/floor/plating, /area/engine/workshop) "cuT" = ( /obj/structure/window/reinforced/spawner/west, -/obj/machinery/conveyor{ - id = "workshop_off" +/obj/machinery/conveyor/auto{ + id = "airbridge" }, /turf/open/floor/plating, /area/engine/workshop) @@ -59908,9 +59814,9 @@ /area/router/air) "cvq" = ( /obj/structure/window/reinforced/spawner/east, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "workshop_off" + id = "airbridge" }, /turf/open/floor/plating, /area/engine/workshop) @@ -60422,12 +60328,11 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/machinery/button/door{ - id = "cargoblock"; - name = "Router Access Control"; +/obj/machinery/button/massdriver{ + id = "cargo_out"; + name = "Cargo Driver Control"; pixel_x = -24; - pixel_y = 24; - req_access_txt = "31" + pixel_y = 24 }, /turf/open/floor/plasteel, /area/quartermaster/sorting) @@ -60587,6 +60492,9 @@ /obj/effect/turf_decal/stripes/line, /obj/machinery/door/firedoor/heavy, /obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/engine_smes{ name = "Power Monitoring" @@ -60894,6 +60802,7 @@ /obj/machinery/airalarm{ pixel_y = 24 }, +/obj/structure/cable/yellow, /turf/open/floor/plasteel, /area/engine/engine_smes{ name = "Power Monitoring" @@ -66167,15 +66076,16 @@ }, /obj/machinery/button/massdriver{ id = "airbridge_out"; + name = "Airbridge Driver Control"; pixel_x = -8; pixel_y = 24 }, /turf/open/floor/plasteel, /area/router/air) "cGa" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "airbridge_off" + id = "router" }, /turf/open/floor/plating, /area/router/air) @@ -66261,9 +66171,9 @@ /area/medical/medbay/central) "cGf" = ( /obj/structure/window/reinforced/spawner, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "airbridge_off" + id = "router" }, /turf/open/floor/plating, /area/router/air) @@ -66273,9 +66183,9 @@ dir = 1 }, /obj/structure/window/reinforced/spawner, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "airbridge_off" + id = "router" }, /turf/open/floor/plating, /area/router/air) @@ -66287,7 +66197,7 @@ /obj/structure/window/reinforced/spawner, /obj/machinery/mass_driver{ dir = 4; - id = "airbridge_in"; + id = "airbridge_out"; name = "Router Driver" }, /turf/open/floor/plating, @@ -66730,7 +66640,6 @@ /turf/open/floor/engine, /area/science/storage) "cGW" = ( -/obj/effect/landmark/blobstart, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -67029,7 +66938,6 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/effect/landmark/blobstart, /obj/machinery/atmospherics/pipe/manifold/orange/hidden{ dir = 4 }, @@ -67284,6 +67192,7 @@ /obj/structure/plasticflaps, /obj/structure/fans/tiny, /obj/machinery/door/poddoor{ + id = "airbridge_out"; name = "Airbridge Router" }, /turf/open/floor/plating, @@ -67326,7 +67235,6 @@ /turf/open/floor/plating, /area/maintenance/aft) "cId" = ( -/obj/effect/landmark/xeno_spawn, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 5 }, @@ -67363,17 +67271,21 @@ /area/medical/genetics) "cIh" = ( /obj/structure/plasticflaps, -/obj/machinery/conveyor{ +/obj/machinery/door/poddoor{ + id = "airbridge_out"; + name = "Airbridge Router" + }, +/obj/machinery/conveyor/auto{ dir = 4; - id = "workshop_off" + id = "router" }, /turf/open/floor/plating, /area/engine/workshop) "cIi" = ( /obj/structure/window/reinforced/spawner, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "workshop_off" + id = "router" }, /turf/open/floor/plating, /area/engine/workshop) @@ -67473,9 +67385,9 @@ "cIq" = ( /obj/structure/window/reinforced/spawner, /obj/structure/window/reinforced/spawner/east, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "workshop_off" + id = "airbridge" }, /turf/open/floor/plating, /area/engine/workshop) @@ -67502,13 +67414,13 @@ name = "Atmospherics"; req_access_txt = "24" }, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /obj/structure/cable{ icon_state = "4-8" }, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cIt" = ( @@ -67737,9 +67649,6 @@ /area/hallway/primary/aft) "cIN" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Engineering Sector" - }, /obj/structure/disposalpipe/segment, /obj/structure/disposalpipe/segment{ dir = 4 @@ -68040,17 +67949,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"cJo" = ( -/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/portable_atmospherics/pump, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel/white/corner, -/area/engine/atmos) "cJp" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 @@ -68103,14 +68001,10 @@ /turf/open/floor/plasteel, /area/ai_monitored/turret_protected/ai_upload_foyer) "cJu" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Mix to Engine" }, -/obj/machinery/portable_atmospherics/canister, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) "cJv" = ( @@ -68256,14 +68150,9 @@ /turf/open/floor/plasteel, /area/engine/gravity_generator) "cJH" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/machinery/portable_atmospherics/canister, /obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 + dir = 9 }, -/obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) "cJI" = ( @@ -68982,11 +68871,12 @@ /obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 5 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 1; + name = "Unfiltered & Air to Mix" }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 10 +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -69016,10 +68906,10 @@ /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/violet/visible, /obj/structure/extinguisher_cabinet{ pixel_y = 29 }, +/obj/machinery/atmospherics/pipe/simple/violet/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cLh" = ( @@ -69075,7 +68965,6 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/closed/wall/r_wall, /area/engine/atmos) "cLn" = ( @@ -69262,8 +69151,8 @@ /area/router/air) "cLK" = ( /obj/structure/window/reinforced/spawner/north, -/obj/machinery/conveyor{ - id = "airbridge_off" +/obj/machinery/conveyor/auto{ + id = "airbridge" }, /turf/open/floor/plating, /area/router/air) @@ -69289,9 +69178,9 @@ /area/medical/virology) "cLO" = ( /obj/structure/window/reinforced/spawner/north, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "airbridge_off" + id = "airbridge" }, /turf/open/floor/plating, /area/router/air) @@ -69328,6 +69217,7 @@ id = "airbridge_off" }, /obj/machinery/door/poddoor{ + id = "airbridge_in"; name = "Airbridge Router" }, /turf/open/floor/plating, @@ -69338,10 +69228,9 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 8; - id = "workshop_in"; - name = "Router Driver" + id = "airbridge_in" }, /turf/open/floor/plating, /area/engine/workshop) @@ -69363,8 +69252,8 @@ /turf/open/floor/plating/airless, /area/medical/virology) "cLV" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ - dir = 4 +/obj/machinery/atmospherics/components/binary/pump/on{ + name = "Waste to Filter" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -69381,19 +69270,13 @@ dir = 6 }, /turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cLY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/atmos/incinerator_output{ dir = 4 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) -"cLZ" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 4 - }, -/turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cMa" = ( /obj/machinery/light/small{ dir = 1; @@ -69404,21 +69287,17 @@ dir = 4 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cMb" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/closed/wall/r_wall, /area/engine/atmos) "cMc" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 6 }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 9 - }, /turf/open/floor/plasteel, /area/engine/atmos) "cMd" = ( @@ -69451,9 +69330,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "cMi" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/structure/closet/firecloset, -/turf/open/floor/plasteel, +/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/atmos_waste{ + dir = 1 + }, +/turf/open/floor/plating/airless, /area/engine/atmos) "cMj" = ( /obj/structure/cable{ @@ -69463,7 +69343,7 @@ dir = 1 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cMk" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 @@ -69527,7 +69407,7 @@ dir = 4 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cMu" = ( /obj/machinery/light/small, /obj/machinery/atmospherics/pipe/simple/cyan/visible, @@ -69535,7 +69415,7 @@ dir = 8 }, /turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/area/engine/atmos) "cMv" = ( /obj/machinery/button/door/incinerator_vent_atmos_main{ pixel_x = -24; @@ -69545,29 +69425,27 @@ pixel_x = -40; pixel_y = 8 }, -/obj/machinery/atmospherics/pipe/simple/general/visible{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cMw" = ( -/obj/machinery/atmospherics/components/binary/valve/digital{ - name = "Waste Release" - }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/machinery/atmospherics/pipe/simple/dark/visible{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) "cMx" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 5 - }, /obj/item/radio/intercom{ name = "Station Intercom (General)"; pixel_y = -30 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cMy" = ( @@ -69659,14 +69537,20 @@ /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "cMG" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 5 +/obj/structure/disposalpipe/segment{ + dir = 4 }, -/turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "cMH" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, -/turf/closed/wall/r_wall, +/obj/machinery/suit_storage_unit/atmos, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, /area/engine/atmos) "cMI" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ @@ -69717,13 +69601,12 @@ /turf/open/floor/plating, /area/engine/atmos) "cMP" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/atmos_waste{ - dir = 1 - }, /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ dir = 4 }, -/turf/open/floor/plating/airless, +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, /area/engine/atmos) "cMQ" = ( /obj/structure/lattice, @@ -69755,16 +69638,16 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "workshop_off" + id = "airbridge" }, /turf/open/floor/plating, /area/engine/workshop) "cMV" = ( -/obj/machinery/conveyor{ - dir = 10; - id = "workshop_off" +/obj/machinery/conveyor/auto{ + dir = 8; + id = "airbridge" }, /turf/open/floor/plating, /area/engine/workshop) @@ -69943,17 +69826,10 @@ /obj/machinery/light, /turf/open/floor/plasteel, /area/router/air) -"cNm" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "airbridge_off" - }, -/turf/open/floor/plating, -/area/router/air) "cNn" = ( -/obj/machinery/conveyor{ - dir = 10; - id = "airbridge_off" +/obj/machinery/conveyor/auto{ + dir = 8; + id = "airbridge" }, /turf/open/floor/plating, /area/router/air) @@ -70359,6 +70235,7 @@ icon_state = "2-4" }, /obj/effect/landmark/event_spawn, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plasteel/white, /area/science/xenobiology) "cOr" = ( @@ -70499,6 +70376,12 @@ dir = 4; pixel_x = -22 }, +/obj/machinery/button/massdriver{ + id = "research_out"; + name = "Medsci Driver Control"; + pixel_x = -24; + pixel_y = -24 + }, /turf/open/floor/plasteel, /area/router/medsci) "cOF" = ( @@ -70527,8 +70410,8 @@ /turf/closed/wall/r_wall, /area/router/medsci) "cOJ" = ( -/obj/machinery/conveyor{ - id = "medsci_off" +/obj/machinery/conveyor/auto{ + id = "medsci" }, /turf/open/floor/plating, /area/router/medsci) @@ -70538,11 +70421,6 @@ /obj/item/hand_labeler, /obj/item/destTagger, /obj/machinery/light, -/obj/machinery/button/massdriver{ - id = "medsci_out"; - pixel_x = -8; - pixel_y = 8 - }, /obj/machinery/requests_console{ department = "MedSci Router"; name = "MedSci Router RC"; @@ -70551,9 +70429,9 @@ /turf/open/floor/plating, /area/router/medsci) "cOL" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "medsci_off" + id = "medsci" }, /turf/open/floor/plating, /area/router/medsci) @@ -70579,7 +70457,7 @@ /area/janitor/aux) "cOP" = ( /obj/machinery/mass_driver{ - id = "medsci_out"; + id = "research_out"; name = "Router Driver" }, /turf/open/floor/plating, @@ -70649,6 +70527,7 @@ /obj/structure/plasticflaps, /obj/structure/fans/tiny, /obj/machinery/door/poddoor{ + id = "research_out"; name = "MedSci Router" }, /turf/open/floor/plating, @@ -70657,11 +70536,12 @@ /obj/structure/plasticflaps, /obj/structure/fans/tiny, /obj/machinery/door/poddoor{ + id = "research_in"; name = "MedSci Router" }, -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "medsci_off" + id = "medsci" }, /turf/open/floor/plating, /area/router/medsci) @@ -70691,6 +70571,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plasteel, /area/janitor/aux) "cOX" = ( @@ -70768,100 +70649,88 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "cPd" = ( -/obj/machinery/conveyor{ - id = "sq_off" +/obj/machinery/conveyor/auto{ + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) "cPe" = ( -/obj/machinery/mass_driver{ - dir = 1; - id = "sq_out"; - name = "Router Driver" +/obj/machinery/mass_driver/pressure_plate{ + dir = 1 }, /turf/open/floor/plating/airless, /area/router/aux) -"cPf" = ( -/obj/machinery/conveyor/auto, -/turf/open/floor/plating/airless, -/area/router/aux) "cPg" = ( -/obj/machinery/mass_driver{ +/obj/machinery/mass_driver/pressure_plate{ dir = 1; - id = "medsci_in"; - name = "Router Driver" + id = "research_in" }, /turf/open/floor/plating/airless, /area/router/aux) "cPh" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "sq_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) "cPi" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 1; - id = "viro_off" + id = "pq" }, /turf/open/floor/plating/airless, /area/router/aux) "cPj" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 9; - id = "viro_off" + id = "medsci" }, /turf/open/floor/plating/airless, /area/router/aux) "cPk" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "viro_off" + id = "medsci" }, /turf/open/floor/plating/airless, /area/router/aux) "cPl" = ( -/obj/machinery/mass_driver{ - dir = 8; - id = "viro_in"; - name = "Router Driver" +/obj/machinery/mass_driver/pressure_plate{ + dir = 8 }, /turf/open/floor/plating/airless, /area/router/aux) "cPm" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 8; - id = "sq_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) "cPn" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 10; - id = "sq_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) "cPo" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "viro_off" +/obj/machinery/conveyor/auto{ + id = "pq" }, /turf/open/floor/plating/airless, /area/router/aux) "cPp" = ( -/obj/machinery/mass_driver{ - dir = 4; - id = "viro_out"; - name = "Router Driver" +/obj/machinery/mass_driver/pressure_plate{ + dir = 4 }, /turf/open/floor/plating/airless, /area/router/aux) "cPq" = ( -/obj/machinery/conveyor{ +/obj/machinery/conveyor/auto{ dir = 4; - id = "sq_off" + id = "starboard" }, /turf/open/floor/plating/airless, /area/router/aux) @@ -71867,7 +71736,7 @@ id = "MiningConveyorBlastDoor"; name = "Asteroid Mining Load Door" }, -/turf/open/floor/plating/airless, +/turf/open/floor/plating, /area/quartermaster/miningoffice) "cRb" = ( /obj/machinery/computer/cloning, @@ -71932,13 +71801,7 @@ /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ dir = 4 }, -/obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/portable_atmospherics/pump, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/machinery/light, -/turf/open/floor/plasteel/white/corner, +/turf/open/floor/plasteel, /area/engine/atmos) "cRh" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ @@ -71972,8 +71835,8 @@ /obj/item/stock_parts/cell/high{ charge = 100; maxcharge = 15000; - pixel_y = 3; - pixel_x = 4 + pixel_x = 4; + pixel_y = 3 }, /obj/item/stock_parts/cell/high{ charge = 100; @@ -72137,29 +72000,41 @@ name = "Medbay Treatment Center" }) "cVq" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/hallway/primary/aft) "cVO" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/simple/general/visible, +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) "dpO" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ +/obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) +"dwH" = ( +/obj/structure/plasticflaps, +/obj/machinery/conveyor/auto{ + dir = 1; + id = "router" + }, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "engi_out"; + name = "Engineering Router" + }, +/turf/open/floor/plating, +/area/router) "dVR" = ( -/obj/machinery/atmospherics/pipe/manifold4w/general/visible, -/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/simple/violet/visible, /turf/open/floor/plasteel, /area/engine/atmos) "dYm" = ( @@ -72170,12 +72045,12 @@ /turf/open/floor/engine, /area/science/storage) "eCy" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 - }, /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "eIh" = ( @@ -72194,13 +72069,15 @@ }, /area/engine/atmos) "eKM" = ( -/obj/item/radio/intercom{ - name = "Station Intercom (General)"; - pixel_y = -30 - }, /obj/machinery/atmospherics/pipe/manifold/supplymain/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"eSd" = ( +/obj/machinery/mass_driver/pressure_plate{ + id = "security_in" + }, +/turf/open/floor/plating/airless, +/area/router/aux) "eTZ" = ( /obj/effect/turf_decal/tile/green{ dir = 4 @@ -72208,10 +72085,9 @@ /obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible{ +/obj/machinery/atmospherics/pipe/manifold/brown/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "eUF" = ( @@ -72238,24 +72114,25 @@ /turf/open/floor/plasteel, /area/engine/atmos) "fkx" = ( -/obj/machinery/atmospherics/pipe/simple/dark/visible{ - dir = 4 +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 }, +/obj/machinery/portable_atmospherics/scrubber, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/hallway/primary/aft) "fti" = ( -/obj/machinery/atmospherics/components/binary/pump, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/obj/machinery/atmospherics/pipe/manifold/green/visible{ dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) "fui" = ( -/obj/machinery/atmospherics/pipe/simple/violet/visible{ - dir = 4 +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 }, -/turf/open/space/basic, -/area/space) +/obj/machinery/portable_atmospherics/pump, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "fuE" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/orange/visible{ @@ -72271,32 +72148,22 @@ }, /turf/open/floor/plasteel, /area/science/mixing) -"fIw" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/machinery/meter, -/turf/open/floor/plasteel, -/area/engine/atmos) "guK" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/space/basic, /area/space) "gDY" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Fuel Pipe to Incinerator" - }, /obj/machinery/light, -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) "gGG" = ( /obj/structure/lattice, -/obj/machinery/atmospherics/pipe/manifold/orange/visible{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 5 }, /turf/open/space/basic, /area/space/nearstation) @@ -72330,24 +72197,15 @@ /turf/open/floor/plasteel, /area/tcommsat/computer) "hlo" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 1 - }, -/obj/machinery/meter, +/obj/effect/landmark/blobstart, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/quartermaster/miningdock/airless) "hlV" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ - dir = 4 - }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/obj/effect/landmark/blobstart, +/turf/open/floor/plating, +/area/storage/tech) "hDz" = ( -/obj/machinery/space_heater, -/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel, /area/engine/atmos) "hFa" = ( @@ -72358,19 +72216,10 @@ /turf/open/floor/engine, /area/science/storage) "hKC" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 10 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"hMZ" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "Pure to Port" +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "hXk" = ( @@ -72384,17 +72233,10 @@ /obj/machinery/atmospherics/pipe/manifold/orange/visible, /turf/open/space/basic, /area/space/nearstation) -"iAW" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "iQY" = ( /obj/machinery/atmospherics/pipe/manifold/yellow/visible{ dir = 4 }, -/obj/structure/closet/firecloset, /turf/open/floor/plasteel, /area/engine/atmos) "jiZ" = ( @@ -72403,19 +72245,8 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos) -"jml" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - layer = 2.4 - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel, -/area/engine/atmos) "jon" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ +/obj/machinery/atmospherics/pipe/simple/violet/visible{ dir = 4 }, /turf/open/floor/plasteel, @@ -72435,16 +72266,6 @@ /area/engine/secure_construction{ name = "Engineering Construction Area" }) -"jXo" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 10 - }, -/turf/closed/wall/r_wall, -/area/engine/atmos) -"kxw" = ( -/obj/machinery/atmospherics/pipe/simple/violet/visible, -/turf/open/space/basic, -/area/space) "kzb" = ( /obj/machinery/atmospherics/pipe/manifold/orange/hidden{ dir = 4 @@ -72455,16 +72276,12 @@ /obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 4 }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Mix to Engine" - }, +/obj/machinery/atmospherics/pipe/simple/violet/visible, /turf/open/floor/plasteel, /area/engine/atmos) "lcD" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "Air to Port" +/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -72472,8 +72289,9 @@ /obj/machinery/light{ dir = 1 }, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 8 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "Mix to Filter" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -72487,7 +72305,10 @@ name = "Engine Room" }) "mqB" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Air to Ports" + }, /turf/open/floor/plasteel, /area/engine/atmos) "mxW" = ( @@ -72497,13 +72318,12 @@ }, /turf/open/space/basic, /area/space/nearstation) -"mBP" = ( -/obj/effect/landmark/xeno_spawn, -/turf/open/floor/plasteel, -/area/science/mixing) "mEa" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, -/obj/machinery/meter, +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "Air to Distro" + }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "mIm" = ( @@ -72530,36 +72350,14 @@ /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, /area/tcommsat/computer) -"mNN" = ( -/obj/machinery/space_heater, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"ntC" = ( -/obj/machinery/atmospherics/components/binary/pump{ - name = "Port to Fuel Pipe" - }, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "nvn" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 1 - }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) "nAF" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "Mix to Port" - }, +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "nBM" = ( @@ -72570,26 +72368,9 @@ }, /turf/open/floor/plating, /area/engine/atmos) -"nEX" = ( -/obj/machinery/atmospherics/pipe/simple/dark/visible{ - dir = 9 - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"nLV" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) "ony" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ +/obj/machinery/atmospherics/pipe/manifold/brown/visible{ dir = 4 }, /turf/open/floor/plating, @@ -72618,6 +72399,13 @@ /obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"pZq" = ( +/obj/structure/disposalpipe/sorting/mail/flip{ + dir = 8; + sortType = 12 + }, +/turf/open/floor/plating/airless, +/area/router/aux) "qeq" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -72625,41 +72413,72 @@ }, /turf/open/space/basic, /area/space/nearstation) -"qgO" = ( -/obj/machinery/portable_atmospherics/scrubber, -/turf/open/floor/plasteel, -/area/engine/atmos) "qlJ" = ( /obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/supplymain/visible, /turf/open/space/basic, /area/space/nearstation) -"qvB" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater{ - dir = 8 +"qGi" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" }, -/turf/open/floor/plasteel, -/area/engine/atmos) +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/turf/closed/wall/r_wall, +/area/engine/engine_smes{ + name = "Power Monitoring" + }) "qHL" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 6 }, /turf/open/floor/plating, /area/engine/atmos) -"qWY" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - name = "Waste In" +"qMN" = ( +/obj/structure/plasticflaps, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "starboardbelthell_out"; + name = "Belt Hell" }, +/turf/open/floor/plating, +/area/router) +"qWY" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "rdF" = ( -/obj/machinery/atmospherics/pipe/simple/dark/visible{ - dir = 6 - }, +/obj/machinery/atmospherics/pipe/simple/dark/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"rke" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/closed/wall/r_wall, +/area/engine/engine_smes{ + name = "Power Monitoring" + }) +"rqk" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/closed/wall/r_wall, +/area/engine/engine_smes{ + name = "Power Monitoring" + }) +"rOE" = ( +/obj/structure/plasticflaps, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "eva_in"; + name = "EVA Router" + }, +/turf/open/floor/plating, +/area/router) "rTW" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/violet/visible{ @@ -72673,22 +72492,28 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"sdp" = ( -/obj/structure/reagent_dispensers/foamtank, -/turf/open/floor/engine, -/area/engine/secure_construction{ - name = "Engineering Construction Area" - }) -"sHB" = ( -/obj/machinery/atmospherics/pipe/manifold/orange/visible{ - dir = 4 +"sky" = ( +/obj/machinery/conveyor/auto{ + dir = 4; + id = "pq" }, +/turf/open/floor/plating/airless, +/area/router/aux) +"sAm" = ( +/obj/structure/plasticflaps, +/obj/machinery/door/poddoor{ + id = "airbridge_out"; + name = "Airbridge Router" + }, +/turf/open/floor/plating, +/area/engine/workshop) +"sHB" = ( +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) "sRD" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible, +/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/engine/atmos) "sVC" = ( @@ -72699,6 +72524,15 @@ /obj/machinery/atmospherics/pipe/simple/supplymain/visible, /turf/open/space/basic, /area/space/nearstation) +"tff" = ( +/obj/structure/plasticflaps, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "portbelthell_out"; + name = "Airbridge Router" + }, +/turf/open/floor/plating, +/area/router) "tjb" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ @@ -72714,12 +72548,15 @@ /obj/machinery/atmospherics/pipe/simple/violet/visible, /turf/open/space/basic, /area/space/nearstation) -"tuF" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 6 +"tsU" = ( +/obj/structure/plasticflaps, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor{ + id = "engi_in"; + name = "Engineering Router" }, -/turf/closed/wall/r_wall, -/area/engine/atmos) +/turf/open/floor/plating, +/area/router) "tyI" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ dir = 4 @@ -72728,36 +72565,28 @@ /area/engine/atmos) "tXV" = ( /obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - layer = 2.4 + name = "Pure to Ports" }, /turf/open/floor/plasteel, /area/engine/atmos) "tZj" = ( -/obj/structure/tank_dispenser{ - pixel_x = -1 - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 6 - }, +/obj/machinery/atmospherics/pipe/manifold/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "tZC" = ( -/obj/machinery/atmospherics/pipe/manifold4w/orange/visible, -/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/manifold/orange/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "urj" = ( -/obj/machinery/atmospherics/pipe/simple/general/hidden{ - dir = 8; - icon_state = "intact" - }, /obj/structure/cable{ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ dir = 4 }, +/obj/effect/landmark/xeno_spawn, /turf/open/floor/plasteel/dark, /area/bridge) "uwK" = ( @@ -72778,27 +72607,18 @@ /turf/open/floor/plasteel, /area/engine/atmos) "uVD" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 5 +/obj/machinery/atmospherics/pipe/simple/brown/visible{ + dir = 9 }, /turf/open/floor/plasteel, /area/engine/atmos) "vcb" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 10 +/obj/machinery/atmospherics/pipe/simple/brown/visible, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) -"vsO" = ( -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/closed/wall/r_wall, -/area/engine/atmos) "vxU" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/structure/extinguisher_cabinet{ @@ -72818,7 +72638,9 @@ /turf/open/space/basic, /area/space/nearstation) "wWH" = ( -/obj/machinery/atmospherics/pipe/manifold4w/general/visible, +/obj/machinery/atmospherics/components/unary/thermomachine/heater{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "xcO" = ( @@ -72828,24 +72650,8 @@ /obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, /obj/machinery/atmospherics/components/binary/pump{ - dir = 0; - name = "Mix Outlet Pump" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"xjk" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"xkC" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 + name = "Mix to Ports" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -72862,9 +72668,8 @@ /turf/closed/wall, /area/quartermaster/storage) "xCy" = ( -/obj/machinery/atmospherics/components/binary/pump, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/violet/visible{ + dir = 9 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -92048,7 +91853,7 @@ aaa aaa bcy bdf -mBP +bdf crJ blT bqJ @@ -92763,7 +92568,7 @@ auL aAc aGq aJX -bdE +cQQ cen aGq cvK @@ -95885,7 +95690,7 @@ bhS beJ beJ bGI -bXP +aaU aaa aaa aaa @@ -96142,7 +95947,7 @@ bdg beJ beJ bGI -bXV +aaU aaa aaa aaa @@ -96399,7 +96204,7 @@ bdg beJ ceI bGI -bXV +aaU aaa aaa aaa @@ -96656,7 +96461,7 @@ bdg cmd beT bGI -bXV +aaU aaa aaa aaa @@ -96913,7 +96718,7 @@ bdg beJ bfd bdg -bXV +aaU aaa aaa ceD @@ -97170,7 +96975,7 @@ bdg beJ bfd bdg -bXV +aaU aaa bdg buB @@ -97427,7 +97232,7 @@ bdg caW bJy bdg -bXV +aaU aaU bdg bjg @@ -97684,7 +97489,7 @@ bdg beJ bfd bGI -bYd +bGI bGI bGI bzb @@ -97941,7 +97746,7 @@ beJ beJ bfd blc -bYP +beJ coS aXc aXc @@ -98116,7 +97921,7 @@ aak aak aak aak -aak +eSd aaa aaa aaa @@ -98198,7 +98003,7 @@ bzB bgA bWf bXm -bZQ +bgA bWq ccN cei @@ -98263,10 +98068,10 @@ aaa aaa aaa aaa -cPf -cPf -cPf -cPf +cPo +cPo +cPo +cPo cPo abp aaa @@ -98524,7 +98329,7 @@ abM abR abM abM -cPo +sky aaU aaa aaa @@ -98781,7 +98586,7 @@ cPg cPi cPj abR -cPo +sky aaU aaa aaa @@ -99038,7 +98843,7 @@ aaa aaa cPk abR -cPo +sky aaU aaa aaa @@ -99399,7 +99204,7 @@ aaa aaU aar abM -acf +cPp aaU aaa aaa @@ -99661,12 +99466,12 @@ aaU aaa aaa aaa +adM adj adj adj adj -adj -adj +adM aaU aaU aaa @@ -99918,12 +99723,12 @@ aaU aaa aaa aaa -adj +adM aeC afv adF agM -adj +adM aaa aaU aaU @@ -100175,12 +99980,12 @@ aaU aaa aaa aaa -adj +adM aeR afx aga afI -adj +adM aaa aaa aaU @@ -100432,20 +100237,20 @@ aaU add adC adC -adC +aap aeS adj adj agN +aiX ahL ahL -ahL -ahL +aaq afD afQ age age -agy +age age age afC @@ -100697,8 +100502,8 @@ aad aad aad aad -adM -aaj +aiM +agy aaI ami akX @@ -100955,7 +100760,7 @@ aad aad aad aiM -aaj +azO aaI aco akX @@ -101020,7 +100825,7 @@ bRf cCG cCH cCG -bUw +bgi bVJ cCG bWF @@ -101277,7 +101082,7 @@ bcf bcf bCs bcf -bwU +bhI bCD bcf bcf @@ -101469,7 +101274,7 @@ aad aad aad aiM -aap +aco abd abT akX @@ -101725,8 +101530,8 @@ aad aad aad aad -adM -aaq +aiM +aco aaI acF akX @@ -101982,7 +101787,7 @@ agO adj adj adj -adM +aiM aat abf acF @@ -103105,7 +102910,7 @@ aaa cuR cGa cuR -cNm +cNn cuR cIH cgv @@ -103927,7 +103732,7 @@ aaa aaa aaa aaa -aaa +cpB ckl ckl ckl @@ -105619,7 +105424,7 @@ aYi baU bdh aOJ -aog +bdE aog axV aHV @@ -106149,7 +105954,7 @@ aaU aaa btT bzE -btZ +rOE btT aaa aaa @@ -106188,7 +105993,7 @@ aaa aaa ctG cIh -ctJ +sAm ctG cIy bjm @@ -106925,7 +106730,7 @@ bKl bQW bUp cci -btZ +tff aSq bgh bIY @@ -107163,7 +106968,7 @@ bdP bfF bha bdP -abp +aOJ aPN bes aaU @@ -107208,8 +107013,8 @@ aPg aPg cet bpL -bBO -bBO +bpL +rqk bBO bBO ctG @@ -107228,7 +107033,7 @@ bZq bZh cEE bpD -cmL +bpD cyS byQ byQ @@ -107420,7 +107225,7 @@ bdW bfJ bhc bdP -abp +aOJ aPN bes aaU @@ -107466,7 +107271,7 @@ cdV cdV bpN bCa -bSo +bSp bSv cfl ctX @@ -107677,7 +107482,7 @@ bdY bfM bhg bdP -abp +aOJ aPN bey aaU @@ -107934,7 +107739,7 @@ bdP bdP bhl bdP -abp +aOJ aPN bes aaU @@ -107978,7 +107783,7 @@ cmf cnK cnK cdV -bBO +rke bUB bSq bVf @@ -108191,7 +107996,7 @@ aaU aaU cuA cuy -bcc +blD bcO bes aaU @@ -108448,7 +108253,7 @@ aaa aaa aaa aaU -brs +aQq aPR cux aaU @@ -108492,7 +108297,7 @@ cmE cok cok cdV -bBO +rke bPv cBd cfi @@ -108705,7 +108510,7 @@ aaa aaa aaa aaU -brs +aQq aQp cux aaU @@ -108749,7 +108554,7 @@ cmG coT cpL cpZ -bBO +qGi cxd cBd cfj @@ -108962,9 +108767,9 @@ aaU aaU aaU aaU -abp -aQq -bes +aUq +bmO +bcc aaU aaa aaa @@ -109006,7 +108811,7 @@ cmY cdV cdV cdV -bBO +qGi bSm cBk cfk @@ -109066,7 +108871,7 @@ aaa aaa aaa aaa -aaa +cpB aaa ckl ckl @@ -109219,9 +109024,9 @@ aaa aaa aaa aaU -abp +aUq aQr -bes +bcc aaU aaa aaa @@ -109239,7 +109044,7 @@ bBv bXM ccn ccA -ccy +dwH aTl bsz cdG @@ -109263,7 +109068,7 @@ cks crv crx aeI -bBO +rke bSn cBl bSn @@ -109476,7 +109281,7 @@ aaa aaa aaa aaU -abp +aUq aQr beD cuy @@ -109496,7 +109301,7 @@ bUc bXM cco ccE -btZ +tsU aTl bsz cdU @@ -109534,7 +109339,7 @@ cNt beZ cIS coz -bty +fkx bBl aaU aaU @@ -110046,9 +109851,9 @@ cJy cNg cNs cIB -cIM -bXX -bty +cMG +cVq +fui bBl aaU bIm @@ -110262,7 +110067,7 @@ aaa btT bBX btT -btZ +qMN btT aaa aaU @@ -110303,9 +110108,9 @@ cvi cuN cNv bhT -cIM -bXX -bty +cMG +cVq +fui bzr byT cfc @@ -110799,12 +110604,12 @@ aCZ aRG aOl aOV -avQ +bSo cmX aRp bkJ aUf -aeI +ciG bnp cmO cfU @@ -112870,7 +112675,7 @@ biV cKg cLn cLz -bmz +cLz biV cdP bXX @@ -113177,7 +112982,7 @@ aaa aaa aaa aaa -aaa +cpB aaa aaa ckl @@ -113336,7 +113141,7 @@ cAM bCP boA aYC -brf +att att att att @@ -114066,7 +113871,7 @@ aaa aaU aio akZ -biO +aKe bEt bEA aik @@ -114643,7 +114448,7 @@ aaa bsz anr bcI -sdp +bgw bUX bgw uwK @@ -116226,7 +116031,7 @@ btz bPm bxH bSf -bzd +hlV bQD bxH bxH @@ -116873,7 +116678,7 @@ aaa aaa aaa aaU -cnM +cPl abM acj aaU @@ -117470,8 +117275,8 @@ aaa aaa aaa aaa -bgi -fui +bMp +bJv aaa cwK aaa @@ -117727,8 +117532,8 @@ aZG aaa aaa aaa -bgi -fui +bMp +bJv aaa cwI aaa @@ -117984,8 +117789,8 @@ aaa aaa aaa aaa -bgi -fui +bMp +bJv aaa cwK aaa @@ -118026,7 +117831,7 @@ bYh bYn bYn bYE -cni +bYn cyf cgy bIz @@ -118488,16 +118293,16 @@ bzO caD bzn bjz -ciG +ciq bAK ciV aMI aaa bJj bLS -kxw -kxw -kxw +bHg +bHg +bHg bPA wPS aaa @@ -118931,7 +118736,7 @@ aaa aaU aav abM -acz +cPp aaU aaa aaa @@ -118961,7 +118766,7 @@ avz awx axU ayL -azO +azU aAu awp aCP @@ -119533,10 +119338,10 @@ cPD bVE cbT cww -bhI -bhI +cww +cww can -bhI +cww aaa anr aaa @@ -119786,15 +119591,15 @@ bNb bPL cwB cwB -cwB +hDz bVX eKM +bZQ +cww cww -bhI -bhI cao -bhI -bhI +cww +cww anr aaa aaU @@ -120041,13 +119846,13 @@ cww bjE bNq bQK -qgO +cwB chO cpN bWG cRg -jiZ -bhI +cmL +cww cLY cap cMt @@ -120301,14 +120106,14 @@ bNd bNE cww cpO -bWG -cJo +bYP +cRg cMH -bhI -cLZ +cww +cMb caq -cLZ -bhI +cMb +cww anr aaa aaU @@ -120557,15 +120362,15 @@ cww cww cww cww -cww +cLm cIs tyI -cMJ +cww cLX cMa cMj cMu -cMG +jiZ anr aaU aaU @@ -120812,17 +120617,17 @@ pgu pgu pgu gGG -vsO +cww chS cpQ cfM cbU -jXo +cww cLm cMb cas cMb -cMH +cMJ anr aaa aaa @@ -121069,9 +120874,9 @@ aXx aXx aXx bfW -tuF +cww lRy -fti +cMl cfP mEa cLV @@ -121326,7 +121131,7 @@ bca cat cKX bQN -nLV +cLb cLd fti cfT @@ -121337,7 +121142,7 @@ chx chM gDY jiZ -hlV +anr aaa aaa aaU @@ -121595,7 +121400,7 @@ rUl cMw cfs cMP -aaa +cMi aaa aaU aaa @@ -121838,14 +121643,14 @@ aXx bca bca cKQ -cKY -bQO +biO +bmz ony xcO hKC cVO -sRD -cMe +nAF +cni cai rdF cMk @@ -122099,12 +121904,12 @@ aXx bfW cww bUa -cMr +brf sRD -cMo +nAF cgz -cai -fkx +cJH +cwB cMl cMx cMJ @@ -122356,13 +122161,13 @@ cKX bQN cLb cLe -cMo -hMZ +bXP +sRD nAF lcD -cai -fkx -mNN +cwB +cwB +cwB cLo nBM cfD @@ -122613,12 +122418,12 @@ bZR bfW cwA cLf -cMo -iAW -fIw +bXV +sRD +nAF wWH -ntC -nEX +cwB +cwB hDz cLp oMB @@ -122870,11 +122675,11 @@ cKY bQO cLc eIh -car +bYd tXV tZj -jml -cVq +cwB +cwB cMc cMm cMy @@ -123128,10 +122933,10 @@ bfW cww bhJ cMo -iAW +cwB cJu -iAW -cJH +cwB +cwB cMd cMn cMz @@ -123385,10 +123190,10 @@ bQN cLb cLh cMo -iAW -cJu -hlo -cJH +cwB +jon +cwB +cwB cMe cMo cLq @@ -123643,9 +123448,9 @@ bWK cLi xKr nvn -cJu -iAW -cJH +jon +cwB +cwB cMe cMo cMA @@ -123899,10 +123704,10 @@ cLa cLc fgS car -iAW +cwB jon -xjk -cai +cwB +cwB cMg cMq cMB @@ -124159,7 +123964,7 @@ kOG dVR xCy sHB -xkC +cwB cMe cMr cMC @@ -124413,7 +124218,7 @@ bQS cLb cLj cMo -qvB +cwB cgh cgA chq @@ -124931,7 +124736,7 @@ prx vxU cLW ccG -cMi +prx iQY cMF cMO @@ -125728,7 +125533,7 @@ cNB cNB cNB cNG -cNN +hlo cNT cNy cNX @@ -125941,7 +125746,7 @@ aaa aaa aaa aaU -cbS +cPq abM ccH aaU @@ -126125,9 +125930,9 @@ aaa aaa aaa aaU -abF +cPl abM -acA +cPq aaU aaa aaa @@ -126198,9 +126003,9 @@ aaa aaa aaa aaU -cbS +cPq abR -ccJ +cPm aaU aaa aaa @@ -126382,9 +126187,9 @@ aaa aaa aaa aaU -abJ +cPm abR -acA +cPq aaU aaU aaU @@ -126639,12 +126444,12 @@ aaa aaa aaa aaU -abJ +cPm abR acB -adc -adc -adL +cPd +cPd +cdq aaa aaa aaa @@ -126709,14 +126514,14 @@ aaU aaa aaa aaa -bGK -bGK +cPd +cPd bUe ccc abR -aaY +pZq cdb -bGK +cPd cdq aaa aaa @@ -126896,7 +126701,7 @@ aaa aaa aaa aaU -abJ +cPm abM abR abM @@ -127153,12 +126958,12 @@ aaa aaa aaa abp -abJ -abZ -abZ -abZ -abZ -abZ +cPm +cPh +cPh +cPh +cPh +cPh aaa aaa aaa @@ -127223,15 +127028,15 @@ aaU aaa aaa aaa -bGP -bNo -bNo +cPe +cPh +cPh ccf ccs ccP cdi -bNo -bNo +cPh +cPh aaa aaa aaa diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 53ca9a72b0..78bb797a56 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -509,8 +509,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/firealarm{ dir = 4; - pixel_x = -24; - pixel_y = 0 + pixel_x = -24 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index fdc313c30a..6f0636d3cb 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -982,11 +982,11 @@ /area/security/prison) "aci" = ( /obj/structure/lattice/catwalk, -/obj/machinery/door/airlock/external{ - req_one_access_txt = "13,8" +/obj/structure/cable{ + icon_state = "0-2" }, /turf/open/space, -/area/maintenance/starboard/fore) +/area/solar/starboard/fore) "acj" = ( /obj/machinery/light/small{ dir = 1 @@ -3123,6 +3123,17 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"afQ" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) "afR" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 @@ -5480,15 +5491,17 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "akd" = ( -/turf/open/space, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, /area/maintenance/solars/starboard/fore) "ake" = ( -/obj/structure/cable{ - icon_state = "0-2" - }, -/obj/structure/lattice/catwalk, /turf/open/space, -/area/maintenance/solars/starboard/fore) +/area/space) "akf" = ( /obj/machinery/conveyor{ dir = 1; @@ -6294,11 +6307,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) "alx" = ( @@ -6997,6 +7005,10 @@ /obj/structure/window/reinforced, /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) +"amB" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/maintenance/port) "amC" = ( /obj/structure/chair{ dir = 4 @@ -7014,6 +7026,17 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/crew_quarters/fitness/recreation) +"amF" = ( +/obj/machinery/door/airlock/maintenance/abandoned{ + name = "Storage Room"; + req_access_txt = "12" + }, +/obj/structure/barricade/wooden, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"amG" = ( +/turf/closed/wall, +/area/crew_quarters/fitness/pool) "amH" = ( /obj/machinery/door/airlock/external{ req_one_access_txt = "13,8" @@ -7086,14 +7109,9 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "amN" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, +/obj/effect/turf_decal/stripes/corner, /turf/open/floor/plating, -/area/maintenance/solars/starboard/fore) +/area/crew_quarters/fitness/pool) "amO" = ( /obj/machinery/light/small{ dir = 8 @@ -7158,6 +7176,13 @@ icon_state = "platingdmg2" }, /area/maintenance/port) +"amV" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "amW" = ( /obj/structure/table/reinforced, /obj/item/folder, @@ -7438,6 +7463,9 @@ /obj/item/paper, /turf/open/floor/plasteel, /area/security/main) +"anz" = ( +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "anA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/disposalpipe/segment, @@ -7898,6 +7926,10 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/security/warden) +"aov" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "aow" = ( /obj/machinery/door/firedoor, /obj/structure/cable/yellow{ @@ -8616,6 +8648,12 @@ }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"apP" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "apQ" = ( /obj/structure/reagent_dispensers/peppertank{ pixel_x = 32 @@ -8682,6 +8720,9 @@ /obj/item/assembly/flash/handheld, /turf/open/floor/plasteel, /area/security/main) +"apX" = ( +/turf/open/pool, +/area/crew_quarters/fitness/pool) "apY" = ( /obj/structure/table, /obj/item/folder/red, @@ -8747,6 +8788,12 @@ }, /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) +"aqe" = ( +/obj/machinery/pool/filter{ + pixel_y = 16 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) "aqf" = ( /obj/structure/closet/lasertag/blue, /obj/effect/turf_decal/tile/neutral{ @@ -9248,6 +9295,12 @@ }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"arh" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "ari" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -9478,6 +9531,14 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/dorms) +"arF" = ( +/obj/structure/pool/ladder{ + dir = 8; + icon_state = "ladder"; + pixel_x = 4 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) "arG" = ( /obj/structure/closet, /obj/item/storage/box/lights/mixed, @@ -10167,6 +10228,13 @@ /obj/structure/chair, /turf/open/floor/plasteel/grimy, /area/security/main) +"asN" = ( +/obj/machinery/light/built{ + icon_state = "tube-empty"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "asO" = ( /obj/item/paper_bin{ pixel_x = -3; @@ -10466,6 +10534,10 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"atw" = ( +/obj/machinery/pool/drain, +/turf/open/pool, +/area/crew_quarters/fitness/pool) "atx" = ( /obj/structure/cable/yellow{ icon_state = "2-4" @@ -10536,6 +10608,12 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"atC" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "atD" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -10558,6 +10636,10 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"atF" = ( +/obj/machinery/pool/controller, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "atG" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -10601,6 +10683,23 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"atJ" = ( +/obj/structure/sign/poster/ripped{ + pixel_y = 32 + }, +/obj/structure/table, +/obj/structure/cable/yellow{ + icon_state = "0-2" + }, +/obj/item/light/tube, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/fitness/pool"; + dir = 4; + name = "Pool APC"; + pixel_x = 26 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "atK" = ( /obj/machinery/computer/prisoner/gulag_teleporter_computer{ dir = 1 @@ -11069,6 +11168,24 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"auQ" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"auR" = ( +/obj/structure/pool/Lboard, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"auS" = ( +/obj/structure/pool/Rboard, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) +"auT" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "auU" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -11659,6 +11776,50 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"avU" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"avV" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance/abandoned, +/obj/structure/barricade/wooden, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"avW" = ( +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"avX" = ( +/obj/structure/chair{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "avY" = ( /obj/machinery/door/airlock/external{ name = "Labor Camp Shuttle Airlock"; @@ -11932,6 +12093,11 @@ }, /turf/open/floor/plasteel/dark, /area/security/brig) +"awA" = ( +/obj/structure/closet/athletic_mixed, +/obj/item/toy/poolnoodle/blue, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "awB" = ( /obj/structure/reagent_dispensers/watertank, /obj/item/storage/box/lights/mixed, @@ -12053,6 +12219,18 @@ /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, /area/maintenance/port/fore) +"awN" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"awO" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "awP" = ( /obj/item/clothing/gloves/color/rainbow, /obj/item/clothing/shoes/sneakers/rainbow, @@ -12105,6 +12283,25 @@ "awW" = ( /turf/closed/wall/r_wall, /area/security/nuke_storage) +"awX" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"awY" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/aft) "awZ" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 8 @@ -54179,21 +54376,6 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/port/aft) -"cek" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) -"cel" = ( -/obj/structure/sign/warning/vacuum/external{ - pixel_y = 32 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) "cem" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -54885,16 +55067,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) -"cfB" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) "cfC" = ( /obj/item/trash/pistachios, /obj/structure/closet, @@ -55509,13 +55681,6 @@ /obj/structure/reagent_dispensers/cooking_oil, /turf/open/floor/plasteel/showroomfloor, /area/crew_quarters/kitchen) -"cgG" = ( -/obj/structure/closet/emcloset/anchored, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) "cgH" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -81287,19 +81452,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) -"gsT" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plating, -/area/solar/starboard/aft) "gEk" = ( /obj/structure/cable/yellow{ icon_state = "2-8" @@ -97098,15 +97250,15 @@ bTp bUP bVS bXv -bYC -bYC -bYC -bYC -aaa -aaf -aaa -aaa -aaf +bTn +bTn +bTn +bTn +amG +auQ +auQ +amG +amG aaf aaf aaa @@ -97356,16 +97508,16 @@ bTn bTn bTn bTn +amN +anz +arh +asN +anz +arh +awN +amG aaa -aaf -aaa -aaa -aaf -aaf -aaf -aaf -aaa -aaa +lMJ aaa aaa aaa @@ -97609,20 +97761,20 @@ bzx alC mEe alK -aob -aob dix -alK -aaf -aaf -aaf -aaf -aaf -aaa -aaa -aaf -aaa +aob +amB +amF +amV +apX +apX +apX +apX +apX +awO +auQ aaa +lMJ aaa aaa aaa @@ -97869,17 +98021,17 @@ bTr bUQ bVT aob -alK -aaa -aaf -aaa -aaa -aaa -aaa -aaa -aaf -aaa +amG +anz +aqe +apX +atw +apX +apX +anz +auQ aaa +lMJ aaa aaa aaa @@ -98126,15 +98278,15 @@ alK bJs bVU bXx -alK -aaa -aaf -aaf -ack -aaf -aaf -aaf -aaf +amG +aov +apX +arF +apX +auR +apX +anz +auQ aaf aaf aaf @@ -98383,15 +98535,15 @@ alK bUR alK alK -alK -aaa -aaf -aaa -ack -aaf -aaa -aaa -aaa +amG +apP +anz +anz +atC +auS +atC +awX +amG aaa aaa aaa @@ -98640,15 +98792,15 @@ alK alK alK bXy -dux -dux -dux -dux -cek -dux -dux -dux -dux +amG +amG +amG +amG +atF +auT +avX +amG +amG ckN ckN ckN @@ -98900,11 +99052,11 @@ bXz bYE bYE cbp -dux -cel -bUU -cgG -dux +amG +atJ +avU +awA +amG cjp ckO cmg @@ -99157,11 +99309,11 @@ dux dux dux cbq -dux -dux -cek -dux -dux +amG +amG +avV +amG +amG cjq ckP ckS @@ -99416,7 +99568,7 @@ dux cbr bYE cem -cfB +avW cbp dux diE @@ -119752,7 +119904,7 @@ cJf dvY aaa dbN -gsT +awY dbN aaa aaa @@ -124021,7 +124173,7 @@ aaf aaa aaf dnh -aci +amH dnh ape dnS @@ -126848,7 +127000,7 @@ aaa aaf aaa aaa -akd +ake alv apm apm @@ -127103,7 +127255,7 @@ aaf aaa aaa aaf -akd +alv alv alv alv @@ -127359,10 +127511,10 @@ abR abR abR abR -abR -ake +aci +afQ +akd alw -amN sGh apo aqz @@ -127617,7 +127769,7 @@ aaf aaa aaa aaf -akd +alv alv alv alv @@ -127876,7 +128028,7 @@ aaa aaf aaa aaa -akd +ake alv apm apm diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index db44dfb92a..668bcead78 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -1240,13 +1240,26 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/hop) "abL" = ( -/obj/structure/sign/warning/securearea, -/turf/closed/wall, -/area/maintenance/starboard/fore) +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/effect/turf_decal/box, +/obj/machinery/power/solar{ + id = "forestarboard"; + name = "Fore-Starboard Solar Array" + }, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/starboard/fore) "abM" = ( -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/starboard/fore) +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) "abN" = ( /obj/structure/sign/warning/vacuum, /turf/closed/wall, @@ -1602,15 +1615,16 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/hop) "acu" = ( -/obj/structure/sign/warning/vacuum{ - pixel_x = 32; - pixel_y = 32 +/obj/structure/cable{ + icon_state = "0-8" }, -/obj/effect/turf_decal/delivery, -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/landmark/xeno_spawn, -/turf/open/floor/plasteel, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/box, +/obj/machinery/power/solar{ + id = "forestarboard"; + name = "Fore-Starboard Solar Array" + }, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/starboard/fore) "acv" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -2131,20 +2145,12 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/hop) "adm" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "0-2" +/obj/structure/sign/warning/securearea{ + pixel_x = 32; + pixel_y = -32 }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/starboard/fore"; - dir = 4; - name = "Starboard Bow Maintenance APC"; - pixel_x = 26 - }, -/turf/open/floor/plating{ - icon_state = "platingdmg2" - }, -/area/maintenance/starboard/fore) +/turf/open/space/basic, +/area/space) "adn" = ( /turf/closed/wall, /area/quartermaster/storage) @@ -2157,15 +2163,9 @@ /turf/closed/wall, /area/quartermaster/storage) "adq" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/structure/closet/emcloset/anchored, -/obj/machinery/light/small{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/fore) +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/solar/starboard/fore) "adr" = ( /obj/structure/cable{ icon_state = "4-8" @@ -2194,20 +2194,12 @@ /turf/open/floor/plating, /area/engine/supermatter) "adt" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-4" }, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, -/area/maintenance/starboard/fore) +/turf/open/space/basic, +/area/solar/starboard/fore) "adu" = ( /turf/closed/wall, /area/quartermaster/qm) @@ -2393,13 +2385,18 @@ /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "adM" = ( -/obj/structure/sign/warning/vacuum{ - pixel_x = 32; - pixel_y = 32 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) "adN" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/item/radio/intercom{ @@ -2597,11 +2594,12 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "aef" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-8" }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/turf/open/space/basic, +/area/solar/starboard/fore) "aeg" = ( /obj/machinery/conveyor{ dir = 8; @@ -3099,6 +3097,7 @@ "aeS" = ( /obj/structure/closet/crate, /obj/effect/turf_decal/delivery, +/obj/item/toy/figure/cargotech, /turf/open/floor/plasteel, /area/quartermaster/storage) "aeT" = ( @@ -5559,7 +5558,8 @@ icon_state = "plant-21" }, /obj/machinery/camera{ - c_tag = "Chemistry" + c_tag = "Chemistry"; + network = list("ss13","medbay") }, /obj/effect/turf_decal/tile/yellow{ dir = 8 @@ -6262,12 +6262,8 @@ /turf/open/floor/plasteel, /area/medical/medbay/zone3) "ajP" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/landmark/start/research_director, -/turf/open/floor/plasteel, -/area/science/mixing) +/turf/closed/wall/r_wall, +/area/crew_quarters/heads/hor) "ajQ" = ( /obj/effect/turf_decal/loading_area{ dir = 8 @@ -7432,7 +7428,8 @@ dir = 4 }, /obj/machinery/camera{ - c_tag = "Chief Engineer's Office" + c_tag = "Chief Engineer's Office"; + network = list("ss13","engine") }, /mob/living/simple_animal/parrot/Poly, /turf/open/floor/plasteel/dark, @@ -12020,18 +12017,28 @@ }, /area/engine/atmos) "asH" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Atmospherics North East"; - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, -/turf/open/floor/plasteel/checker, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Plasma to Pure" + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/camera{ + c_tag = "Atmospherics North"; + network = list("ss13","engine") + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, /area/engine/atmos) "asI" = ( /obj/structure/sign/warning/vacuum{ @@ -15126,7 +15133,8 @@ "axu" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /obj/machinery/camera{ - c_tag = "Atmospherics Monitoring" + c_tag = "Atmospherics Monitoring"; + network = list("ss13","engine") }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -15702,6 +15710,10 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/item/toy/figure/atmos{ + pixel_x = -2; + pixel_y = 2 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -18253,23 +18265,25 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "aCF" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 4; - name = "Air to External Air Ports" +/obj/effect/decal/cleanable/dirt, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = 24 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/camera{ - c_tag = "Atmospherics South East"; - dir = 1 + c_tag = "Atmospherics North West"; + dir = 4; + network = list("ss13","engine") }, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/turf/open/floor/plasteel/dark, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/turf/open/floor/plasteel/dark/corner{ + dir = 1 + }, /area/engine/atmos) "aCG" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -19324,7 +19338,8 @@ }, /obj/machinery/camera{ c_tag = "Engineering Secure Storage"; - dir = 4 + dir = 4; + network = list("ss13","engine") }, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, @@ -20192,7 +20207,8 @@ }, /obj/machinery/camera{ c_tag = "SMES Access"; - dir = 8 + dir = 8; + network = list("ss13","engine") }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -20226,23 +20242,22 @@ /turf/open/floor/plasteel, /area/engine/engineering) "aFB" = ( -/obj/machinery/shower{ - dir = 8; - name = "emergency shower" +/obj/structure/cable{ + icon_state = "0-8" }, -/obj/machinery/light/small, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ +/obj/machinery/power/terminal{ dir = 4 }, +/obj/effect/turf_decal/delivery, +/obj/machinery/airalarm{ + pixel_y = 24 + }, /obj/machinery/camera{ - c_tag = "Engineering Access"; - dir = 8 + c_tag = "Starboard Bow Solar"; + network = list("ss13","engine") }, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/engine/engineering) +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) "aFC" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 4 @@ -20787,7 +20802,8 @@ /obj/machinery/light, /obj/machinery/camera{ c_tag = "Engineering Foyer"; - dir = 1 + dir = 1; + network = list("ss13","engine") }, /obj/machinery/power/apc{ areastring = "/area/engine/break_room"; @@ -21227,22 +21243,20 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "aGY" = ( -/obj/structure/bed/dogbed/runtime, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/delivery, -/obj/structure/sign/poster/official/medical_green_cross{ - pixel_x = -32 - }, /obj/machinery/camera{ - c_tag = "CMO's Office"; - dir = 4 + c_tag = "Genetics Cloning"; + dir = 4; + network = list("ss13","medbay") }, -/mob/living/simple_animal/pet/cat/Runtime, -/turf/open/floor/plasteel/dark, -/area/crew_quarters/heads/cmo) +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aGZ" = ( /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -21343,7 +21357,8 @@ "aHg" = ( /obj/machinery/camera{ c_tag = "Gravity Generator Room"; - dir = 8 + dir = 8; + network = list("ss13","engine") }, /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ @@ -22188,7 +22203,8 @@ pixel_x = -32 }, /obj/machinery/camera{ - c_tag = "Engineering Monitoring" + c_tag = "Engineering Monitoring"; + network = list("ss13","engine") }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -22593,28 +22609,24 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "aJe" = ( -/obj/structure/table, -/obj/machinery/airalarm/unlocked{ - dir = 4; - pixel_x = -23 +/obj/machinery/firealarm{ + pixel_y = 24 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 +/obj/structure/extinguisher_cabinet{ + pixel_x = -24; + pixel_y = 32 }, -/obj/effect/turf_decal/tile/neutral, -/obj/item/clipboard, -/obj/item/folder/white, -/obj/item/storage/pill_bottle/mutadone{ - pixel_x = -8; - pixel_y = 8 +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/camera{ + c_tag = "Gravity Generator Entry"; + network = list("ss13","engine"); + pixel_x = 23 }, -/obj/item/storage/pill_bottle/mannitol{ - pixel_x = -8; - pixel_y = 2 +/obj/effect/turf_decal/stripes/line{ + dir = 9 }, -/obj/item/radio/headset/headset_medsci, -/turf/open/floor/plasteel/dark, -/area/medical/genetics) +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "aJf" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -22684,23 +22696,30 @@ /turf/open/floor/plating, /area/engine/gravity_generator) "aJk" = ( -/obj/machinery/firealarm{ - pixel_y = 24 +/obj/structure/table/reinforced, +/obj/item/lightreplacer, +/obj/structure/cable/white{ + icon_state = "1-8" }, -/obj/structure/extinguisher_cabinet{ - pixel_x = -24; - pixel_y = 32 +/obj/structure/cable/white{ + icon_state = "4-8" }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/machinery/camera{ - c_tag = "Gravity Generator Entry"; - pixel_x = 23 - }, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/item/toy/figure/engineer, /turf/open/floor/plasteel, -/area/engine/gravity_generator) +/area/engine/engineering) "aJl" = ( /obj/machinery/power/apc/highcap/five_k{ areastring = "/area/engine/gravity_generator"; @@ -22876,8 +22895,7 @@ /obj/machinery/requests_console{ department = "Genetics"; name = "Genetics RC"; - pixel_x = 28; - pixel_y = 0 + pixel_x = 28 }, /turf/open/floor/plasteel/white, /area/medical/genetics) @@ -23106,19 +23124,13 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "aJO" = ( -/obj/machinery/camera{ - c_tag = "Genetics Cloning"; - dir = 4 +/obj/effect/spawner/structure/window/plasma/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "rdprivacy"; + name = "Director's Privacy Blast Door" }, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -22 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/medical/genetics) +/turf/open/floor/plating, +/area/crew_quarters/heads/hor) "aJP" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -23394,21 +23406,9 @@ /turf/closed/wall, /area/maintenance/port/aft) "aKo" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/structure/lattice, +/turf/open/floor/plating/asteroid/airless, +/area/asteroid/nearstation) "aKp" = ( /obj/machinery/airalarm{ dir = 4; @@ -23446,17 +23446,16 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "aKr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 +/obj/machinery/power/solar{ + id = "aftport"; + name = "Aft-Port Solar Array" }, -/obj/effect/landmark/xeno_spawn, -/obj/structure/sign/warning/vacuum{ - pixel_x = -32; - pixel_y = 32 +/obj/structure/cable{ + icon_state = "0-4" }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/effect/turf_decal/box, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/port/aft) "aKs" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/command/glass{ @@ -23600,11 +23599,15 @@ /turf/open/floor/engine, /area/engine/supermatter) "aKB" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" }, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/space/basic, +/area/solar/port/aft) "aKC" = ( /obj/machinery/atmospherics/components/binary/pump{ name = "Gas to Chamber" @@ -23624,24 +23627,16 @@ /turf/open/floor/plasteel/dark, /area/engine/engineering) "aKF" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/machinery/power/solar{ + id = "aftport"; + name = "Aft-Port Solar Array" }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/structure/cable{ + icon_state = "0-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/effect/turf_decal/box, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/port/aft) "aKG" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -23750,29 +23745,15 @@ /turf/open/floor/plasteel, /area/engine/engineering) "aKM" = ( -/obj/structure/table/reinforced, -/obj/item/lightreplacer, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +/obj/machinery/light_switch{ + pixel_y = -24 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/bot, +/obj/structure/closet/l3closet/janitor, +/obj/item/toy/figure/janitor, /turf/open/floor/plasteel, -/area/engine/engineering) +/area/janitor) "aKN" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -24268,13 +24249,18 @@ }, /area/maintenance/port/aft) "aLz" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" }, -/obj/machinery/light/small, -/obj/structure/closet/emcloset/anchored, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/space/basic, +/area/solar/port/aft) "aLA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 @@ -24292,12 +24278,8 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "aLC" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/item/cigbutt, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/turf/closed/wall, +/area/maintenance/solars/port/aft) "aLD" = ( /obj/machinery/power/port_gen/pacman, /obj/effect/turf_decal/stripes/line{ @@ -24396,11 +24378,13 @@ /turf/open/floor/plasteel, /area/engine/gravity_generator) "aLL" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/effect/turf_decal/box, +/obj/structure/cable{ + icon_state = "0-4" }, -/turf/open/floor/plating/airless, -/area/maintenance/port/aft) +/obj/machinery/power/tracker, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/port/aft) "aLM" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -24938,27 +24922,19 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "aMH" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-8" }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/turf/open/space/basic, +/area/solar/port/aft) "aMI" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-4" }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port/aft) +/turf/open/space/basic, +/area/solar/port/aft) "aMJ" = ( /turf/closed/wall/r_wall, /area/tcommsat/server) @@ -25024,21 +25000,18 @@ /turf/open/floor/engine, /area/engine/engineering) "aMQ" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-4" }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 +/obj/structure/cable{ + icon_state = "2-4" }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/obj/structure/cable{ + icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port/aft) +/turf/open/space/basic, +/area/solar/port/aft) "aMR" = ( /obj/machinery/camera{ c_tag = "Supermatter Chamber"; @@ -25257,14 +25230,32 @@ /turf/open/floor/plasteel, /area/janitor) "aNl" = ( -/obj/machinery/light_switch{ - pixel_y = -24 +/obj/structure/table, +/obj/machinery/airalarm/unlocked{ + dir = 4; + pixel_x = -23 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/bot, -/obj/structure/closet/l3closet/janitor, -/turf/open/floor/plasteel, -/area/janitor) +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/item/clipboard, +/obj/item/folder/white, +/obj/item/storage/pill_bottle/mutadone{ + pixel_x = -8; + pixel_y = 8 + }, +/obj/item/storage/pill_bottle/mannitol{ + pixel_x = -8; + pixel_y = 2 + }, +/obj/item/radio/headset/headset_medsci, +/obj/item/toy/figure/geneticist{ + pixel_x = 5; + pixel_y = 13 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aNm" = ( /obj/effect/turf_decal/bot, /obj/machinery/vending/wardrobe/jani_wardrobe, @@ -25575,23 +25566,17 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "aNO" = ( -/obj/machinery/camera{ - c_tag = "Genetics Lab"; - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/obj/machinery/computer/scan_consolenew{ - icon_state = "computer"; - dir = 1 +/obj/structure/sign/poster/official/anniversary_vintage_reprint{ + pixel_x = 32 }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel/dark, -/area/medical/genetics) +/turf/open/floor/plasteel/white, +/area/science/research) "aNP" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -25744,22 +25729,10 @@ /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/cmo) "aOc" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) +/obj/structure/lattice/catwalk, +/obj/effect/landmark/xeno_spawn, +/turf/open/space/basic, +/area/solar/port/aft) "aOd" = ( /obj/machinery/power/apc{ areastring = "/area/engine/engineering"; @@ -26119,17 +26092,18 @@ /turf/open/floor/engine, /area/engine/engineering) "aOH" = ( -/obj/structure/cable/white{ - icon_state = "1-2" +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 +/obj/structure/cable{ + icon_state = "1-4" }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/structure/cable{ + icon_state = "4-8" }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/turf/open/space/basic, +/area/solar/port/aft) "aOI" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -26329,21 +26303,15 @@ /turf/closed/wall, /area/medical/genetics) "aOX" = ( -/obj/machinery/requests_console{ - department = "Medbay"; - departmentType = 1; - name = "Medbay RC"; - pixel_x = -30 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/camera{ - c_tag = "Medbay Storage" + c_tag = "R&D"; + dir = 1; + network = list("ss13","rd") }, -/obj/machinery/rnd/production/techfab/department/medical, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/box, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel/white, +/area/science/lab) "aOY" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -27125,18 +27093,24 @@ }, /area/hallway/primary/port/aft) "aQe" = ( -/obj/structure/table/glass, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/machinery/camera{ + c_tag = "Genetics Lab"; + dir = 8; + network = list("ss13","medbay") }, -/obj/effect/turf_decal/tile/blue{ +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/paper_bin, -/obj/item/pen, -/obj/item/stamp/cmo, -/turf/open/floor/plasteel/cafeteria, -/area/crew_quarters/heads/cmo) +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/computer/scan_consolenew{ + icon_state = "computer"; + dir = 1 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aQf" = ( /obj/machinery/firealarm{ dir = 1; @@ -27424,40 +27398,12 @@ /turf/open/floor/plasteel/dark, /area/medical/morgue) "aQE" = ( -/obj/machinery/light/small{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "0-8" - }, -/obj/structure/table/wood, -/obj/item/storage/box/bodybags{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/box/bodybags, -/obj/machinery/power/apc{ - areastring = "/area/medical/morgue"; +/obj/machinery/airalarm/unlocked{ dir = 4; - name = "Morgue APC"; - pixel_x = 26 + pixel_x = -23 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Morgue"; - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/turf/open/floor/plating/asteroid, +/area/crew_quarters/heads/hor) "aQF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -28844,24 +28790,20 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "aTn" = ( -/obj/effect/landmark/start/virologist, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 +/obj/structure/table/plasmaglass, +/obj/machinery/recharger, +/obj/item/paicard{ + pixel_x = 15 }, -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/medical/virology"; - dir = 1; - name = "Virology APC"; - pixel_y = 24 +/obj/structure/sign/poster/official/ue_no{ + pixel_y = 32 }, -/obj/structure/cable/white{ - icon_state = "0-4" +/obj/item/toy/figure/rd{ + pixel_x = -8; + pixel_y = 14 }, -/obj/machinery/camera{ - c_tag = "Virology" - }, -/turf/open/floor/plasteel, -/area/medical/virology) +/turf/open/floor/plating/asteroid, +/area/crew_quarters/heads/hor) "aTo" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall/r_wall, @@ -30095,14 +30037,24 @@ /turf/open/floor/plasteel/white, /area/science/research) "aVz" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ +/obj/machinery/shower{ + dir = 8; + name = "emergency shower" + }, +/obj/machinery/light/small, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/machinery/camera{ + c_tag = "Engineering Access"; + dir = 8; + network = list("ss13","engine") }, -/turf/open/floor/plasteel/white, -/area/science/research) +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/engine/engineering) "aVA" = ( /turf/closed/wall, /area/science/research) @@ -30425,6 +30377,10 @@ /obj/item/reagent_containers/glass/bottle/epinephrine, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/dropper, +/obj/item/toy/figure/chemist{ + pixel_x = -6; + pixel_y = 11 + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "aWg" = ( @@ -30517,14 +30473,24 @@ /turf/open/floor/plasteel/white, /area/science/lab) "aWm" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/camera{ - c_tag = "R&D"; - dir = 1 +/obj/structure/table, +/obj/item/storage/box/gloves{ + pixel_x = 3; + pixel_y = 3 }, -/obj/effect/turf_decal/tile/purple, -/turf/open/floor/plasteel/white, -/area/science/lab) +/obj/item/storage/box/beakers, +/obj/structure/extinguisher_cabinet{ + pixel_x = -26 + }, +/obj/machinery/camera{ + c_tag = "Medbay West"; + network = list("ss13","medbay") + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) "aWn" = ( /obj/machinery/firealarm{ dir = 1; @@ -31057,23 +31023,22 @@ /turf/open/floor/plasteel/dark, /area/library) "aXm" = ( -/obj/structure/table, -/obj/item/storage/box/gloves{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/box/beakers, -/obj/structure/extinguisher_cabinet{ - pixel_x = -26 - }, -/obj/machinery/camera{ - c_tag = "Medbay West" - }, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/camera{ + c_tag = "Research Division North"; + network = list("ss13","rd") + }, +/obj/effect/landmark/event_spawn, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/science/research) "aXn" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/blue{ @@ -31712,18 +31677,26 @@ /turf/open/floor/plasteel/white, /area/science/research) "aYp" = ( -/obj/structure/extinguisher_cabinet{ - pixel_x = 24 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/machinery/camera{ - c_tag = "Research Division South"; + c_tag = "Communications Relay"; + dir = 8; + network = list("ss13","tcomms") + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/vending/wardrobe/science_wardrobe, -/obj/effect/turf_decal/tile/purple, -/turf/open/floor/plasteel/white, -/area/science/research) +/turf/open/floor/plasteel/dark/telecomms, +/area/tcommsat/server) "aYq" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{ dir = 1 @@ -31881,21 +31854,25 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "aYB" = ( -/obj/machinery/shower{ - desc = "From what you understand it was put in rather recently, but the design looks right out of the 2510's. Weird."; - dir = 1; - icon_state = "shower"; - name = "Emergency Shower" +/obj/machinery/door/firedoor/heavy, +/obj/machinery/door/airlock/command{ + name = "Research Director's Office"; + req_access_txt = "30" + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /obj/effect/turf_decal/stripes/line{ - dir = 6 + dir = 4 }, -/obj/machinery/camera{ - c_tag = "Virology Access"; - dir = 1 +/obj/effect/turf_decal/stripes/line{ + dir = 8 }, -/turf/open/floor/plasteel/white, -/area/medical/virology) +/turf/open/floor/plasteel, +/area/crew_quarters/heads/hor) "aYC" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/landmark/event_spawn, @@ -31915,7 +31892,6 @@ /obj/machinery/requests_console{ department = "Virology"; name = "Virology RC"; - pixel_x = 0; pixel_y = -32; receive_ore_updates = 1 }, @@ -32695,6 +32671,17 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"aZS" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/solar/port/aft) +"aZT" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating/airless, +/area/solar/port/aft) "aZU" = ( /obj/machinery/recharge_station, /obj/effect/landmark/start/cyborg, @@ -32822,6 +32809,25 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) +"bae" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) "baf" = ( /obj/item/stack/sheet/metal/fifty, /obj/item/stack/sheet/metal/fifty, @@ -32895,6 +32901,148 @@ icon_state = "platingdmg1" }, /area/maintenance/starboard) +"baj" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/effect/landmark/xeno_spawn, +/obj/structure/sign/warning/vacuum{ + pixel_x = -32; + pixel_y = 32 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) +"bak" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) +"bal" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) +"bam" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/sign/warning/vacuum{ + pixel_y = 32 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"ban" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bao" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/sign/warning/electricshock{ + pixel_y = -32 + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bap" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"baq" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"bar" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/space/basic, +/area/solar/port/aft) +"bas" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small, +/obj/structure/closet/emcloset/anchored, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) +"bat" = ( +/turf/closed/wall/r_wall/rust, +/area/maintenance/solars/port/aft) +"bau" = ( +/turf/closed/wall/r_wall, +/area/maintenance/solars/port/aft) +"bav" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/closed/wall, +/area/maintenance/solars/port/aft) "baw" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/departments/medbay/alt, @@ -33015,6 +33163,17 @@ }, /turf/open/floor/plasteel, /area/medical/medbay/zone3) +"baE" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/engineering{ + name = "Port Quarter Solar Access"; + req_access_txt = "10" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "baF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/blue, @@ -33125,28 +33284,22 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "baN" = ( -/obj/machinery/firealarm{ - dir = 4; - pixel_x = -24 +/obj/machinery/computer/card/minor/rd, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/cable/white{ - icon_state = "1-2" +/obj/item/aicard, +/turf/open/floor/plasteel{ + icon_state = "sepia" }, -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/machinery/camera{ - c_tag = "Mech Bay"; - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/science/robotics/mechbay) +/area/crew_quarters/heads/hor) "baO" = ( /obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, /obj/structure/cable/white{ @@ -33292,6 +33445,165 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) +"bbb" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/obj/structure/cable/white{ + icon_state = "1-4" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"bbc" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/item/cigbutt, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"bbd" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"bbe" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plating/airless, +/area/maintenance/port/aft) +"bbf" = ( +/obj/machinery/power/smes, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bbg" = ( +/obj/structure/lattice/catwalk, +/obj/effect/landmark/xeno_spawn, +/turf/open/space/basic, +/area/solar/starboard/fore) +"bbh" = ( +/obj/structure/cable/white{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bbi" = ( +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/obj/machinery/power/apc{ + areastring = "/area/maintenance/solars/port/aft"; + dir = 4; + name = "Port Quarter Solar APC"; + pixel_x = 26 + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bbj" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"bbk" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"bbl" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"bbm" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"bbn" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"bbo" = ( +/obj/structure/cable/white{ + icon_state = "1-4" + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "bbp" = ( /obj/machinery/light{ dir = 8 @@ -33605,6 +33917,153 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) +"bbP" = ( +/obj/machinery/modular_computer/console/preset/research, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bbQ" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) +"bbR" = ( +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/structure/cable/white, +/obj/machinery/power/solar_control{ + dir = 8; + id = "aftport"; + name = "Port Quarter Solar Control" + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bbS" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/space/basic, +/area/solar/port/aft) +"bbT" = ( +/turf/closed/wall, +/area/maintenance/solars/starboard/fore) +"bbU" = ( +/turf/closed/wall/r_wall, +/area/maintenance/solars/starboard/fore) +"bbV" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) +"bbW" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) +"bbX" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/closet/emcloset/anchored, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) +"bbY" = ( +/obj/structure/lattice/catwalk, +/turf/open/floor/plating/airless, +/area/solar/starboard/fore) +"bbZ" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) +"bca" = ( +/obj/structure/sign/warning/vacuum{ + pixel_x = 32; + pixel_y = 32 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/obj/effect/landmark/xeno_spawn, +/obj/effect/turf_decal/delivery, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) +"bcb" = ( +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) +"bcc" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) "bcd" = ( /obj/item/retractor, /obj/item/hemostat, @@ -33923,12 +34382,166 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) +"bcD" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/space/basic, +/area/solar/starboard/fore) "bcE" = ( /obj/structure/closet/l3closet/scientist{ pixel_x = -2 }, /turf/open/floor/plasteel, /area/science/mixing) +"bcF" = ( +/obj/structure/sign/warning/securearea, +/turf/closed/wall/r_wall, +/area/maintenance/solars/starboard/fore) +"bcG" = ( +/obj/structure/sign/warning/vacuum{ + pixel_x = 32; + pixel_y = 32 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcH" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcI" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcJ" = ( +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/effect/turf_decal/box, +/obj/machinery/power/tracker, +/turf/open/floor/plasteel/airless/solarpanel, +/area/solar/starboard/fore) +"bcK" = ( +/obj/machinery/power/smes, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcL" = ( +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/machinery/power/solar_control{ + dir = 2; + id = "forestarboard"; + name = "Starboard Bow Solar Control" + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcM" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/sign/warning/electricshock{ + pixel_x = 32; + pixel_y = -32 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcO" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/door/airlock/engineering{ + name = "Starboard Bow Solar Access"; + req_access_txt = "10" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcP" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcQ" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/turf/open/space/basic, +/area/solar/starboard/fore) +"bcR" = ( +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bcS" = ( +/obj/structure/lattice, +/obj/structure/sign/warning/securearea{ + pixel_x = -32 + }, +/turf/open/floor/plating/asteroid/airless, +/area/asteroid/nearstation) +"bcT" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) "bcU" = ( /obj/item/circular_saw, /obj/item/surgicaldrill{ @@ -34174,6 +34787,15 @@ }, /turf/open/floor/plating, /area/security/checkpoint) +"bdi" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "bdj" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -34319,20 +34941,20 @@ /turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bdv" = ( -/obj/structure/table/reinforced, -/obj/structure/window/reinforced{ +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ dir = 8 }, -/obj/item/clothing/gloves/color/latex, -/obj/item/surgical_drapes, -/obj/item/cautery, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/camera{ + c_tag = "Atmospherics North East"; + dir = 8; + network = list("ss13","engine") + }, +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/checker, +/area/engine/atmos) "bdw" = ( /obj/machinery/holopad, /obj/effect/turf_decal/tile/purple{ @@ -34380,6 +35002,243 @@ /obj/structure/sign/warning/fire, /turf/closed/wall, /area/science/mixing) +"bdB" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating/airless, +/area/solar/starboard/fore) +"bdC" = ( +/obj/structure/cable, +/obj/machinery/power/terminal{ + dir = 8 + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bdD" = ( +/obj/structure/displaycase/labcage, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/heads/hor"; + dir = 1; + name = "RD Office APC"; + pixel_y = 26 + }, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdE" = ( +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/machinery/power/apc{ + areastring = "/area/maintenance/solars/starboard/fore"; + dir = 2; + name = "Starboard Bow Solar APC"; + pixel_y = -26 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) +"bdF" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/power/apc{ + areastring = "/area/maintenance/starboard/fore"; + dir = 4; + name = "Starboard Bow Maintenance APC"; + pixel_x = 26 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) +"bdG" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) +"bdH" = ( +/obj/machinery/requests_console{ + department = "Medbay"; + departmentType = 1; + name = "Medbay RC"; + pixel_x = -30 + }, +/obj/machinery/camera{ + c_tag = "Medbay Storage"; + network = list("ss13","medbay") + }, +/obj/machinery/rnd/production/techfab/department/medical, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/box, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) +"bdI" = ( +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/holopad, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdJ" = ( +/obj/structure/chair/office/dark{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/landmark/start/research_director, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdK" = ( +/obj/machinery/computer/mecha{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdL" = ( +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/landmark/start/research_director, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdM" = ( +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdN" = ( +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/keycard_auth{ + pixel_x = 24; + pixel_y = -24 + }, +/obj/machinery/button/door{ + id = "rdprivacy"; + name = "Director's Privacy Toggle"; + pixel_x = 24; + pixel_y = -38 + }, +/obj/machinery/light_switch{ + pixel_x = 40; + pixel_y = -24 + }, +/obj/machinery/button/door{ + id = "rdxeno"; + name = "Xenobiology Containment Lockdown"; + pixel_x = 38; + pixel_y = -38; + req_access_txt = "47" + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bdO" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall/r_wall, +/area/crew_quarters/heads/hor) +"bdP" = ( +/obj/machinery/light{ + dir = 1; + light_color = "#c1caff" + }, +/obj/structure/flora/tree/palm, +/turf/open/floor/plating/asteroid, +/area/crew_quarters/heads/hor) "bdQ" = ( /obj/structure/closet/secure_closet/medical2, /obj/machinery/airalarm{ @@ -34487,25 +35346,23 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) "bdW" = ( -/obj/structure/closet/crate/freezer/blood, -/obj/structure/extinguisher_cabinet{ - pixel_y = -26 +/obj/structure/bed/dogbed/runtime, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 +/obj/effect/turf_decal/delivery, +/obj/structure/sign/poster/official/medical_green_cross{ + pixel_x = -32 }, /obj/machinery/camera{ - c_tag = "Medbay Recovery Room"; - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 + c_tag = "CMO's Office"; + dir = 4; + network = list("ss13","medbay") }, +/mob/living/simple_animal/pet/cat/Runtime, /turf/open/floor/plasteel/dark, -/area/medical/medbay/zone3) +/area/crew_quarters/heads/cmo) "bdX" = ( /obj/machinery/computer/crew{ dir = 4 @@ -34790,10 +35647,174 @@ /obj/machinery/door/poddoor/incinerator_toxmix, /turf/open/floor/engine/vacuum, /area/science/mixing) +"beu" = ( +/obj/machinery/portable_atmospherics/pump, +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/science/mixing) +"bev" = ( +/obj/structure/table/plasmaglass, +/obj/item/paper_bin, +/obj/item/pen, +/obj/item/stamp/rd, +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/turf/open/floor/plating/asteroid, +/area/crew_quarters/heads/hor) +"bew" = ( +/obj/machinery/computer/aifixer{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bex" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"bey" = ( +/obj/structure/table/glass, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/item/paper_bin, +/obj/item/pen, +/obj/item/stamp/cmo, +/obj/machinery/light_switch{ + pixel_x = 24; + pixel_y = -24 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) +"bez" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"beA" = ( +/obj/structure/closet/bombcloset, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"beB" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel, +/area/science/mixing) +"beC" = ( +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/structure/cable/white{ + icon_state = "1-4" + }, +/obj/machinery/camera{ + c_tag = "Mech Bay"; + dir = 4; + network = list("ss13","rd") + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/science/robotics/mechbay) +"beD" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/sign/poster/official/soft_cap_pop_art{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) "beE" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/medical/medbay/zone3) +"beF" = ( +/obj/machinery/camera{ + c_tag = "Toxins Lab West"; + network = list("ss13","rd") + }, +/turf/open/floor/plasteel, +/area/science/mixing) "beG" = ( /obj/structure/sign/departments/medbay/alt, /turf/closed/wall, @@ -34930,6 +35951,146 @@ }, /turf/closed/wall/r_wall, /area/science/robotics/lab) +"beR" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/camera{ + c_tag = "Research Director's Office"; + dir = 1; + network = list("ss13","rd") + }, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = -26 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"beS" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/obj/machinery/requests_console{ + announcementConsole = 1; + department = "Research Director's Desk"; + departmentType = 5; + name = "Research Director RC"; + pixel_x = 0; + pixel_y = -32; + receive_ore_updates = 1 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) +"beT" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"beU" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"beV" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/closet/bombcloset, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"beW" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"beX" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel, +/area/science/mixing) +"beY" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall/r_wall, +/area/crew_quarters/heads/hor) +"beZ" = ( +/obj/machinery/light_switch{ + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfa" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfb" = ( +/obj/machinery/portable_atmospherics/scrubber, +/obj/item/storage/firstaid/toxin, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfc" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfd" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/mixing) "bfe" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/airalarm/unlocked{ @@ -34969,6 +36130,37 @@ /obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"bfh" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfi" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfj" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/mixing) +"bfk" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/science/mixing) "bfl" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -35033,6 +36225,15 @@ }, /turf/open/floor/plating, /area/maintenance/starboard) +"bfq" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/science/mixing) "bfr" = ( /obj/structure/cable/white{ icon_state = "1-8" @@ -35045,6 +36246,32 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"bfs" = ( +/obj/machinery/vending/wardrobe/science_wardrobe, +/obj/machinery/light, +/turf/open/floor/plasteel, +/area/science/mixing) +"bft" = ( +/obj/structure/closet/secure_closet/RD, +/obj/machinery/light, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/obj/item/circuitboard/aicore, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) "bfu" = ( /turf/closed/wall, /area/chapel/main) @@ -35063,6 +36290,27 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel/white, /area/chapel/main) +"bfw" = ( +/obj/machinery/suit_storage_unit/rd, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/computer/security/telescreen/rd{ + dir = 1; + icon_state = "telescreen"; + pixel_y = -28 + }, +/turf/open/floor/plasteel{ + icon_state = "sepia" + }, +/area/crew_quarters/heads/hor) "bfx" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 @@ -35075,16 +36323,148 @@ }, /turf/closed/wall, /area/chapel/main) +"bfz" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/science/mixing) "bfA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/closed/wall, /area/chapel/main) +"bfB" = ( +/obj/machinery/holopad, +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/science/mixing) "bfC" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/closed/wall/rust, /area/chapel/main) +"bfD" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/structure/table/wood, +/obj/item/storage/box/bodybags{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/box/bodybags, +/obj/machinery/power/apc{ + areastring = "/area/medical/morgue"; + dir = 4; + name = "Morgue APC"; + pixel_x = 26 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Morgue"; + dir = 8; + network = list("ss13","medbay") + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"bfE" = ( +/obj/structure/table/reinforced, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/item/clothing/gloves/color/latex, +/obj/item/surgical_drapes, +/obj/item/cautery, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/figure/roboticist{ + pixel_x = -4; + pixel_y = 14 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"bfF" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Surgery Operating"; + dir = 1; + network = list("ss13","medbay"); + pixel_x = 22 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) +"bfG" = ( +/obj/structure/closet/crate/freezer/blood, +/obj/structure/extinguisher_cabinet{ + pixel_y = -26 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Medbay Recovery Room"; + dir = 8; + network = list("ss13","medbay") + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/medbay/zone3) +"bfH" = ( +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/medical/virology"; + dir = 1; + name = "Virology APC"; + pixel_y = 24 + }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/obj/machinery/camera{ + c_tag = "Virology"; + network = list("ss13","medbay") + }, +/turf/open/floor/plasteel, +/area/medical/virology) "bfI" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/cable/white{ @@ -35162,6 +36542,36 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"bfM" = ( +/obj/machinery/shower{ + desc = "From what you understand it was put in rather recently, but the design looks right out of the 2510's. Weird."; + dir = 1; + icon_state = "shower"; + name = "Emergency Shower" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/camera{ + c_tag = "Virology Access"; + dir = 1; + network = list("ss13","medbay") + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"bfN" = ( +/obj/effect/turf_decal/stripes/end{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/camera{ + c_tag = "Xenobiology North"; + dir = 4; + network = list("ss13","rd"); + pixel_y = -5 + }, +/turf/open/floor/plasteel, +/area/science/xenobiology) "bfO" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 @@ -35367,6 +36777,48 @@ }, /turf/open/floor/plasteel/dark, /area/chapel/main) +"bgc" = ( +/obj/machinery/shower{ + dir = 4; + name = "emergency shower" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/stripes/end{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Xenobiology Central"; + dir = 4; + network = list("ss13","rd"); + pixel_y = -5 + }, +/turf/open/floor/plasteel, +/area/science/xenobiology) +"bgd" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/beakers{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/box/syringes, +/obj/item/extinguisher/mini, +/obj/machinery/airalarm/unlocked{ + dir = 4; + pixel_x = -23 + }, +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/obj/machinery/camera{ + c_tag = "Xenobiology Lab"; + dir = 4; + network = list("ss13","rd") + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/science/xenobiology) "bge" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 8 @@ -35401,6 +36853,88 @@ heat_capacity = 1e+006 }, /area/hallway/primary/aft) +"bgg" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/monkeycubes, +/obj/item/storage/box/monkeycubes, +/obj/machinery/status_display{ + pixel_y = -32 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/camera{ + c_tag = "Xenobiology South"; + dir = 1; + network = list("ss13","rd") + }, +/turf/open/floor/plasteel, +/area/science/xenobiology) +"bgh" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/obj/machinery/camera{ + c_tag = "Atmospherics South West"; + dir = 1; + network = list("ss13","engine") + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bgi" = ( +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 4; + name = "Air to External Air Ports" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/camera{ + c_tag = "Atmospherics South East"; + dir = 1; + network = list("ss13","engine") + }, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) +"bgj" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/airlock_sensor{ + id_tag = "incinerator_airlock_sensor"; + master_tag = "incinerator_airlock_control"; + pixel_y = 24 + }, +/obj/machinery/camera/autoname{ + network = list("ss13","engine") + }, +/turf/open/floor/engine, +/area/maintenance/disposal/incinerator) +"bgk" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/light/small, +/obj/machinery/camera{ + c_tag = "Port Quarter Solar"; + dir = 1; + network = list("ss13","engine") + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "bgl" = ( /obj/machinery/vending/cola/random, /obj/machinery/newscaster{ @@ -35428,6 +36962,20 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) +"bgn" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 24 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/machinery/camera{ + c_tag = "Research Division South"; + dir = 8; + network = list("ss13","rd") + }, +/obj/machinery/vending/wardrobe/science_wardrobe, +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel/white, +/area/science/research) "bgo" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable/white{ @@ -36710,22 +38258,6 @@ }, /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) -"biC" = ( -/obj/machinery/shower{ - dir = 4; - name = "emergency shower" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/end{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Xenobiology Central"; - dir = 4; - pixel_y = -5 - }, -/turf/open/floor/plasteel, -/area/science/xenobiology) "biD" = ( /obj/machinery/shower{ dir = 8; @@ -37396,46 +38928,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"bjP" = ( -/obj/structure/table/reinforced, -/obj/item/storage/box/beakers{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/box/syringes, -/obj/item/extinguisher/mini, -/obj/machinery/airalarm/unlocked{ - dir = 4; - pixel_x = -23 - }, -/obj/machinery/newscaster{ - pixel_y = -32 - }, -/obj/machinery/camera{ - c_tag = "Xenobiology Lab"; - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/science/xenobiology) -"bjQ" = ( -/obj/structure/table/reinforced, -/obj/item/storage/box/monkeycubes, -/obj/item/storage/box/monkeycubes, -/obj/machinery/status_display{ - pixel_y = -32 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/camera{ - c_tag = "Xenobiology South"; - dir = 1 - }, -/turf/open/floor/plasteel, -/area/science/xenobiology) "bjR" = ( /obj/machinery/computer/camera_advanced/xenobio{ dir = 1 @@ -37844,22 +39336,6 @@ /obj/machinery/telecomms/broadcaster/preset_left/birdstation, /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) -"blr" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/camera{ - c_tag = "Research Division North" - }, -/obj/effect/landmark/event_spawn, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/science/research) "bls" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -37881,27 +39357,6 @@ heat_capacity = 1e+006 }, /area/hallway/primary/aft) -"blt" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Surgery Operating"; - dir = 1; - pixel_x = 22 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) "blv" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -38715,26 +40170,6 @@ }, /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) -"buU" = ( -/obj/machinery/camera{ - c_tag = "Communications Relay"; - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/tcommsat/server) "buW" = ( /turf/closed/wall/r_wall, /area/engine/supermatter) @@ -39149,9 +40584,6 @@ heat_capacity = 1e+006 }, /area/hallway/secondary/entry) -"bxZ" = ( -/turf/closed/wall, -/area/maintenance/starboard/fore) "bye" = ( /turf/closed/wall/rust, /area/maintenance/fore) @@ -39206,14 +40638,6 @@ dir = 1 }, /area/engine/atmos) -"bNB" = ( -/obj/machinery/portable_atmospherics/pump, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel, -/area/science/mixing) "bOJ" = ( /obj/machinery/camera{ c_tag = "Toxins Launch Room Access"; @@ -39227,15 +40651,6 @@ }, /turf/open/floor/plasteel, /area/science/mixing) -"bWO" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/science/mixing) "bYE" = ( /obj/structure/sign/warning/fire, /obj/machinery/atmospherics/pipe/simple/general/visible{ @@ -39374,19 +40789,6 @@ }, /turf/open/floor/engine/vacuum, /area/maintenance/disposal/incinerator) -"cGz" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -26 - }, -/obj/machinery/camera{ - c_tag = "Atmospherics South West"; - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "cRz" = ( /obj/machinery/button/door{ id = "supplybridge"; @@ -39595,18 +40997,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/atmos) -"edA" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/fore) "eew" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable{ @@ -39738,18 +41128,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"eFp" = ( -/obj/effect/turf_decal/stripes/end{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/camera{ - c_tag = "Xenobiology North"; - dir = 4; - pixel_y = -5 - }, -/turf/open/floor/plasteel, -/area/science/xenobiology) "eGm" = ( /turf/closed/wall/r_wall, /area/science/storage) @@ -40201,12 +41579,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) -"hns" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/closed/wall/rust, -/area/science/mixing) "hpr" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=3.2-AtriumSW"; @@ -40512,14 +41884,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/visible, /turf/open/floor/plasteel, /area/engine/atmos) -"iXB" = ( -/obj/structure/closet/bombcloset, -/obj/machinery/light_switch{ - pixel_y = 28 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel, -/area/science/mixing) "iZQ" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/carbon_input, /turf/open/floor/engine/co2, @@ -40725,13 +42089,6 @@ }, /turf/open/floor/plasteel, /area/science/mixing) -"jLT" = ( -/obj/machinery/portable_atmospherics/scrubber, -/obj/item/storage/firstaid/toxin, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, -/area/science/mixing) "jRe" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -40890,10 +42247,6 @@ /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/plating, /area/science/storage) -"lmr" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, -/area/science/mixing) "low" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 @@ -40965,26 +42318,6 @@ }, /turf/open/floor/plasteel, /area/science/mixing) -"lAs" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_y = 24 - }, -/obj/machinery/camera{ - c_tag = "Atmospherics North West"; - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/turf/open/floor/plasteel/dark/corner{ - dir = 1 - }, -/area/engine/atmos) "lCg" = ( /obj/machinery/door/airlock/external{ name = "Supply Dock Airlock"; @@ -41084,13 +42417,6 @@ "meo" = ( /turf/closed/wall/r_wall/rust, /area/science/mixing) -"mfj" = ( -/obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/science/mixing) "mgs" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/air_input{ dir = 1 @@ -41494,15 +42820,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"oRo" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/science/mixing) "pbT" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 @@ -41701,10 +43018,6 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos) -"pXH" = ( -/obj/machinery/vending/wardrobe/science_wardrobe, -/turf/open/floor/plasteel, -/area/science/mixing) "pZU" = ( /obj/structure/lattice, /obj/structure/grille, @@ -41879,23 +43192,6 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) -"rjV" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4 - }, -/obj/machinery/light/small{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/airlock_sensor{ - id_tag = "incinerator_airlock_sensor"; - master_tag = "incinerator_airlock_control"; - pixel_y = 24 - }, -/obj/machinery/camera/autoname, -/turf/open/floor/engine, -/area/maintenance/disposal/incinerator) "rlq" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -41908,13 +43204,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) -"rpy" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/obj/structure/sign/warning/nosmoking/circle, -/turf/closed/wall, -/area/science/mixing) "rzn" = ( /obj/machinery/status_display, /turf/closed/wall, @@ -41994,18 +43283,6 @@ /mob/living/simple_animal/opossum, /turf/open/floor/plating, /area/maintenance/starboard) -"scn" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/science/mixing) "sdL" = ( /obj/effect/turf_decal/delivery, /obj/machinery/hydroponics/soil, @@ -44840,12 +46117,6 @@ "tin" = ( /turf/open/floor/engine/vacuum, /area/science/mixing) -"tms" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/closed/wall, -/area/maintenance/starboard/aft) "ttp" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/white{ @@ -45025,29 +46296,6 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos) -"uoy" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - name = "Plasma to Pure" - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/camera{ - c_tag = "Atmospherics North" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/engine/atmos) "upN" = ( /obj/machinery/door/airlock/research{ name = "Toxins Launch Room"; @@ -45778,14 +47026,6 @@ /obj/structure/grille, /turf/closed/wall/r_wall, /area/engine/atmos) -"xLe" = ( -/obj/structure/closet/bombcloset, -/obj/machinery/light{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel, -/area/science/mixing) "xPz" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 9 @@ -70446,22 +71686,22 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa jFP jFP jFP @@ -70703,22 +71943,22 @@ jFP jFP jFP jFP -jFP -jFP -jFP -uXD -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aab +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa jFP jFP jFP @@ -70961,19 +72201,19 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU +sdX +pZU +pZU +pZU +sdX +aLL +sdX +pZU +pZU +pZU +sdX +pZU aaa aaa jFP @@ -71218,19 +72458,19 @@ aaa aaa aaa aaa +pZU aaa aaa aaa aaa aaa +aMH aaa aaa aaa aaa aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -71475,19 +72715,19 @@ aaa aaa aaa aaa +pZU aaa +aKr +aKr +aKr +aKr +aMI +aKr +aKr +aKr +aKr aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -71732,19 +72972,19 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +sdX +sdX +aKB +aLz +aLz +aLz +aMQ +bar +bar +bar +bbS +sdX +sdX aaa aaa jFP @@ -71989,19 +73229,19 @@ aaa aaa aaa aaa +pZU aaa +aKF +aKF +aKF +aKF +aMH +aKF +aKF +aKF +aKF aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -72227,7 +73467,7 @@ aad aad aad gdA -rjV +bgj fsJ eyu uvg @@ -72246,19 +73486,19 @@ aaa aaa aaa aaa +pZU aaa aaa aaa aaa aaa +aOc aaa aaa aaa aaa aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -72503,19 +73743,19 @@ aaa aaa aaa aaa +pZU aaa +aKr +aKr +aKr +aKr +aMI +aKr +aKr +aKr +aKr aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -72760,19 +74000,19 @@ aac aac aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU +sdX +aKB +aLz +aLz +aLz +aOH +bar +bar +bar +bbS +sdX +sdX aaa aaa jFP @@ -72990,7 +74230,7 @@ aad aad aad aqz -lAs +aCF qTa oJp hUG @@ -73017,19 +74257,19 @@ aad aac aac aac +sdX aaa +aKF +aKF +aKF +aKF +aMH +aKF +aKF +aKF +aKF aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU aaa aaa jFP @@ -73257,7 +74497,7 @@ bGL vuN jkl eew -cGz +bgh qUW aqz aqz @@ -73274,19 +74514,19 @@ aad aad aad aad -aac -aac -aaa +aKo aaa aaa aaa aaa aaa +aZS aaa aaa aaa aaa aaa +pZU aaa aaa jFP @@ -73531,19 +74771,19 @@ aad aad aad aad -aad +adx aad aac aad aad aad -bvg +aZT aac aaa aaa aaa aaa -aaa +pZU aaa aaa jFP @@ -73793,14 +75033,14 @@ aad aad aad aad -aKm -aKo -aKm -aKm -aaa -aaa -aaa -aaa +aLC +bae +aLC +aLC +sdX +sdX +sdX +sdX aaa aaa aaa @@ -74051,13 +75291,13 @@ aMJ aMJ sJV aMJ -aKr -aLz -aKm -aaa +baj +bas +aLC aaa aaa aaa +pZU aaa aaa aaa @@ -74308,13 +75548,13 @@ buJ buO sKn aMJ -aKB -aLs -aKm -aac -aaa -aaa +bak +bat +aLC +aLC +aLC aaa +pZU aaa aaa aaa @@ -74549,7 +75789,7 @@ anv anK aoo aGe -aJk +aJe aKt aLH aMK @@ -74565,13 +75805,13 @@ buK sKj buR aMJ -aKF -aqo -aad -aac -aaa -aaa +bal +bau +bbf +bbo +aLC aaa +pZU aaa aaa aaa @@ -74822,13 +76062,13 @@ buL buP buS aMJ -aKJ -aKm -aad -aad -aaa -aaa -aaa +bam +bav +bdC +bgk +aLC +sdX +sdX aaa aaa aaa @@ -75079,13 +76319,13 @@ buK sKj buR aMJ -aKJ -aKm -aad -aad -aaa -aaa +ban +baE +bbh +bdG +aLC aaa +pZU aaa aaa aaa @@ -75302,7 +76542,7 @@ pNE oOk xej oaV -uoy +asH lqz fFw auq @@ -75334,15 +76574,15 @@ aTZ blq buN buQ -buU +aYp sJV -aKJ -aqo -aad -aaa -aaa -aaa +bao +bau +bbi +bbR +aLC aaa +pZU aaa aaa aaa @@ -75593,13 +76833,13 @@ sJV aMJ aMJ sJV -aKJ -aqo -aLs -aac -aaa -aaa +bap +bau +bat +aLC +aLC aaa +pZU aaa aaa aaa @@ -75850,13 +77090,13 @@ aad bvo aad aKm -aLp -aLB +baq +bbb aKm aac aac aac -aac +aKo aaa aaa aaa @@ -76108,12 +77348,12 @@ aUQ aXc aKm aqo -aLC +bbc aLv aac aac aac -aad +adx aad aaa aaa @@ -76365,7 +77605,7 @@ aUR aUQ bvo aLs -aKJ +bbd aKm aac aad @@ -76622,7 +77862,7 @@ aWz aVL bvo aqo -aLL +bbe aKm aad aad @@ -76879,7 +78119,7 @@ aWz aUQ bvg aKm -aKJ +bbd aKm aKm aad @@ -77136,7 +78376,7 @@ aWz aVL bvg aLv -aKJ +bbd aME aKm aad @@ -77393,7 +78633,7 @@ aUU aUQ bvg aKm -aKJ +bbd aMF aKm aac @@ -77650,7 +78890,7 @@ aWz aVL bvg aKm -aKJ +bbd aMG aKm aKm @@ -77907,8 +79147,8 @@ aWz aUQ bvo aKm -aLp -aLB +baq +bbb aOI aPQ aPQ @@ -78130,7 +79370,7 @@ asA asD sAx arA -asH +bdv atI auB avG @@ -78165,7 +79405,7 @@ aVL bvo aqo aKm -aMH +bbj axU aKm aMG @@ -78422,7 +79662,7 @@ aUQ aad aLs aLX -aMI +bbk aOL aPR aQV @@ -78679,7 +79919,7 @@ aVL aad aqo aMv -aMQ +bbl aOM aPS aRc @@ -78911,10 +80151,10 @@ ayl azr aAt aBB -aCF +bgi aDu aEz -aFB +aVz aGo aHu aIr @@ -78936,7 +80176,7 @@ bvo bvo aqo aMw -aMI +bbk aON aPT aRd @@ -78945,7 +80185,7 @@ aUm aKm aVH aRe -aTn +bfH aWL aZB aTv @@ -79193,7 +80433,7 @@ axX aEg aEg aMD -aOc +bbm aOS aPU aRj @@ -79450,7 +80690,7 @@ aFM aFM aKl aFM -aOH +bbn aOT aPV uXV @@ -79717,7 +80957,7 @@ aKm aSQ aKV aWJ -aYB +bfM aKV aYA aZJ @@ -80461,7 +81701,7 @@ aGt aHz aIw aJF -aKM +aJk aMa aNe aEt @@ -81504,7 +82744,7 @@ aVT aVQ aXg ajG -aGY +bdW aOl aOQ aCy @@ -82019,7 +83259,7 @@ aVQ aXk ajG aOZ -aQe +bey aOK aCy aPE @@ -82776,7 +84016,7 @@ aIC aJK aKR aMg -aNl +aKM aID aOU aQc @@ -82794,7 +84034,7 @@ aNS aPz aPB aPH -aQE +bfD aQL aRb aVc @@ -83039,13 +84279,13 @@ aEh aFh aGf aHG -aJe +aNl aJo aLo aLu aMl aOW -aOX +bdH aGZ aOE aPv @@ -83557,7 +84797,7 @@ aJg aJA aLr aLA -aNO +aQe ail aXQ aYI @@ -83823,7 +85063,7 @@ baw aSh bcf bcW -blt +bfF ooX avB bfA @@ -84068,11 +85308,11 @@ bxQ sJJ ail aGF -aJO +aGY aNL aNo aNP -aXm +aWm aXS aYK aZG @@ -85108,7 +86348,7 @@ baB bbr bci bcZ -bdW +bfG aSh atE bfA @@ -89216,7 +90456,7 @@ aXy aYi aZb aZU -baN +beC bbC bct bdl @@ -89724,7 +90964,7 @@ aSw aTI aUC aVv -aWm +aOX aWV aXA aYk @@ -90263,7 +91503,7 @@ nTi jdD bhb bhO -bjP +bgd bfP aad aad @@ -90497,7 +91737,7 @@ aSz aTL aWp aWW -blr +aXm aYn aZf aZY @@ -90512,15 +91752,15 @@ bfQ bgq bhc bhP -eFp +bfN bhP pLb bhP -biC +bgc bhP bjq bjD -bjQ +bgg bfP aad aad @@ -90954,9 +92194,9 @@ sOk aae aae aaf -aaa -aaa -aaa +sdX +sdX +sdX aae aad abs @@ -91008,11 +92248,11 @@ aRv aSB aTN aUG -aVz +aNO aWr aWX aXE -aYp +bgn aZh baa baU @@ -91210,12 +92450,12 @@ aad aad aaa aaa -aae -aaa -aaa -bxZ -abL -bxZ +bbT +bbT +bbT +bbT +bcF +bbT swz abs abs @@ -91466,17 +92706,17 @@ sMq aad aad aaa -aaa -aae -aad -aac -edA -abM -acu -adt -adM -aef adm +bbT +bbX +bbZ +bcc +bcG +bcM +bcT +bym +bdi +bdF bxw bym afB @@ -91724,13 +92964,13 @@ aad aad aaa aad -aah -aad -aad -bxZ -bxZ -adq -bxZ +bbU +bbT +bca +bbT +bcH +bcN +bbT adY aei adn @@ -91789,7 +93029,7 @@ bad baX bbL bcA -bdv +bfE beo aZl sPK @@ -91982,11 +93222,11 @@ aac aaa aad aad -aad -aad -aad -bxZ -bxZ +bbT +bcb +bbT +bcI +bcO adu adu aej @@ -92239,11 +93479,11 @@ aac aaa aaa aad -aac -aac -aad -aad -aad +bbY +bdB +bbT +aFB +bcP ady adZ aek @@ -92491,16 +93731,16 @@ sMq sMr sMr aad +adx +sdX +sdX +bbW +bcQ +adq aad -aaa -aaa -aaa -aaa -aaa -aad -aad -aad -aad +bbT +bcK +bdE adu aea aen @@ -92748,16 +93988,16 @@ aad aad aad aad -aac +aKo +aaa +aaa +aef aaa aaa aaa -aaa -aaa -aaa -aad -aad -aad +bbT +bcL +bcR adu aeb aeP @@ -93002,19 +94242,19 @@ aad aad aac aac -aad +adx aaa aaa +sdX aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aac -aac +adq +sdX +sdX +sdX +bbT +bbT +bbU adu adu adu @@ -93259,19 +94499,19 @@ aad aac aac aaa +sdX +aaa +aaa +sdX +aaa +aaa +adq aaa aaa aaa +sdX aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aac +bcS aad aad aad @@ -93324,8 +94564,8 @@ auu avz avF abv -sON -tms +hXc +orV hXc abP jLF @@ -93516,19 +94756,19 @@ aad aaa aaa aaa +pZU aaa +abL +abL +abL +abL +adt +abL +abL +abL +abL aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aac +aKo aac aad aad @@ -93581,8 +94821,8 @@ aux avA avH abv -aad -orV +beA +beV iio tPn wOe @@ -93773,19 +95013,19 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU +sdX +abM +bbQ +bbQ +bbQ +adM +bbV +bbV +bbV +bcD +sdX +pZU aaa aaa aac @@ -93838,9 +95078,9 @@ atF atF atF swG -aad -hns -iXB +beF +beW +beZ hVE sPq hVE @@ -94030,19 +95270,19 @@ aaa aaa aaa aaa +pZU aaa +acu +acu +acu +acu +aef +acu +acu +acu +acu aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +pZU aaa aaa aaa @@ -94094,14 +95334,14 @@ aaa aaa aaa aad -aad -aad -hns -xLe +iio +beB +beX +bfa +bfc +bfi hVE -ajP -hVE -pXH +bfs sVt vCu tin @@ -94287,19 +95527,19 @@ aaa aaa aaa aaa +pZU aaa aaa aaa aaa aaa +bbg aaa aaa aaa aaa aaa -aaa -aaa -aaa +pZU aaa aaa aaa @@ -94349,13 +95589,13 @@ aaa aaa aaa aaa -aac aad -aad -aad -orV +ajP +ajP +aYB +ajP nMh -hVE +beW sPq wPr jIk @@ -94544,19 +95784,19 @@ aaa aaa aaa aaa +sdX aaa +abL +abL +abL +abL +adt +abL +abL +abL +abL aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +sdX aaa aaa aaa @@ -94606,14 +95846,14 @@ aaa aaa aaa aaa -aac -aac aad -aad -orV +ajP +aQE +bex +ajP pdX -hVE -bWO +bfd +bfj oKp dXv sVt @@ -94798,23 +96038,23 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP aaa aaa aaa +pZU +sdX +abM +bbQ +bbQ +bbQ +adM +bbV +bbV +bbV +bcD +sdX +pZU +aaa aaa aaa aaa @@ -94862,15 +96102,15 @@ aaf aaa aaa aaa -aaa aac aad -aad -aad -rpy -jLT -lmr -oRo +ajP +bdP +bez +beY +bfb +bfh +bfk pAN nTg gcw @@ -95055,23 +96295,23 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP aaa aaa aaa +pZU +aaa +acu +acu +acu +acu +aef +acu +acu +acu +acu +aaa +pZU +aaa aaa aaa aaa @@ -95119,15 +96359,15 @@ aaf aaa aaa aaa -aaa -aac aad aad -aad -sVt -bNB -hVE -sPq +ajP +aTn +beD +bdO +beu +mvB +beT hVE lzC sVt @@ -95312,23 +96552,23 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP aaa aaa aaa +pZU +aaa +aaa +aaa +aaa +aaa +adt +aaa +aaa +aaa +aaa +aaa +pZU +aaa aaa aaa aaa @@ -95376,15 +96616,15 @@ aaf aaa aaa aaa -aaa -aac aad -aad -aad -sVt +ajP +ajP +bev +beR +ajP jXX wwT -sPq +beU tFk hVE lzG @@ -95569,23 +96809,23 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP aaa aaa aaa +sdX +sdX +pZU +pZU +pZU +sdX +bcJ +sdX +pZU +pZU +pZU +sdX +sdX +aaa aaa aaa aaa @@ -95633,16 +96873,16 @@ aaa aaa aaa aaa -aaa -aac -aad -aad -aad -meo +ajP +ajP +bdD +bdL +beS +ajP xiZ wvy -sPq -mfj +bfz +bfB mvB mvB kqH @@ -95826,20 +97066,20 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -95890,12 +97130,12 @@ aaa aaa aaa aaa -aaa -aac -aac -aad -aad -sVt +aJO +baN +bdI +bdM +bft +ajP mhf kCG ybw @@ -96083,20 +97323,20 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -96147,12 +97387,12 @@ aaf aaa aaa aaa -aaa -aac -aac -aad -aad -sVt +aJO +bbP +bdJ +bdN +bfw +ajP sVt sVt sVt @@ -96340,20 +97580,20 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -96404,16 +97644,16 @@ aaf aaa aaa aaa -aaa -aaa -aad -aad -eGm -eGm +aJO +aJO +bdK +bew +ajP +ajP eGm meo uiT -scn +bfq bpj iio aad @@ -96597,20 +97837,20 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -96662,10 +97902,10 @@ aaa aaa aaa aaa -aaa -aad -aad -leU +aJO +aJO +aJO +ajP dfK dfK sVt @@ -96854,20 +98094,20 @@ jFP jFP jFP jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP -jFP +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa diff --git a/_maps/map_files/Snaxi/IcemoonUnderground_Above.dmm b/_maps/map_files/Snaxi/IcemoonUnderground_Above.dmm index 403f155854..153ad4265d 100644 --- a/_maps/map_files/Snaxi/IcemoonUnderground_Above.dmm +++ b/_maps/map_files/Snaxi/IcemoonUnderground_Above.dmm @@ -112,7 +112,7 @@ /obj/machinery/light/small{ dir = 8 }, -/turf/closed/mineral/random/snow, +/turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/underground/unexplored/rivers) "eH" = ( /obj/machinery/airalarm{ @@ -581,7 +581,7 @@ desc = "A horn off of a bicycle. This one has been charred to hell and back, yet somehow it still honks."; name = "charred bike horn" }, -/turf/closed/mineral/random/snow, +/turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/underground/unexplored/rivers) "nN" = ( /turf/closed/wall/r_wall, @@ -722,6 +722,9 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) +"rs" = ( +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/underground/unexplored/rivers) "ry" = ( /obj/effect/turf_decal/tile/purple{ dir = 8 @@ -809,6 +812,9 @@ }, /turf/open/floor/plasteel/white, /area/mine/living_quarters) +"sL" = ( +/turf/open/transparent/openspace/icemoon, +/area/icemoon/underground/unexplored/rivers) "sM" = ( /obj/structure/table, /obj/item/storage/firstaid/toxin{ @@ -2367,7 +2373,7 @@ /obj/machinery/light/small{ dir = 1 }, -/turf/closed/mineral/random/snow, +/turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/underground/unexplored/rivers) "WE" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ @@ -29940,9 +29946,9 @@ ah ah ah ah +rs ah -ah -ah +rs ah ah ah @@ -30199,8 +30205,8 @@ ah ah ah ah -ah -ah +rs +rs ah ah ah @@ -30456,8 +30462,8 @@ ah ah ah ah -ah -ah +rs +rs ah ah ah @@ -30712,10 +30718,10 @@ ah ah ah nE -ah -ah -ah -ah +rs +sL +sL +rs ah ah ah @@ -30968,11 +30974,11 @@ ah ah ah ah -ah -ah -ah -ah -ah +rs +rs +rs +sL +rs ah ah ah @@ -31498,8 +31504,8 @@ ah ah ah ah -ah -ah +rs +rs ah ah ah @@ -31749,14 +31755,14 @@ ah ah ah ah +rs +rs +rs +rs ah -ah -ah -ah -ah -ah -ah -ah +rs +rs +rs ah ah ah @@ -32005,14 +32011,14 @@ Gw op nd ah -ah -ah -ah -ah -ah -ah -ah -ah +sL +rs +rs +rs +rs +rs +rs +rs ah ah ah @@ -32262,15 +32268,15 @@ GI Lg nd ah -ah -ah -ah +sL +sL +rs op WE op -ah -ah -ah +rs +rs +rs ah ah ah @@ -32519,17 +32525,17 @@ GN Lu nd ah -ah -ah -ah +rs +rs +rs op sa op -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs ah ah ah @@ -32782,11 +32788,11 @@ nd op WM op -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs ah ah ah @@ -33039,10 +33045,10 @@ Rx ry WO op -ah -ah -ah -ah +rs +rs +rs +rs ah ah ah @@ -33296,9 +33302,9 @@ sa sa sa op -ah -ah -ah +rs +rs +rs ah ah ah @@ -33553,8 +33559,8 @@ TA sa Xf op -ah -ah +rs +rs ah ah ah @@ -33810,8 +33816,8 @@ TA sa sa op -ah -ah +rs +rs ah ah ah @@ -37651,8 +37657,8 @@ ah ah ah ah -ah -ah +rs +rs op sa Ho @@ -37908,8 +37914,8 @@ ah ah ah ah -ah -ah +rs +rs op ET HY @@ -38165,18 +38171,18 @@ ah ah ah ah -ah -ah +rs +rs op op Iq op op -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs ah ah ah @@ -38422,19 +38428,19 @@ ah ah ah ah -ah -ah -ah +rs +rs +rs op Iv op -ah -ah -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs +rs +rs ah ah ah @@ -38680,18 +38686,18 @@ ah ah ah ah -ah -ah +rs +rs op Ho op -ah -ah -ah -ah -ah -ah -ah +rs +rs +sL +rs +rs +rs +rs ah ah ah @@ -38937,18 +38943,18 @@ ah ah ah ah -ah -ah +sL +rs op Ho op -ah -ah -ah -ah -ah -ah -ah +rs +sL +sL +sL +rs +rs +rs ah ah ah @@ -39193,21 +39199,21 @@ ah ah ah ah -ah -ah -ah +sL +sL +rs op Ho op -ah -ah -ah -ah -ah -ah -ah -ah -ah +rs +sL +sL +sL +rs +rs +rs +rs +rs ah ah ah @@ -39444,26 +39450,26 @@ ah ah ah ah +rs +rs +rs ah ah ah ah -ah -ah -ah -ah -ah +rs +rs er IB er -ah -ah -ah -ah -ah -ah -ah -ah +rs +sL +sL +rs +rs +rs +rs +rs ah ah ah @@ -39700,24 +39706,24 @@ ah ah ah ah +rs +rs +rs +rs +rs ah ah ah -ah -ah -ah -ah -ah -ah -ah +rs +rs er IB er -ah -ah -ah -ah -ah +rs +sL +sL +rs +rs ah ah ah @@ -39957,24 +39963,24 @@ ah ah ah ah -ah +rs eZ fB er +rs ah ah ah -ah -ah -ah +rs +rs er IB er -ah -ah -ah -ah -ah +rs +rs +sL +sL +rs ah ah ah @@ -40213,25 +40219,25 @@ ah ah ah ah -ah -ah +rs +rs er fC er +rs +rs ah ah -ah -ah -ah -ah +rs +rs er IF er -ah -ah -ah -ah -ah +rs +rs +sL +sL +rs ah ah ah @@ -40470,25 +40476,25 @@ ah ah ah ah -ah +rs er er fD er er +rs ah -ah -ah -ah +rs +rs Be er IK er er -ah -ah -ah -ah +rs +rs +rs +rs ah ah ah @@ -40743,8 +40749,8 @@ IM gS er eq -ah -ah +rs +rs ah ah ah @@ -40983,7 +40989,7 @@ ah ah ah ah -ah +rs eq eH fb @@ -41000,8 +41006,8 @@ IB fC Nt eq -ah -ah +rs +rs ah ah ah @@ -41240,7 +41246,7 @@ ah ah ah ah -ah +rs er eI fc @@ -41497,7 +41503,7 @@ ah ah ah ah -ah +rs er eJ fd @@ -41774,8 +41780,8 @@ er Tk NK er -ah -ah +rs +rs ah ah ah @@ -42009,7 +42015,7 @@ ah ah ah ah -ah +rs dW ei es @@ -42031,9 +42037,9 @@ Rf Tn NP VC -ah -ah -ah +rs +rs +rs ah ah ah @@ -42265,8 +42271,8 @@ ah ah ah ah -ah -ah +rs +rs dX ej et @@ -42288,8 +42294,8 @@ er To UJ er -ah -ah +rs +rs ah ah ah @@ -42522,8 +42528,8 @@ ah ah ah ah -ah -ah +rs +rs dX ej eu @@ -42780,7 +42786,7 @@ ah ah ah ah -ah +rs dW ek ew @@ -44069,9 +44075,9 @@ ah ah ah ex -ah -ah -ah +rs +rs +rs ex ah ah @@ -44324,13 +44330,13 @@ ah ah ah ah -ah -ah -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs +rs +rs ah ah ah @@ -44581,13 +44587,13 @@ ah ah ah ah -ah -ah -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs +rs +rs ah ah ah @@ -44839,11 +44845,11 @@ ah ah ah ah -ah -ah -ah -ah -ah +rs +rs +rs +rs +rs ah ah ah @@ -45097,9 +45103,9 @@ ah ah ah ah -ah -ah -ah +rs +rs +rs ah ah ah diff --git a/_maps/map_files/Snaxi/IcemoonUnderground_Below.dmm b/_maps/map_files/Snaxi/IcemoonUnderground_Below.dmm index 42971e4315..79e5080644 100644 --- a/_maps/map_files/Snaxi/IcemoonUnderground_Below.dmm +++ b/_maps/map_files/Snaxi/IcemoonUnderground_Below.dmm @@ -5,6 +5,9 @@ "b" = ( /turf/closed/mineral/random/high_chance/snow, /area/icemoon/underground/unexplored/rivers) +"c" = ( +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/underground/unexplored/rivers) "d" = ( /turf/closed/wall, /area/icemoon/underground/explored) @@ -19,6 +22,9 @@ /obj/item/gps/mining, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/underground/explored) +"G" = ( +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/mine/maintenance) "N" = ( /obj/item/flashlight/lantern{ on = 1 @@ -33,6 +39,22 @@ /obj/structure/ladder, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/underground/explored) +"X" = ( +/obj/machinery/telecomms/relay/preset/mining, +/obj/machinery/bluespace_beacon, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/structure/window/reinforced, +/obj/machinery/door/window/eastright{ + dir = 8; + req_access_txt = "48" + }, +/turf/open/floor/circuit, +/area/icemoon/underground/explored) (1,1,1) = {" a @@ -39499,9 +39521,9 @@ a a a a -a -a -a +c +c +c a a a @@ -40011,13 +40033,13 @@ a a a a -a +c e i h h e -a +c a a a @@ -40268,13 +40290,13 @@ a a a a -a +c h h T h h -a +c a a a @@ -40525,13 +40547,13 @@ a a a a -a +c e N h -h +G e -a +c a a a @@ -40786,7 +40808,7 @@ a d O h -e +X d a a @@ -41041,9 +41063,9 @@ a a a a -a -a -a +c +c +c a a a diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm index 45e6e4dee0..27af3be101 100644 --- a/_maps/map_files/Snaxi/Snaxi.dmm +++ b/_maps/map_files/Snaxi/Snaxi.dmm @@ -254,10 +254,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "aar" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/sign/departments/botany, -/turf/open/floor/plating, -/area/hydroponics) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/fore) "aas" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ @@ -285,7 +286,6 @@ /obj/structure/sign/directions/engineering{ dir = 4; icon_state = "direction_eng"; - pixel_x = 0; pixel_y = 40 }, /turf/open/floor/plasteel, @@ -310,6 +310,9 @@ dir = 1 }, /obj/machinery/disposal/bin, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "aaw" = ( @@ -400,7 +403,6 @@ /obj/structure/sign/directions/supply{ dir = 4; icon_state = "direction_supply"; - pixel_x = 0; pixel_y = 28 }, /turf/open/floor/plasteel, @@ -474,7 +476,6 @@ /obj/structure/sign/directions/supply{ dir = 4; icon_state = "direction_supply"; - pixel_x = 0; pixel_y = 32 }, /obj/structure/sign/directions/evac{ @@ -502,7 +503,6 @@ }, /obj/structure/sign/directions/evac{ dir = 4; - pixel_x = 0; pixel_y = 40 }, /turf/open/floor/plasteel/white/corner{ @@ -516,13 +516,6 @@ }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/fitness/recreation) -"aaM" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/atmospherics/components/binary/valve{ - dir = 4 - }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) "aaN" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/machinery/quantumpad{ @@ -569,7 +562,6 @@ /obj/structure/sign/directions/supply{ dir = 4; icon_state = "direction_supply"; - pixel_x = 0; pixel_y = 36 }, /obj/structure/sign/directions/engineering{ @@ -602,7 +594,8 @@ /obj/structure/sign/departments/restroom{ pixel_x = 32 }, -/turf/open/floor/carpet, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/wood, /area/crew_quarters/dorms) "aaV" = ( /obj/structure/sign/directions/evac{ @@ -612,9 +605,7 @@ }, /obj/structure/sign/directions/security{ dir = 8; - icon_state = "direction_sec"; - pixel_x = 0; - pixel_y = 0 + icon_state = "direction_sec" }, /obj/structure/sign/directions/command{ dir = 8; @@ -673,8 +664,8 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/sign/mining{ - pixel_x = 32 +/obj/machinery/light{ + dir = 4 }, /turf/open/floor/plasteel, /area/hallway/primary/central) @@ -942,7 +933,7 @@ /obj/structure/sign/poster/official/fashion{ pixel_y = -32 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "abB" = ( /obj/structure/cable{ @@ -1080,13 +1071,14 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "abL" = ( -/obj/structure/table, -/obj/item/mmi, -/obj/item/mmi, -/obj/item/mmi, /obj/structure/sign/poster/official/state_laws{ pixel_y = -32 }, +/obj/machinery/camera{ + c_tag = "Robotics Lab South"; + dir = 1; + network = list("ss13","rd") + }, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "abM" = ( @@ -1184,14 +1176,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "abU" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 5 - }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "abV" = ( /obj/effect/turf_decal/tile/red{ dir = 1 @@ -1358,7 +1344,9 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/machinery/atmospherics/components/binary/valve{ + dir = 4 + }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "acV" = ( @@ -1568,8 +1556,9 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 9 + dir = 4 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "aeG" = ( @@ -1711,6 +1700,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 9 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "akB" = ( @@ -1858,7 +1848,6 @@ /obj/structure/table/reinforced, /obj/machinery/door/window/eastright{ base_state = "left"; - dir = 8; icon_state = "left"; name = "Chemistry Desk"; req_access_txt = "33" @@ -1866,6 +1855,10 @@ /obj/machinery/door/firedoor/border_only{ dir = 8 }, +/obj/machinery/door/window/eastright{ + dir = 8; + name = "Chemistry Desk" + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "anw" = ( @@ -2075,8 +2068,8 @@ /obj/machinery/door/firedoor/border_only{ dir = 1 }, -/obj/machinery/door/airlock/external, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plasteel, /area/hallway/primary/port) "arE" = ( @@ -2164,6 +2157,7 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "asE" = ( @@ -2505,17 +2499,10 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/door/airlock/highsecurity{ - name = "AI Upload Access"; - req_access_txt = "16" - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plasteel/dark, +/turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/ai_upload) "axc" = ( /obj/structure/table, @@ -2604,17 +2591,9 @@ /obj/structure/plasticflaps/opaque, /turf/open/floor/plasteel/dark, /area/science/lab) -"axL" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 10 - }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) "axN" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible{ - dir = 10 - }, -/turf/open/floor/plating/asteroid/snow/icemoon, +/obj/structure/fluff/railing, +/turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors) "ayk" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -2626,7 +2605,14 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/closed/wall/r_wall, +/obj/machinery/door/airlock/highsecurity{ + name = "AI Upload Access"; + req_access_txt = "16" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload) "aym" = ( /obj/structure/cable{ @@ -2741,20 +2727,34 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/conveyor_switch/oneway{ - dir = 8; - id = "robo2" - }, /obj/machinery/firealarm{ dir = 8; pixel_x = 24 }, +/obj/structure/table, +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" + }, +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" + }, +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" + }, +/obj/item/healthanalyzer, +/obj/item/healthanalyzer, +/obj/item/healthanalyzer, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "ayC" = ( -/obj/machinery/mecha_part_fabricator, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/fluff/railing/corner{ + dir = 8 + }, +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "ayD" = ( /obj/structure/cable{ icon_state = "0-4" @@ -2805,6 +2805,7 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/maintenance/department/electrical) "azq" = ( @@ -2890,20 +2891,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "azH" = ( -/obj/machinery/conveyor{ - dir = 8; - id = "robo2" +/obj/structure/fluff/railing{ + dir = 4 }, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/glass{ - amount = 20; - pixel_x = -3; - pixel_y = 6 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "aAe" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/structure/disposalpipe/segment{ @@ -3136,24 +3128,11 @@ /turf/open/floor/plasteel/white, /area/science/robotics/lab) "aCr" = ( -/obj/structure/table, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" +/obj/structure/fluff/railing{ + dir = 8 }, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" - }, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" - }, -/obj/item/healthanalyzer, -/obj/item/healthanalyzer, -/obj/item/healthanalyzer, -/turf/open/floor/plasteel/white, -/area/science/robotics/lab) +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "aCV" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -3199,8 +3178,7 @@ /area/hallway/primary/port) "aDc" = ( /obj/effect/landmark/start/scientist, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel/white, +/turf/open/floor/circuit, /area/science/lab) "aDd" = ( /obj/structure/cable{ @@ -3226,10 +3204,6 @@ /obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"aDf" = ( -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel/white, -/area/science/lab) "aDg" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 @@ -3380,8 +3354,10 @@ /turf/open/floor/plasteel, /area/security/checkpoint/medical) "aEE" = ( -/obj/machinery/rnd/destructive_analyzer, -/turf/open/floor/circuit, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel/white, /area/science/lab) "aEF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ @@ -3390,25 +3366,24 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "aEG" = ( -/turf/open/floor/circuit, -/area/science/lab) -"aEH" = ( -/obj/machinery/computer/rdconsole/core{ - dir = 1 +/obj/structure/fluff/railing{ + dir = 10 }, +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) +"aEH" = ( /obj/machinery/light, /turf/open/floor/circuit, /area/science/lab) "aEI" = ( -/obj/machinery/rnd/production/protolathe/department/science, +/obj/machinery/rnd/destructive_analyzer, /turf/open/floor/circuit, /area/science/lab) "aEJ" = ( /turf/closed/wall/r_wall, /area/hallway/secondary/entry) "aEK" = ( -/obj/machinery/rnd/production/circuit_imprinter/department/science, -/obj/item/reagent_containers/glass/beaker/sulphuric, +/obj/machinery/rnd/production/protolathe/department/science, /turf/open/floor/circuit, /area/science/lab) "aEL" = ( @@ -3606,35 +3581,11 @@ /turf/open/floor/circuit, /area/science/robotics/mechbay) "aHK" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical{ - pixel_x = -2; - pixel_y = -1 +/obj/structure/fluff/railing{ + dir = 6 }, -/obj/item/storage/toolbox/electrical{ - pixel_x = 1; - pixel_y = 6 - }, -/obj/item/clothing/head/welding{ - pixel_x = -3; - pixel_y = 5 - }, -/obj/item/clothing/head/welding{ - pixel_x = -3; - pixel_y = 5 - }, -/obj/item/clothing/glasses/welding, -/obj/item/clothing/glasses/welding, -/obj/item/multitool{ - pixel_x = 3 - }, -/obj/item/multitool{ - pixel_x = 3 - }, -/obj/item/storage/belt/utility, -/obj/item/storage/belt/utility, -/turf/open/floor/plasteel/white, -/area/science/robotics/lab) +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "aHU" = ( /obj/machinery/rnd/production/techfab/department/service, /turf/open/floor/plating, @@ -3749,11 +3700,12 @@ /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) "aKa" = ( -/obj/machinery/atmospherics/components/binary/valve/digital{ - dir = 4 +/obj/structure/cable{ + icon_state = "0-2" }, -/turf/closed/wall/r_wall, -/area/storage/atmos) +/obj/machinery/power/tracker, +/turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, +/area/solar/port/fore) "aKf" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ @@ -4062,14 +4014,14 @@ /turf/open/floor/wood, /area/security/courtroom) "aNL" = ( -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/firedoor/border_only{ dir = 1; name = "north facing firelock" }, /obj/structure/fans/tiny, -/turf/open/floor/carpet, +/obj/machinery/door/airlock/external/glass, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "aNS" = ( /obj/machinery/turnstile{ @@ -4136,18 +4088,12 @@ /obj/structure/cable{ icon_state = "0-4" }, -/obj/machinery/power/apc{ - areastring = "/area/storage/atmos"; - dir = 8; - name = "Atmospherics APC"; - pixel_x = -24 - }, /obj/structure/extinguisher_cabinet{ pixel_y = -30 }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "aOq" = ( /obj/structure/cable{ icon_state = "2-4" @@ -4159,7 +4105,7 @@ dir = 8 }, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "aOr" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, @@ -4203,9 +4149,11 @@ /turf/open/floor/plating, /area/security/checkpoint/medical) "aPC" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/storage/atmos) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "aPD" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -4213,10 +4161,17 @@ }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "aPE" = ( -/turf/closed/wall/r_wall, -/area/storage/atmos) +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/solar{ + id = "auxsolareast"; + name = "Port Auxiliary Solar Array" + }, +/turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, +/area/solar/port/fore) "aPY" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -4286,7 +4241,7 @@ icon_state = "2-4" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "aQT" = ( /obj/structure/cable{ icon_state = "1-2" @@ -4352,6 +4307,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 9 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "aSI" = ( @@ -4700,6 +4656,13 @@ }, /turf/open/floor/plating, /area/quartermaster/storage) +"bfo" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "bfB" = ( /obj/structure/cable{ icon_state = "1-2" @@ -4755,6 +4718,12 @@ /obj/machinery/vending/coffee, /turf/open/floor/plasteel/dark, /area/maintenance/department/bridge) +"bjR" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "bjU" = ( /obj/machinery/airalarm{ dir = 8; @@ -4804,13 +4773,6 @@ /obj/machinery/holopad, /turf/open/floor/plasteel/dark, /area/maintenance/department/bridge) -"blD" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "blI" = ( /obj/machinery/hydroponics/soil, /obj/item/seeds/ambrosia, @@ -4977,6 +4939,12 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"bqb" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "bqx" = ( /obj/structure/table/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -5185,9 +5153,6 @@ /area/icemoon/surface/outdoors) "buF" = ( /obj/machinery/light, -/obj/structure/window/plasma/reinforced{ - dir = 4 - }, /obj/structure/table, /obj/item/clothing/gloves/color/yellow, /obj/item/clothing/gloves/color/yellow, @@ -5200,6 +5165,9 @@ dir = 8 }, /obj/item/pipe_dispenser, +/obj/structure/window/reinforced{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "buI" = ( @@ -6106,9 +6074,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/airalarm{ - pixel_y = 28 - }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -6218,9 +6183,6 @@ /obj/effect/turf_decal/tile/brown{ dir = 4 }, -/obj/machinery/light{ - dir = 4 - }, /turf/open/floor/plasteel, /area/hallway/primary/central) "bCM" = ( @@ -6414,6 +6376,17 @@ /obj/machinery/vending/wardrobe/science_wardrobe, /turf/open/floor/plasteel/white, /area/science/misc_lab) +"bEp" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/grille, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "bEJ" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/effect/turf_decal/tile/purple{ @@ -6921,7 +6894,7 @@ /obj/structure/window/reinforced, /obj/structure/table/reinforced, /obj/machinery/button/door{ - id = "xenobio2"; + id = "xenobiospec"; name = "Containment Blast Doors"; pixel_y = 4; req_access_txt = "55" @@ -6982,7 +6955,7 @@ req_access_txt = "55" }, /obj/machinery/door/poddoor/preopen{ - id = "xenobio2"; + id = "xenobiospec"; name = "containment blast door" }, /turf/open/floor/engine, @@ -7138,35 +7111,9 @@ /obj/machinery/disposal/bin, /turf/open/floor/plasteel/cult, /area/lawoffice) -"bJQ" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "Arrivals Airlock" - }, -/obj/structure/fans/tiny, -/turf/open/floor/plating, -/area/hallway/secondary/exit/departure_lounge) "bKl" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, /obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel, +/turf/open/transparent/glass/reinforced, /area/crew_quarters/fitness) "bKo" = ( /obj/machinery/door/airlock/public/glass{ @@ -7245,7 +7192,7 @@ icon_state = "0-4" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "bLI" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -7477,6 +7424,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/recharge_station, /turf/open/floor/plasteel, /area/maintenance/department/electrical) "bOp" = ( @@ -7621,16 +7569,16 @@ dir = 8; name = "west facing firelock" }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /obj/machinery/door/poddoor/preopen{ - id = "xenobio2"; + id = "xenobiospec"; name = "containment blast door" }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /turf/open/floor/engine, /area/science/xenobiology) "bPW" = ( @@ -8578,23 +8526,14 @@ "chp" = ( /turf/open/floor/plating, /area/maintenance/aft) -"chN" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "chZ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/maintenance/solars/port/fore) +"cih" = ( +/obj/structure/cable, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "cio" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -8822,7 +8761,7 @@ icon_state = "0-4" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "cly" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -9154,6 +9093,12 @@ }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/fitness/recreation) +"cvN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) "cwm" = ( /obj/machinery/vending/boozeomat, /obj/machinery/firealarm{ @@ -9506,15 +9451,6 @@ }, /turf/open/floor/plating, /area/bridge) -"cDO" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "cDS" = ( /obj/structure/bodycontainer/morgue{ dir = 8 @@ -9542,6 +9478,12 @@ /obj/structure/reflector/single, /turf/open/floor/plating, /area/engine/storage) +"cEs" = ( +/obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/structure/disposalpipe/segment, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "cFm" = ( /obj/structure/reagent_dispensers/peppertank{ pixel_x = -30 @@ -9698,7 +9640,7 @@ }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "cKQ" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 4 @@ -9723,7 +9665,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/plasteel, +/turf/open/floor/wood, /area/crew_quarters/fitness) "cLC" = ( /obj/effect/turf_decal/tile/brown{ @@ -9770,7 +9712,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "cNE" = ( /obj/structure/cable{ @@ -10043,6 +9985,13 @@ "cTO" = ( /turf/closed/wall/r_wall, /area/quartermaster/miningoffice) +"cTV" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "cUd" = ( /obj/structure/cable{ icon_state = "1-2" @@ -10062,6 +10011,40 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) +"cUs" = ( +/obj/effect/landmark/start/ai, +/obj/item/radio/intercom{ + freerange = 1; + name = "Common Channel"; + pixel_x = 25; + pixel_y = -4 + }, +/obj/item/radio/intercom{ + freerange = 1; + frequency = 1447; + name = "Private Channel"; + pixel_x = 25; + pixel_y = -13 + }, +/obj/item/radio/intercom{ + freerange = 1; + listening = 0; + name = "Custom Channel"; + pixel_x = 25; + pixel_y = 7 + }, +/obj/machinery/button/door{ + id = "AI Chamber entrance shutters"; + name = "AI Chamber entrance shutters control"; + pixel_x = -7; + pixel_y = -24; + req_access_txt = "16" + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/circuit, +/area/ai_monitored/turret_protected/ai) "cUC" = ( /obj/structure/chair, /obj/effect/landmark/start/geneticist, @@ -10090,6 +10073,12 @@ }, /turf/open/floor/pod/dark, /area/maintenance/starboard) +"cVa" = ( +/obj/structure/fluff/railing{ + dir = 9 + }, +/turf/open/transparent/openspace/icemoon, +/area/engine/atmospherics_engine) "cVu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/blue{ @@ -10143,6 +10132,10 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"cWI" = ( +/obj/structure/cable, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "cWO" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 4 @@ -10167,11 +10160,9 @@ /turf/open/floor/plasteel/dark, /area/security/prison) "cXI" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/closed/wall/r_wall, -/area/ai_monitored/turret_protected/ai) +/obj/structure/cable, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "cXO" = ( /obj/structure/cable, /obj/effect/landmark/start/ai/secondary, @@ -10495,21 +10486,23 @@ name = "Port Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "dfy" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/structure/cable{ icon_state = "1-4" }, /obj/structure/cable{ icon_state = "2-4" }, +/obj/effect/landmark/event_spawn, +/obj/machinery/flasher{ + id = "AI"; + pixel_x = -26; + pixel_y = 3 + }, /obj/machinery/ai_slipper{ uses = 10 }, -/obj/effect/landmark/event_spawn, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) "dfV" = ( @@ -10817,8 +10810,8 @@ dir = 4 }, /obj/machinery/door/airlock/atmos{ - name = "Atmospherics"; - req_access_txt = "24" + name = "Antimatter Engine"; + req_access_txt = "10" }, /obj/machinery/door/firedoor/border_only{ dir = 8; @@ -10886,10 +10879,11 @@ /obj/structure/cable{ icon_state = "2-4" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/structure/cable{ + icon_state = "2-8" }, -/turf/open/floor/carpet, +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, +/turf/open/floor/wood, /area/crew_quarters/dorms) "duI" = ( /obj/structure/cable{ @@ -10934,6 +10928,7 @@ /obj/structure/disposalpipe/segment{ dir = 6 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "dvs" = ( @@ -10946,7 +10941,7 @@ /obj/machinery/door/firedoor/border_only{ name = "south facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "dvw" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -11053,12 +11048,6 @@ }, /turf/open/floor/pod/dark, /area/maintenance/starboard) -"dAi" = ( -/obj/structure/sign/warning/pods{ - pixel_x = -32 - }, -/turf/open/floor/carpet, -/area/crew_quarters/dorms) "dAs" = ( /obj/structure/cable{ icon_state = "1-2" @@ -11158,36 +11147,11 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "dDC" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/fluff/railing{ dir = 1 }, -/obj/structure/closet/crate/engineering{ - name = "Antimatter Engine Crate" - }, -/obj/machinery/power/am_control_unit, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_shielding_container, -/obj/item/am_containment, -/obj/item/am_containment, -/turf/open/floor/plasteel/dark, -/area/engine/secure_construction) +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "dDK" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 6 @@ -11265,9 +11229,11 @@ /turf/closed/wall, /area/quartermaster/qm) "dFJ" = ( -/obj/effect/turf_decal/stripes/corner, -/turf/open/floor/plasteel/white, -/area/science/lab) +/obj/structure/fluff/railing{ + dir = 5 + }, +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "dGb" = ( /obj/structure/cable{ icon_state = "1-8" @@ -11354,7 +11320,7 @@ /obj/machinery/door/firedoor/border_only{ name = "south facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "dJc" = ( /obj/structure/cable{ @@ -11386,7 +11352,7 @@ /obj/structure/disposalpipe/segment{ dir = 6 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "dKw" = ( /obj/structure/cable{ @@ -11437,6 +11403,11 @@ "dMj" = ( /turf/closed/wall/r_wall, /area/ai_monitored/nuke_storage) +"dMo" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "dMI" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -12102,6 +12073,7 @@ dir = 1; sortType = 26 }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "egM" = ( @@ -12218,15 +12190,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/brig) -"ejw" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "ekw" = ( /obj/structure/chair{ dir = 1 @@ -12287,6 +12250,18 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/dark, /area/hallway/secondary/exit/departure_lounge) +"eoH" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "eoL" = ( /obj/structure/chair{ dir = 4 @@ -12354,9 +12329,6 @@ /turf/open/floor/plasteel/dark, /area/engine/engineering) "ery" = ( -/obj/machinery/light{ - dir = 8 - }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -12371,10 +12343,6 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/radio/intercom{ - name = "Station Intercom (General)"; - pixel_x = -28 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload_foyer) "erG" = ( @@ -12587,6 +12555,12 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) +"eyc" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/crew_quarters/dorms) "eyP" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -12690,6 +12664,13 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/aft) +"eCS" = ( +/obj/machinery/door/airlock{ + id_tag = "Dorm5"; + name = "Room Four" + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "eDr" = ( /obj/structure/cable{ icon_state = "4-8" @@ -12870,7 +12851,7 @@ /area/hallway/primary/central) "eHK" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, /turf/open/floor/plating, @@ -12982,25 +12963,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/aft) -"eLl" = ( -/obj/structure/window{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/structure/window{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "eLm" = ( /obj/structure/cable{ icon_state = "4-8" @@ -13174,10 +13136,6 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) -"eOO" = ( -/obj/structure/weightmachine/weightlifter, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "eOZ" = ( /obj/machinery/atmospherics/components/binary/pump/on, /turf/open/floor/plasteel/dark, @@ -13417,6 +13375,20 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/mineral/wood, /area/maintenance/bar) +"eXy" = ( +/obj/effect/turf_decal/stripes/corner, +/turf/open/floor/plasteel/white, +/area/science/lab) +"eXO" = ( +/obj/structure/table, +/obj/item/mmi, +/obj/item/mmi, +/obj/item/mmi, +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "eYe" = ( /obj/machinery/conveyor{ dir = 4; @@ -13489,7 +13461,7 @@ icon_state = "1-4" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/aft) "faR" = ( /obj/structure/window/reinforced{ dir = 8 @@ -13497,7 +13469,7 @@ /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/effect/landmark/blobstart, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "faV" = ( /obj/machinery/light{ dir = 4 @@ -13819,6 +13791,13 @@ /obj/machinery/space_heater, /turf/open/floor/plating, /area/icemoon/surface/outdoors) +"fkA" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "fkC" = ( /obj/machinery/atmospherics/pipe/simple/green/visible, /turf/closed/wall/r_wall, @@ -13914,9 +13893,14 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "fne" = ( -/obj/effect/landmark/start/roboticist, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "fni" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/atmos/carbon_output{ dir = 8 @@ -13957,6 +13941,11 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/engine/engineering) +"fol" = ( +/obj/machinery/rnd/production/circuit_imprinter/department/science, +/obj/item/reagent_containers/glass/beaker/sulphuric, +/turf/open/floor/circuit, +/area/science/lab) "foy" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -13986,17 +13975,6 @@ /turf/open/floor/plating, /area/maintenance/disposal) "fpS" = ( -/obj/structure/table, -/obj/item/hemostat, -/obj/item/retractor, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/circular_saw, -/obj/item/cautery{ - pixel_x = 4 - }, -/obj/item/surgical_drapes, /obj/machinery/airalarm{ pixel_y = 23 }, @@ -14004,7 +13982,14 @@ c_tag = "Robotics Lab"; network = list("ss13","rd") }, -/turf/open/floor/plasteel/white, +/obj/machinery/mecha_part_fabricator, +/obj/item/stack/sheet/glass{ + amount = 20; + pixel_x = -3; + pixel_y = 6 + }, +/obj/item/stack/sheet/metal/fifty, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "fqj" = ( /obj/machinery/field/generator, @@ -14088,7 +14073,7 @@ icon_state = "1-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "fsA" = ( /obj/structure/bodycontainer/morgue, /obj/effect/turf_decal/tile/blue{ @@ -14115,11 +14100,8 @@ /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "ftH" = ( -/obj/machinery/mineral/ore_redemption{ - input_dir = 2; - output_dir = 1 - }, -/turf/open/floor/plating, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/space/basic, /area/quartermaster/miningdock) "ftM" = ( /obj/structure/cable{ @@ -14189,11 +14171,6 @@ /turf/open/floor/plasteel, /area/engine/engineering) "fvz" = ( -/obj/structure/table/optable{ - name = "Robotics Operating Table" - }, -/obj/item/tank/internals/anesthetic, -/obj/item/clothing/mask/breath, /obj/structure/extinguisher_cabinet{ pixel_y = 30 }, @@ -14355,6 +14332,9 @@ c_tag = "Bathrooms"; dir = 1 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/dorms) "fBG" = ( @@ -14376,9 +14356,6 @@ /turf/open/floor/engine, /area/engine/atmospherics_engine) "fCQ" = ( -/obj/structure/toilet/secret/low_loot{ - pixel_y = 14 - }, /obj/machinery/button/door{ id = "Bath2"; name = "Door Bolt Control"; @@ -14391,6 +14368,7 @@ dir = 8 }, /obj/effect/landmark/blobstart, +/obj/machinery/recharge_station, /turf/open/floor/plasteel/freezer, /area/crew_quarters/dorms) "fDi" = ( @@ -14416,6 +14394,13 @@ "fDJ" = ( /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) +"fEz" = ( +/obj/machinery/computer/operating, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "fET" = ( /obj/effect/turf_decal/tile/neutral, /obj/machinery/camera{ @@ -14514,7 +14499,18 @@ dir = 4 }, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) +"fIk" = ( +/obj/machinery/button/door{ + id = "holoprivacy"; + name = "Holodeck Privacy"; + pixel_x = 24; + pixel_y = 7 + }, +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/holodeck/rec_center) "fIu" = ( /obj/structure/cable{ icon_state = "1-8" @@ -14733,11 +14729,11 @@ pixel_y = -28 }, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "fNh" = ( /obj/structure/cable, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "fNC" = ( /obj/structure/cable{ icon_state = "1-2" @@ -14869,6 +14865,9 @@ dir = 8; name = "west facing firelock" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plating, /area/crew_quarters/dorms) "fPN" = ( @@ -14955,6 +14954,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"fSb" = ( +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "fSw" = ( /obj/structure/cable{ icon_state = "2-4" @@ -14998,8 +15004,14 @@ /obj/machinery/light{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) +"fUc" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "fUm" = ( /obj/structure/cable{ icon_state = "1-2" @@ -15044,7 +15056,7 @@ icon_state = "2-4" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "fVT" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /turf/open/floor/engine, @@ -15273,6 +15285,12 @@ /obj/item/storage/fancy/donut_box, /turf/open/floor/plasteel, /area/security/checkpoint/supply) +"gdH" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) "gdL" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 @@ -15441,6 +15459,12 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/engine/engineering) +"gjZ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) "gkl" = ( /obj/machinery/jukebox, /turf/open/floor/wood, @@ -15504,28 +15528,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"gls" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/machinery/door/window/westright{ - name = "Red Corner" - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "gmf" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/disposalpipe/segment, @@ -15699,9 +15701,6 @@ /turf/closed/wall, /area/security/courtroom) "grZ" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/structure/table, /obj/item/aiModule/core/full/custom, /obj/item/aiModule/core/freeformcore, @@ -15713,6 +15712,9 @@ dir = 1; network = list("aiupload") }, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/circuit, /area/ai_monitored/turret_protected/ai_upload) "gsr" = ( @@ -15814,12 +15816,11 @@ /turf/open/floor/plasteel/dark, /area/bridge) "guI" = ( -/obj/machinery/light/floor, -/obj/structure/disposalpipe/segment{ - dir = 5 +/obj/structure/cable{ + icon_state = "0-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/fore) "guR" = ( /obj/structure/table/glass, /obj/effect/turf_decal/tile/yellow{ @@ -16063,7 +16064,7 @@ dir = 1 }, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "gCG" = ( /obj/structure/closet/firecloset, /turf/open/floor/plating, @@ -16078,15 +16079,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "gCO" = ( -/obj/machinery/light, -/obj/machinery/door/airlock/public/glass{ - name = "Holodeck Door" - }, -/obj/structure/fans/tiny, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plasteel/white, +/turf/open/floor/wood, /area/crew_quarters/dorms) "gCS" = ( /obj/structure/bodycontainer/morgue, @@ -16240,6 +16236,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"gIW" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "gJi" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/machinery/atmospherics/pipe/simple/green/visible{ @@ -16486,7 +16488,7 @@ }, /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "gPE" = ( /obj/machinery/portable_atmospherics/pump, /obj/machinery/firealarm{ @@ -16662,7 +16664,7 @@ icon_state = "2-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "gTH" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -16692,11 +16694,18 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "gUc" = ( -/obj/machinery/light, -/turf/open/floor/plasteel/white, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Dorms Central"; + dir = 1 + }, +/turf/open/floor/carpet, /area/crew_quarters/dorms) "gUw" = ( /obj/structure/plasticflaps, @@ -16773,7 +16782,8 @@ /obj/structure/cable{ icon_state = "2-8" }, -/turf/open/floor/plasteel/white, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "gXE" = ( /obj/structure/table, @@ -17108,13 +17118,16 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "hiO" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "hjv" = ( @@ -17158,6 +17171,14 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) +"hlQ" = ( +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = 30 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "hlT" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -17168,9 +17189,6 @@ /obj/structure/cable{ icon_state = "2-8" }, -/obj/structure/cable{ - icon_state = "1-2" - }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) "hmM" = ( @@ -17195,6 +17213,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"hnN" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/structure/disposalpipe/segment, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "hnO" = ( /obj/machinery/atmospherics/components/unary/cryo_cell, /turf/open/floor/plasteel/white, @@ -17219,20 +17246,10 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "hop" = ( -/obj/structure/window{ - dir = 4 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "4-8" }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/landmark/start/assistant, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "hoq" = ( @@ -17342,6 +17359,7 @@ /obj/machinery/light{ dir = 1 }, +/obj/machinery/vending/cigarette, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "hrN" = ( @@ -17361,15 +17379,14 @@ /turf/open/floor/plasteel, /area/quartermaster/miningdock) "hrS" = ( -/obj/effect/turf_decal/tile/neutral, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "hse" = ( /obj/structure/cable{ - icon_state = "1-4" + icon_state = "0-4" }, -/turf/open/floor/circuit/off, -/area/ai_monitored/turret_protected/ai) +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "hsl" = ( /turf/open/floor/plating, /area/maintenance/starboard) @@ -17419,12 +17436,6 @@ }, /turf/open/floor/wood, /area/bridge/meeting_room) -"hsQ" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "hta" = ( /obj/structure/cable{ icon_state = "1-2" @@ -17471,11 +17482,14 @@ /turf/open/floor/engine/co2, /area/engine/atmos) "huF" = ( -/obj/machinery/mineral/stacking_unit_console{ - machinedir = 4 +/obj/structure/cable{ + icon_state = "1-8" }, -/turf/closed/wall, -/area/maintenance/disposal) +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "huQ" = ( /obj/machinery/power/terminal{ dir = 1 @@ -17507,6 +17521,14 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"hvG" = ( +/obj/machinery/light, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "hwg" = ( /obj/machinery/computer/teleporter{ dir = 8 @@ -17567,7 +17589,7 @@ }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "hxP" = ( /obj/machinery/door/airlock/medical/glass{ id_tag = "MedbayFoyer"; @@ -17589,6 +17611,18 @@ /obj/structure/closet/secure_closet/personal/cabinet, /turf/open/floor/carpet, /area/quartermaster/miningoffice) +"hyx" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/airalarm{ + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/quartermaster/miningdock) "hyz" = ( /obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, @@ -17680,7 +17714,7 @@ dir = 1; name = "north facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "hBb" = ( /obj/machinery/camera{ @@ -17710,6 +17744,10 @@ /obj/machinery/vending/medical, /turf/open/floor/plasteel/white, /area/medical/virology) +"hBM" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel/white, +/area/science/lab) "hBQ" = ( /obj/structure/cable{ icon_state = "2-4" @@ -17720,6 +17758,16 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/port) +"hCx" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8; + name = "west facing firelock" + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "hCD" = ( /obj/structure/cable{ icon_state = "4-8" @@ -17829,7 +17877,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "hFG" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -17855,7 +17903,7 @@ icon_state = "0-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "hGU" = ( /obj/structure/closet/secure_closet/personal/cabinet{ pixel_x = -8 @@ -17896,6 +17944,12 @@ }, /turf/open/floor/plasteel, /area/engine/atmospherics_engine) +"hHV" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) "hHW" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -18001,7 +18055,7 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "hKt" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -18127,7 +18181,7 @@ /area/engine/secure_construction) "hNT" = ( /obj/effect/landmark/event_spawn, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "hNZ" = ( /obj/effect/turf_decal/tile/yellow{ @@ -18154,7 +18208,7 @@ }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "hOw" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ @@ -18403,6 +18457,10 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"hUg" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "hUo" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -18554,6 +18612,10 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"hWp" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "hWW" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -18866,28 +18928,6 @@ /obj/machinery/space_heater, /turf/open/floor/plasteel, /area/engine/atmos) -"igK" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/door/window/eastleft{ - name = "Blue Corner" - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "igO" = ( /obj/machinery/vending/boozeomat, /turf/open/floor/wood{ @@ -18916,17 +18956,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/flasher{ - id = "AI"; - pixel_x = -26; - pixel_y = 3 - }, -/obj/machinery/turretid{ - icon_state = "control_stun"; - name = "AI Chamber turret control"; - pixel_x = -25; - pixel_y = -3 - }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) "ihE" = ( @@ -18937,6 +18966,7 @@ dir = 10 }, /obj/machinery/atmospherics/components/unary/portables_connector/visible, +/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/science/mixing) "ihJ" = ( @@ -18970,6 +19000,9 @@ /obj/machinery/power/smes, /turf/open/floor/plating, /area/maintenance/department/electrical) +"ihY" = ( +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "iiM" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -19305,6 +19338,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"iru" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/circuit/off, +/area/ai_monitored/turret_protected/ai) "irN" = ( /obj/machinery/requests_console{ department = "AI"; @@ -19363,7 +19402,7 @@ }, /obj/machinery/light, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "itw" = ( /obj/structure/cable{ icon_state = "4-8" @@ -19437,7 +19476,7 @@ dir = 1; name = "north facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "iuP" = ( /obj/machinery/door/airlock/external{ @@ -19446,15 +19485,6 @@ }, /turf/open/floor/engine, /area/engine/atmospherics_engine) -"ivM" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "Escape Airlock" - }, -/turf/open/floor/plating, -/area/hallway/secondary/exit/departure_lounge) "ivQ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -19488,6 +19518,13 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"iwH" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "ixf" = ( /obj/structure/cable{ icon_state = "1-2" @@ -19501,6 +19538,12 @@ /obj/item/hand_tele, /turf/open/floor/plasteel/dark, /area/teleporter) +"ixO" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "ixZ" = ( /obj/structure/chair/office/dark, /mob/living/simple_animal/pet/cat/Runtime{ @@ -19791,6 +19834,13 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = -28 + }, +/obj/machinery/light{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload_foyer) "iFl" = ( @@ -19976,7 +20026,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "iJK" = ( /obj/structure/table/reinforced, @@ -20018,6 +20068,13 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"iMk" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/ai_monitored/turret_protected/aisat/service) "iML" = ( /obj/machinery/light, /obj/machinery/requests_console{ @@ -20030,14 +20087,15 @@ /turf/open/floor/carpet, /area/crew_quarters/heads/hop) "iMX" = ( -/obj/structure/cable, -/obj/machinery/power/terminal, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/porta_turret/ai{ + dir = 4 + }, /turf/open/floor/circuit, /area/ai_monitored/turret_protected/ai_upload) "iNi" = ( -/obj/structure/window/plasma/reinforced{ - dir = 8 - }, /obj/machinery/computer/rdconsole/production{ dir = 4 }, @@ -20047,6 +20105,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "iNE" = ( @@ -20062,22 +20123,6 @@ }, /turf/open/floor/engine, /area/engine/engineering) -"iNK" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "iNV" = ( /obj/structure/cable{ icon_state = "1-2" @@ -20102,12 +20147,6 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, -/obj/structure/window/plasma/reinforced{ - dir = 8 - }, -/obj/structure/window/plasma/reinforced{ - dir = 1 - }, /obj/machinery/rnd/production/protolathe/department/engineering, /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -20119,6 +20158,12 @@ c_tag = "Engineering Storage"; dir = 4 }, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "iOG" = ( @@ -20163,6 +20208,13 @@ /obj/machinery/light, /turf/open/floor/plasteel, /area/hallway/primary/port) +"iQu" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "iQv" = ( /obj/machinery/door/airlock/public/glass{ name = "Courtroom"; @@ -20204,12 +20256,12 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "iRF" = ( -/obj/machinery/door/airlock/external, /obj/machinery/door/firedoor/border_only{ dir = 1; name = "north facing firelock" }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plating, /area/hallway/primary/aft) "iRO" = ( @@ -20246,9 +20298,13 @@ /turf/open/floor/plasteel/cult, /area/lawoffice) "iSB" = ( -/obj/machinery/light/floor, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) +/obj/structure/cable, +/obj/machinery/power/solar{ + id = "auxsolareast"; + name = "Port Auxiliary Solar Array" + }, +/turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, +/area/solar/port/fore) "iTP" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/carpet, @@ -20404,7 +20460,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "iZu" = ( /obj/machinery/firealarm{ @@ -20709,7 +20765,7 @@ /area/quartermaster/storage) "jjB" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "jjC" = ( /obj/structure/closet/crate, @@ -20776,7 +20832,7 @@ }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "jmU" = ( /obj/effect/turf_decal/tile/brown{ dir = 1 @@ -20898,10 +20954,11 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/fore) "jso" = ( -/obj/machinery/light/small{ - dir = 8 +/obj/machinery/power/smes{ + charge = 5e+006 }, -/turf/open/floor/circuit/off, +/obj/structure/cable, +/turf/open/floor/circuit, /area/ai_monitored/turret_protected/ai) "jsu" = ( /obj/structure/cable{ @@ -20952,11 +21009,11 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/fore) "jvV" = ( -/obj/machinery/mineral/stacking_unit_console{ - machinedir = 8 +/obj/structure/cable{ + icon_state = "0-2" }, -/turf/closed/wall, -/area/maintenance/disposal) +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/fore) "jwc" = ( /obj/structure/cable{ icon_state = "1-2" @@ -21027,7 +21084,7 @@ name = "Starboard Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/aft) "jxS" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/structure/cable{ @@ -21122,22 +21179,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"jAT" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/landmark/start/assistant, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "jBk" = ( /obj/structure/cable{ icon_state = "1-2" @@ -21256,6 +21297,12 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel/white, /area/medical/paramedic) +"jEm" = ( +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "jER" = ( /obj/machinery/vending/kink, /turf/open/floor/plating, @@ -21569,7 +21616,7 @@ }, /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "jOB" = ( /obj/structure/cable{ icon_state = "4-8" @@ -21604,6 +21651,12 @@ }, /turf/open/floor/plating, /area/engine/atmospherics_engine) +"jPf" = ( +/obj/machinery/computer/rdconsole/core{ + dir = 8 + }, +/turf/open/floor/circuit, +/area/science/lab) "jPh" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -21824,6 +21877,9 @@ "jWr" = ( /turf/closed/wall/r_wall, /area/storage/tech) +"jWw" = ( +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "jWx" = ( /obj/structure/table/glass, /obj/item/stack/sheet/mineral/plasma, @@ -21882,7 +21938,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "jYS" = ( /obj/structure/chair{ @@ -21941,6 +21997,13 @@ /obj/machinery/smartfridge, /turf/open/floor/plasteel, /area/hydroponics) +"kbE" = ( +/obj/structure/chair/comfy/brown{ + color = "#596479"; + dir = 8 + }, +/turf/open/transparent/glass/reinforced, +/area/crew_quarters/fitness) "kbR" = ( /obj/structure/table, /obj/item/storage/firstaid/regular{ @@ -22027,15 +22090,18 @@ }, /turf/open/floor/plasteel, /area/storage/auxiliary) +"kdy" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) "kdA" = ( /obj/structure/table/glass, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 }, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, /turf/open/floor/plasteel/white, /area/science/lab) "kdM" = ( @@ -22124,24 +22190,11 @@ /turf/open/floor/carpet, /area/chapel/office) "kge" = ( -/obj/structure/window{ - dir = 8 - }, -/obj/structure/window{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ +/obj/structure/chair/comfy/brown{ + color = "#596479"; dir = 4 }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/landmark/start/assistant, -/turf/open/floor/plasteel, +/turf/open/transparent/glass/reinforced, /area/crew_quarters/fitness) "kgx" = ( /obj/structure/table, @@ -22245,6 +22298,14 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/fore) +"kjx" = ( +/obj/machinery/door/window/eastright{ + dir = 8; + name = "Robotics Surgery"; + req_access_txt = "29" + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "kkn" = ( /obj/structure/cable{ icon_state = "4-8" @@ -22412,7 +22473,7 @@ icon_state = "2-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "kol" = ( /obj/machinery/light{ dir = 1 @@ -22934,6 +22995,13 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) +"kHJ" = ( +/obj/structure/grille, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "kHP" = ( /obj/machinery/atmospherics/pipe/manifold/yellow/visible{ dir = 4 @@ -22963,6 +23031,12 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/fore) +"kIV" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "kJk" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 9 @@ -23063,7 +23137,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, @@ -23071,6 +23144,7 @@ dir = 4 }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plasteel, /area/hallway/primary/port) "kMy" = ( @@ -23153,9 +23227,6 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "kPu" = ( -/obj/structure/window/plasma/reinforced{ - dir = 4 - }, /obj/structure/table, /obj/item/stack/sheet/metal/fifty, /obj/item/stack/sheet/metal/fifty, @@ -23166,6 +23237,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/structure/window/reinforced{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "kPA" = ( @@ -23227,9 +23301,6 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/maintenance/aft/secondary) -"kRk" = ( -/turf/open/floor/plasteel/white, -/area/crew_quarters/dorms) "kRz" = ( /obj/structure/cable{ icon_state = "1-8" @@ -23363,6 +23434,13 @@ "kVO" = ( /turf/closed/wall, /area/hallway/primary/aft) +"kWz" = ( +/obj/machinery/door/airlock{ + id_tag = "Dorm6"; + name = "Room Five" + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "kWC" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -23373,6 +23451,17 @@ /obj/machinery/door/airlock/maintenance, /turf/open/floor/plating, /area/maintenance/aft/secondary) +"kXL" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Snow Airlock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" + }, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "kXY" = ( /obj/structure/cable{ icon_state = "4-8" @@ -23486,7 +23575,7 @@ name = "Port Auxiliary Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "lbv" = ( /obj/machinery/atmospherics/components/binary/pump, /obj/machinery/door/firedoor/border_only{ @@ -23495,6 +23584,19 @@ }, /turf/open/floor/plasteel/white, /area/science/xenobiology) +"lcv" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "ldt" = ( /obj/structure/cable{ icon_state = "1-2" @@ -23593,15 +23695,15 @@ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/door/airlock/public/glass{ - name = "Hydroponics"; - req_access_txt = "35" - }, /obj/machinery/door/firedoor/border_only{ dir = 1; name = "north facing firelock" }, /obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock{ + name = "Hydroponics"; + req_access_txt = "35" + }, /turf/open/floor/plasteel, /area/hydroponics) "lfD" = ( @@ -23621,6 +23723,12 @@ /obj/structure/closet/cardboard, /turf/open/floor/plating, /area/maintenance/starboard) +"lgg" = ( +/obj/structure/fluff/railing{ + dir = 5 + }, +/turf/open/transparent/openspace/icemoon, +/area/engine/atmospherics_engine) "lgn" = ( /obj/structure/cable{ icon_state = "1-2" @@ -23673,14 +23781,12 @@ /turf/open/floor/plasteel, /area/maintenance/aft) "lhr" = ( -/obj/structure/cable{ - icon_state = "0-8" +/obj/machinery/mineral/stacking_unit_console{ + machinedir = 1; + pixel_x = -30 }, -/obj/machinery/power/smes{ - charge = 5e+006 - }, -/turf/open/floor/circuit, -/area/ai_monitored/turret_protected/ai_upload) +/turf/open/floor/plasteel, +/area/maintenance/disposal) "lhB" = ( /obj/machinery/camera{ c_tag = "Northwestern Hall 7"; @@ -23710,29 +23816,27 @@ /obj/structure/cable{ icon_state = "2-8" }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/landmark/start/assistant, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "liL" = ( -/obj/structure/cable{ - icon_state = "0-2" - }, /obj/machinery/ai_slipper{ uses = 10 }, -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/ai_monitored/turret_protected/ai"; +/obj/machinery/door/window{ + base_state = "rightsecure"; dir = 4; - name = "AI Chamber APC"; - pixel_x = 24 + icon_state = "rightsecure"; + layer = 4.1; + name = "Secondary AI Core Access"; + obj_integrity = 300; + pixel_x = 4; + req_access_txt = "16" + }, +/obj/structure/cable{ + icon_state = "2-4" }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) @@ -23757,11 +23861,11 @@ /turf/open/floor/pod/dark, /area/medical/paramedic) "lki" = ( -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plasteel, /area/hallway/primary/port) "lkP" = ( @@ -23992,7 +24096,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "lqW" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -24544,7 +24648,12 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, -/obj/structure/weightmachine/stacklifter, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, +/obj/structure/cable{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "lJi" = ( @@ -24571,12 +24680,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/icemoon/surface/outdoors) -"lJN" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/crew_quarters/dorms) "lKT" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -24591,12 +24694,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/crew_quarters/theatre) -"lLv" = ( -/obj/structure/chair/comfy/beige{ - dir = 8 - }, -/turf/open/floor/carpet, -/area/crew_quarters/dorms) "lLD" = ( /obj/structure/cable{ icon_state = "1-2" @@ -24672,6 +24769,19 @@ }, /turf/open/floor/carpet/orange, /area/engine/secure_construction) +"lOa" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8; + name = "west facing firelock" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "lOs" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, @@ -24716,27 +24826,35 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmospherics_engine) -"lQp" = ( +"lQd" = ( /obj/structure/cable{ - icon_state = "1-2" + icon_state = "4-8" }, -/obj/machinery/porta_turret/ai{ - dir = 4 +/obj/structure/cable{ + icon_state = "1-8" }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/ai) +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) +"lQp" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "waste relief valve" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "lQs" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/hallway/secondary/exit/departure_lounge) "lQJ" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 +/obj/structure/fluff/railing{ + dir = 9 }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) +/turf/open/transparent/openspace/icemoon, +/area/icemoon/surface/outdoors) "lRx" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -25107,7 +25225,9 @@ dir = 4 }, /obj/effect/turf_decal/tile/green, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark/side{ + dir = 5 + }, /area/hydroponics) "mbM" = ( /obj/effect/turf_decal/tile/blue{ @@ -25216,6 +25336,13 @@ }, /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) +"mfU" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Holodeck Door" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "mgo" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/firedoor/border_only{ @@ -25391,7 +25518,7 @@ icon_state = "4-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/fore) "mmO" = ( /obj/structure/cable{ icon_state = "1-2" @@ -25475,11 +25602,11 @@ /turf/open/floor/plating, /area/medical/virology) "mps" = ( -/obj/machinery/atmospherics/components/binary/valve{ - dir = 4 +/obj/structure/chair/comfy/beige{ + dir = 8 }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "mqb" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 8 @@ -25499,6 +25626,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"mqd" = ( +/obj/item/paper/fluff{ + info = "Crystal has been moved to a lockbox in secure storage until further notice."; + name = "Note from an engineer"; + pixel_x = -5; + pixel_y = 3 + }, +/turf/open/floor/engine, +/area/engine/supermatter) "mqm" = ( /obj/structure/cable{ icon_state = "1-2" @@ -25591,7 +25727,7 @@ /turf/open/floor/plating, /area/maintenance/aft/secondary) "mtP" = ( -/turf/open/floor/carpet, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "mtY" = ( /obj/structure/cable{ @@ -25846,17 +25982,28 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/quartermaster/miningdock) +"mEH" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "mEI" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/eastright{ base_state = "left"; - dir = 2; + dir = 1; icon_state = "left"; name = "Chemistry Desk"; req_access_txt = "33" }, /obj/machinery/door/firedoor/border_only, /obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/door/window/eastright{ + dir = 2; + name = "Chemistry Desk" + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "mFg" = ( @@ -25917,6 +26064,16 @@ /obj/machinery/space_heater, /turf/open/floor/plating, /area/icemoon/surface/outdoors) +"mHm" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "mHT" = ( /obj/structure/closet/l3closet/scientist, /obj/item/extinguisher, @@ -26527,7 +26684,7 @@ }, /obj/structure/bed, /obj/effect/spawner/lootdrop/bedsheet, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "mWD" = ( /obj/structure/cable{ @@ -26618,6 +26775,10 @@ /obj/machinery/door/firedoor/border_only{ dir = 1 }, +/obj/machinery/door/window/eastright{ + dir = 1; + name = "Chemistry Desk" + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "mZk" = ( @@ -26635,7 +26796,11 @@ name = "Station Intercom (General)"; pixel_x = 30 }, -/turf/open/floor/carpet, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/wood, /area/crew_quarters/dorms) "nbr" = ( /obj/structure/cable{ @@ -26975,13 +27140,13 @@ /turf/open/floor/plating, /area/security/checkpoint/medical) "nlF" = ( -/obj/machinery/door/airlock/public/glass{ - name = "Holodeck Door" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plasteel/white, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/carpet, /area/crew_quarters/dorms) "nlM" = ( /obj/machinery/light{ @@ -26994,19 +27159,6 @@ /obj/machinery/rnd/production/techfab/department/cargo, /turf/open/floor/plasteel, /area/quartermaster/miningdock) -"nmL" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/landmark/start/assistant, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "nmM" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -27147,7 +27299,6 @@ /area/storage/auxiliary) "nrY" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -27155,7 +27306,8 @@ name = "south facing firelock" }, /obj/structure/fans/tiny, -/turf/open/floor/carpet, +/obj/machinery/door/airlock/external/glass, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "nsf" = ( /obj/machinery/door/firedoor, @@ -27244,6 +27396,12 @@ dir = 4; network = list("aicore") }, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) "ntX" = ( @@ -27258,7 +27416,7 @@ }, /obj/machinery/power/tracker, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "nuJ" = ( /obj/structure/cable{ icon_state = "1-8" @@ -27362,7 +27520,7 @@ icon_state = "0-2" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "nyT" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, @@ -27450,7 +27608,7 @@ pixel_x = -24; specialfunctions = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "nBk" = ( /obj/structure/cable{ @@ -27572,16 +27730,26 @@ /turf/open/floor/plasteel, /area/engine/engineering) "nDd" = ( -/obj/structure/cable{ - icon_state = "4-8" +/obj/structure/closet/crate/engineering{ + name = "Antimatter Engine Crate" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/visible, -/obj/machinery/light/floor, -/turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/obj/machinery/power/am_control_unit, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_shielding_container, +/obj/item/am_containment, +/obj/item/am_containment, +/turf/open/floor/carpet/orange, +/area/engine/secure_construction) "nDl" = ( /obj/structure/cable{ icon_state = "4-8" @@ -27597,8 +27765,21 @@ icon_state = "0-8" }, /obj/structure/grille, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) +"nDN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/visible{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "nEa" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -27640,6 +27821,16 @@ }, /turf/open/floor/carpet, /area/hallway/primary/port) +"nEH" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "nEI" = ( /obj/structure/dresser, /obj/machinery/camera{ @@ -27792,6 +27983,13 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"nJB" = ( +/obj/machinery/light, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "nJI" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/southleft{ @@ -27921,10 +28119,15 @@ /area/hallway/primary/port) "nOY" = ( /obj/machinery/camera{ - c_tag = "Dorms West"; + c_tag = "Dorms Northeast"; dir = 8 }, -/turf/open/floor/carpet, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/wood, /area/crew_quarters/dorms) "nPd" = ( /obj/structure/cable{ @@ -28021,6 +28224,13 @@ /obj/machinery/atmospherics/pipe/simple/general/visible, /turf/closed/wall/r_wall, /area/science/mixing) +"nRA" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/chair/comfy/beige, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "nRS" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -28184,6 +28394,12 @@ }, /turf/open/floor/plasteel/dark, /area/security/main) +"nYd" = ( +/obj/machinery/atmospherics/components/binary/valve{ + dir = 4 + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "nYv" = ( /obj/structure/chair{ dir = 8 @@ -28639,7 +28855,7 @@ dir = 4; name = "east facing firelock" }, -/turf/open/floor/plasteel, +/turf/open/floor/wood, /area/crew_quarters/fitness) "ojs" = ( /obj/structure/cable{ @@ -28824,6 +29040,18 @@ }, /turf/open/floor/engine/n2, /area/engine/atmos) +"onO" = ( +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/ai_monitored/turret_protected/ai"; + dir = 4; + name = "AI Chamber APC"; + pixel_x = 24 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/circuit/off, +/area/ai_monitored/turret_protected/ai) "onY" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/green/visible{ @@ -28860,45 +29088,8 @@ /turf/open/floor/plasteel, /area/engine/break_room) "ooR" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/effect/landmark/start/ai, -/obj/item/radio/intercom{ - freerange = 1; - frequency = 1447; - name = "Private Channel"; - pixel_x = -25; - pixel_y = -10 - }, -/obj/item/radio/intercom{ - freerange = 1; - listening = 0; - name = "Custom Channel"; - pixel_y = 27 - }, -/obj/item/radio/intercom{ - freerange = 1; - name = "Common Channel"; - pixel_x = -25 - }, -/obj/machinery/button/door{ - id = "AI Chamber entrance shutters"; - name = "AI Chamber entrance shutters control"; - pixel_x = 8; - pixel_y = 23; - req_access_txt = "16" - }, -/obj/machinery/door/window{ - base_state = "rightsecure"; - dir = 4; - icon_state = "rightsecure"; - name = "Primary AI Core Access"; - obj_integrity = 300; - req_access_txt = "16" - }, -/turf/open/floor/circuit, -/area/ai_monitored/turret_protected/ai) +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters) "opq" = ( /obj/machinery/computer/rdservercontrol{ dir = 1 @@ -28917,11 +29108,8 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, -/obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" - }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plasteel, /area/maintenance/aft) "opY" = ( @@ -28995,6 +29183,10 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint/medical) +"ord" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "orN" = ( /obj/structure/cable{ icon_state = "2-4" @@ -29253,10 +29445,7 @@ /area/engine/engineering) "oBj" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plasteel, /area/maintenance/aft) "oBl" = ( @@ -29281,7 +29470,7 @@ c_tag = "Dorms South"; dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "oBF" = ( /obj/structure/cable{ @@ -29401,6 +29590,12 @@ }, /turf/open/floor/wood, /area/hallway/primary/central) +"oGZ" = ( +/obj/structure/fluff/railing{ + dir = 6 + }, +/turf/open/transparent/openspace/icemoon, +/area/engine/atmospherics_engine) "oHl" = ( /obj/structure/closet/crate/secure/engineering{ name = "TEG crate" @@ -29601,15 +29796,13 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload_foyer) "oME" = ( -/obj/structure/cable{ - icon_state = "4-8" +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/machinery/light/floor, -/turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/obj/machinery/vending/snack/random, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "oNv" = ( /obj/structure/table/wood, /turf/open/floor/wood, @@ -29679,17 +29872,27 @@ /obj/effect/landmark/start/head_of_personnel, /turf/open/floor/carpet, /area/crew_quarters/heads/hop) +"oPk" = ( +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "oPP" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/eastright{ base_state = "left"; - dir = 2; + dir = 1; icon_state = "left"; name = "Chemistry Desk"; req_access_txt = "33" }, /obj/machinery/door/firedoor/border_only, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/door/window/eastright{ + dir = 2; + name = "Chemistry Desk" + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "oPS" = ( @@ -29798,6 +30001,12 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, /area/engine/storage) +"oUT" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "oUV" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -29994,17 +30203,7 @@ /turf/open/floor/plasteel, /area/storage/primary) "pbf" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 }, /turf/open/floor/plasteel, @@ -30085,13 +30284,11 @@ /turf/open/floor/carpet, /area/hallway/secondary/exit/departure_lounge) "pce" = ( -/obj/machinery/door/airlock/external{ - name = "Auxiliary Airlock" - }, /obj/machinery/door/firedoor/border_only{ name = "south facing firelock" }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plating, /area/hallway/secondary/exit/departure_lounge) "pcl" = ( @@ -30233,23 +30430,11 @@ dir = 4 }, /obj/machinery/disposal/bin, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "pgk" = ( -/obj/structure/window{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/turf/open/floor/plasteel, +/obj/structure/table, +/turf/open/transparent/glass/reinforced, /area/crew_quarters/fitness) "pgp" = ( /turf/closed/wall, @@ -30419,7 +30604,7 @@ icon_state = "2-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "pkJ" = ( /turf/open/floor/wood{ icon_state = "wood-broken6" @@ -30553,6 +30738,13 @@ "pqj" = ( /turf/open/floor/plasteel, /area/hallway/primary/fore) +"pqm" = ( +/obj/machinery/camera{ + c_tag = "Dorms Northwest"; + dir = 4 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "pqs" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 4 @@ -30692,7 +30884,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "ptv" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/on/layer1, @@ -30705,6 +30897,16 @@ }, /turf/open/floor/engine, /area/engine/atmospherics_engine) +"ptH" = ( +/obj/machinery/computer/holodeck{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "ptU" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -30718,7 +30920,7 @@ dir = 4 }, /obj/machinery/door/poddoor/preopen{ - id = "xenobio2"; + id = "xenobiospec"; name = "containment blast door" }, /turf/open/floor/engine, @@ -30887,6 +31089,15 @@ }, /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) +"pvP" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "pvV" = ( /obj/machinery/airalarm{ pixel_y = 26 @@ -30923,6 +31134,9 @@ /area/engine/storage) "pwE" = ( /obj/effect/landmark/start/cyborg, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/service) "pwL" = ( @@ -31078,14 +31292,12 @@ /turf/open/floor/plasteel/freezer, /area/security/prison) "pze" = ( -/obj/machinery/door/airlock/external{ - name = "Auxiliary Airlock" - }, /obj/machinery/door/firedoor/border_only{ dir = 1; name = "north facing firelock" }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plating, /area/quartermaster/miningdock) "pzk" = ( @@ -31176,6 +31388,11 @@ }, /turf/open/floor/wood, /area/crew_quarters/heads/captain) +"pDg" = ( +/obj/structure/table, +/obj/item/paicard, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "pDh" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -31346,8 +31563,12 @@ /turf/open/floor/plasteel, /area/storage/primary) "pIf" = ( -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/machinery/vending/cigarette, +/turf/open/floor/wood, +/area/crew_quarters/dorms) +"pIs" = ( +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "pIz" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -31376,6 +31597,18 @@ }, /turf/open/floor/plasteel/dark, /area/maintenance/department/bridge) +"pJm" = ( +/obj/structure/table/optable{ + name = "Robotics Operating Table" + }, +/obj/item/tank/internals/anesthetic, +/obj/item/clothing/mask/breath, +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_y = 29 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "pJS" = ( /turf/closed/wall, /area/quartermaster/storage) @@ -31651,6 +31884,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "pQg" = ( @@ -31806,7 +32040,6 @@ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -31814,7 +32047,8 @@ name = "south facing firelock" }, /obj/structure/fans/tiny, -/turf/open/floor/carpet, +/obj/machinery/door/airlock/external/glass, +/turf/open/floor/plasteel, /area/crew_quarters/dorms) "pXl" = ( /obj/machinery/computer/cloning{ @@ -32022,7 +32256,7 @@ icon_state = "4-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/fore) "qfT" = ( /obj/machinery/holopad, /turf/open/floor/carpet, @@ -32103,6 +32337,10 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"qim" = ( +/obj/machinery/light, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "qip" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -32147,6 +32385,18 @@ }, /turf/open/floor/plasteel, /area/storage/primary) +"qjF" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "qkg" = ( /obj/effect/turf_decal/tile/green{ dir = 4 @@ -32238,23 +32488,7 @@ /turf/closed/wall, /area/quartermaster/miningdock) "qnx" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/turf/open/floor/plasteel, +/turf/open/transparent/glass/reinforced, /area/crew_quarters/fitness) "qnC" = ( /obj/structure/cable, @@ -32338,7 +32572,7 @@ }, /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "qqo" = ( /obj/machinery/light{ dir = 4 @@ -32704,7 +32938,7 @@ }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "qAI" = ( /obj/structure/cable{ icon_state = "4-8" @@ -32731,6 +32965,13 @@ }, /turf/open/floor/carpet, /area/hallway/primary/central) +"qBl" = ( +/obj/machinery/mineral/ore_redemption{ + input_dir = 4; + output_dir = 8 + }, +/turf/open/floor/plating, +/area/quartermaster/miningdock) "qBu" = ( /obj/machinery/atmospherics/components/binary/pump, /turf/open/floor/plasteel, @@ -32867,7 +33108,7 @@ name = "Station Intercom (General)"; pixel_y = 29 }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "qFZ" = ( /obj/structure/closet/emcloset, @@ -32948,12 +33189,19 @@ /area/hallway/primary/fore) "qHC" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/layer_manifold, /turf/open/floor/plating, /area/engine/atmos) "qHL" = ( -/obj/structure/chair/comfy/beige{ - dir = 1 +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4; + name = "east facing firelock" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /turf/open/floor/carpet, /area/crew_quarters/dorms) @@ -32988,13 +33236,10 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/structure/chair/stool{ - pixel_y = 8 - }, /obj/machinery/camera{ - c_tag = "Dorms Central" + c_tag = "Dorms East" }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "qIR" = ( /obj/machinery/button/massdriver{ @@ -33023,6 +33268,18 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel/white, /area/medical/virology) +"qIW" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "qJs" = ( /obj/structure/chair, /obj/effect/turf_decal/stripes/line{ @@ -33076,9 +33333,6 @@ /turf/open/floor/plasteel/white, /area/science/xenobiology) "qKA" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33086,6 +33340,9 @@ dir = 8 }, /obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "qKP" = ( @@ -33184,6 +33441,14 @@ }, /turf/open/floor/plasteel/freezer, /area/medical/surgery) +"qOJ" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "qOL" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/carpet, @@ -33337,6 +33602,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"qSF" = ( +/obj/structure/chair/comfy/beige{ + dir = 1 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "qSJ" = ( /obj/machinery/airalarm{ pixel_y = 28 @@ -33527,6 +33798,12 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"qZb" = ( +/obj/structure/fluff/railing{ + dir = 10 + }, +/turf/open/transparent/openspace/icemoon, +/area/engine/atmospherics_engine) "qZO" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 4 @@ -33566,14 +33843,20 @@ /turf/closed/wall/r_wall, /area/maintenance/starboard) "raM" = ( -/obj/machinery/door/airlock/external, -/obj/machinery/door/firedoor/border_only{ - dir = 8; - name = "west facing firelock" +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "holoprivacy"; + name = "Holodeck Shutters" }, -/obj/structure/fans/tiny, /turf/open/floor/plating, /area/crew_quarters/dorms) +"rbb" = ( +/obj/machinery/space_heater, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "rbg" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 8; @@ -34095,7 +34378,7 @@ name = "Starboard Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/aft) "roS" = ( /obj/machinery/computer/card/minor/cmo{ dir = 4 @@ -34327,9 +34610,9 @@ /turf/open/floor/engine, /area/engine/engineering) "ruo" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) +/obj/machinery/vending/cola/random, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "ruD" = ( /obj/machinery/airalarm{ dir = 1; @@ -34412,7 +34695,7 @@ name = "Port Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "rxJ" = ( /obj/item/stack/cable_coil/random, /turf/open/floor/plating/asteroid/snow/icemoon, @@ -34547,7 +34830,6 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/science/mixing) "rDE" = ( @@ -34570,6 +34852,18 @@ }, /turf/open/floor/plating, /area/maintenance/department/electrical) +"rEF" = ( +/obj/structure/bed, +/obj/effect/spawner/lootdrop/bedsheet, +/obj/machinery/button/door{ + id = "Dorm6"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 25; + specialfunctions = 4 + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "rFk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, @@ -34705,6 +34999,12 @@ }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) +"rKC" = ( +/obj/machinery/camera{ + c_tag = "Dorms West" + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "rLb" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -34804,28 +35104,16 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "rPU" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "robo1" +/obj/machinery/light{ + dir = 8 }, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/glass{ - amount = 20; - pixel_x = -3; - pixel_y = 6 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/wood, +/area/crew_quarters/dorms) "rQs" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/hallway/primary/fore) "rQu" = ( -/obj/structure/cable{ - icon_state = "1-8" - }, /obj/machinery/firealarm{ dir = 8; pixel_x = 24 @@ -34865,9 +35153,27 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "rRk" = ( -/obj/structure/chair/comfy/beige, +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4; + name = "east facing firelock" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/carpet, /area/crew_quarters/dorms) +"rRQ" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/science/lab) "rRV" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -34936,6 +35242,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "rTW" = ( @@ -35052,9 +35359,7 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "rYc" = ( -/obj/machinery/computer/arcade/battle{ - dir = 8 - }, +/obj/machinery/vending/cigarette, /turf/open/floor/wood, /area/crew_quarters/bar) "rYi" = ( @@ -35100,6 +35405,13 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"sae" = ( +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "sat" = ( /obj/machinery/light, /turf/open/floor/plasteel/white, @@ -35184,6 +35496,12 @@ /turf/open/floor/plasteel, /area/maintenance/aft) "scF" = ( +/obj/machinery/turretid{ + icon_state = "control_stun"; + name = "AI Chamber turret control"; + pixel_x = 24; + pixel_y = -3 + }, /obj/structure/cable{ icon_state = "1-2" }, @@ -35674,6 +35992,16 @@ }, /turf/open/floor/engine/n2o, /area/engine/atmos) +"stP" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/grille, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "stW" = ( /obj/structure/table/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -35688,7 +36016,7 @@ "sub" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "sup" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -35751,14 +36079,8 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "swQ" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) +/turf/open/floor/wood, +/area/crew_quarters/dorms) "sxa" = ( /obj/machinery/requests_console{ department = "Medbay"; @@ -35963,20 +36285,16 @@ /turf/closed/wall/r_wall, /area/crew_quarters/heads/captain) "sFw" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, /obj/machinery/light, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/blue{ +/obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "sGC" = ( @@ -36059,7 +36377,7 @@ /turf/open/floor/engine, /area/engine/engineering) "sIT" = ( -/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/recharge_station, /turf/open/floor/pod/dark, /area/medical/paramedic) "sJs" = ( @@ -36091,9 +36409,6 @@ /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) "sKN" = ( -/obj/structure/window/plasma/reinforced{ - dir = 8 - }, /obj/machinery/rnd/production/circuit_imprinter, /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -36101,6 +36416,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "sLg" = ( @@ -36152,6 +36470,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"sLF" = ( +/obj/structure/sign/mining{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/quartermaster/miningdock) "sLN" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, @@ -36216,6 +36540,32 @@ name = "Robotics Lab APC"; pixel_x = 25 }, +/obj/structure/table, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -2; + pixel_y = -1 + }, +/obj/item/storage/toolbox/electrical{ + pixel_x = 1; + pixel_y = 6 + }, +/obj/item/clothing/head/welding{ + pixel_x = -3; + pixel_y = 5 + }, +/obj/item/clothing/head/welding{ + pixel_x = -3; + pixel_y = 5 + }, +/obj/item/clothing/glasses/welding, +/obj/item/clothing/glasses/welding, +/obj/item/multitool{ + pixel_x = 3 + }, +/obj/item/multitool{ + pixel_x = 3 + }, +/obj/item/storage/belt/utility, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "sOi" = ( @@ -36310,6 +36660,15 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) +"sQk" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "sRh" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -36396,8 +36755,24 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "sTq" = ( +/obj/structure/fluff/railing{ + dir = 1 + }, /turf/open/transparent/openspace/icemoon, /area/engine/atmospherics_engine) +"sTt" = ( +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -6; + pixel_y = 4 + }, +/obj/item/pen/fourcolor, +/obj/item/paper_bin/bundlenatural{ + pixel_x = 6; + pixel_y = 4 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "sTz" = ( /obj/effect/turf_decal/bot_white, /obj/structure/window/reinforced{ @@ -36884,22 +37259,9 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/fore) "tgd" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/window{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "tht" = ( @@ -37181,7 +37543,7 @@ icon_state = "1-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "tod" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -37288,6 +37650,7 @@ /obj/structure/disposalpipe/segment{ dir = 6 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "tqp" = ( @@ -37357,7 +37720,7 @@ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "ttl" = ( /obj/structure/cable{ @@ -37555,6 +37918,18 @@ }, /turf/open/floor/plasteel, /area/quartermaster/miningoffice) +"tzb" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/terminal{ + dir = 1 + }, +/turf/open/floor/circuit/off, +/area/ai_monitored/turret_protected/ai) "tzB" = ( /obj/machinery/atmospherics/pipe/simple{ dir = 6 @@ -37749,6 +38124,12 @@ /obj/machinery/atmospherics/components/binary/pump/on, /turf/open/floor/plasteel, /area/engine/atmos) +"tEC" = ( +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "tEQ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -37776,11 +38157,12 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "tFu" = ( -/obj/structure/cable{ - icon_state = "2-4" +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = 30 }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/ai) +/turf/open/floor/wood, +/area/crew_quarters/dorms) "tFN" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 4 @@ -37816,11 +38198,9 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/door/airlock/external{ - name = "Escape Airlock" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/carpet, /area/hallway/primary/port) "tHr" = ( @@ -37894,9 +38274,12 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload_foyer) "tJi" = ( -/obj/machinery/vending/wardrobe/robo_wardrobe, -/turf/open/floor/plasteel/white, -/area/science/robotics/lab) +/obj/structure/closet/secure_closet/personal/cabinet, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "tJA" = ( /obj/structure/cable{ icon_state = "1-2" @@ -37966,6 +38349,16 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/quartermaster/miningoffice) +"tLb" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/visible{ + dir = 4 + }, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "tLA" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -38109,17 +38502,14 @@ /turf/open/floor/plasteel/freezer, /area/medical/surgery) "tOz" = ( -/obj/machinery/light{ - dir = 1 +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 }, -/obj/machinery/door/airlock/public/glass{ - name = "Holodeck Door" +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 }, -/obj/structure/fans/tiny, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/turf/open/floor/plasteel/white, +/turf/open/floor/wood, /area/crew_quarters/dorms) "tOE" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -38140,10 +38530,12 @@ name = "Fitness Room APC"; pixel_y = -24 }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "tPB" = ( @@ -38231,18 +38623,11 @@ /turf/open/floor/plasteel/dark, /area/maintenance/department/bridge) "tRC" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/structure/window{ - dir = 8 +/obj/structure/cable{ + icon_state = "4-8" }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -38270,11 +38655,13 @@ /turf/open/floor/plasteel/white, /area/science/xenobiology) "tSd" = ( -/obj/structure/cable{ - icon_state = "2-8" +/obj/item/radio/intercom{ + dir = 4; + name = "Station Intercom (General)"; + pixel_y = 29 }, -/turf/closed/wall/r_wall, -/area/ai_monitored/turret_protected/ai) +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "tSB" = ( /obj/machinery/atmospherics/pipe/simple{ dir = 4 @@ -38350,6 +38737,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"tUq" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "tUF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -38409,6 +38802,17 @@ }, /turf/open/floor/plasteel, /area/science/robotics/mechbay) +"tWs" = ( +/obj/machinery/door/airlock/external/glass, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, +/obj/structure/fans/tiny, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "tXn" = ( /obj/structure/cable{ icon_state = "4-8" @@ -38431,7 +38835,7 @@ pixel_x = -24; specialfunctions = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "tYT" = ( /obj/structure/cable{ @@ -38720,7 +39124,7 @@ /area/engine/atmos) "ugk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "uha" = ( /obj/structure/cable{ @@ -38803,7 +39207,7 @@ /obj/machinery/door/firedoor/border_only{ name = "south facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "ukJ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -38814,6 +39218,10 @@ }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/kitchen) +"ule" = ( +/obj/structure/sign/departments/botany, +/turf/closed/wall, +/area/hydroponics) "ulh" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -38862,14 +39270,14 @@ /turf/open/floor/plating, /area/crew_quarters/heads/hop) "umC" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/effect/turf_decal/tile/neutral, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "umD" = ( @@ -38892,7 +39300,7 @@ dir = 4 }, /obj/structure/closet/wardrobe/white, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "unA" = ( /obj/effect/spawner/structure/window/reinforced, @@ -39031,7 +39439,7 @@ /obj/structure/cable, /obj/machinery/power/smes, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "utS" = ( /obj/structure/table, /obj/item/clothing/suit/apron/surgical, @@ -39046,11 +39454,18 @@ }, /turf/open/floor/plasteel/freezer, /area/medical/surgery) +"utY" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "uup" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "uut" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 @@ -39105,13 +39520,9 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/landmark/start/assistant, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -39194,6 +39605,12 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) +"uyV" = ( +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/port/aft) "uyW" = ( /obj/structure/cable{ icon_state = "0-4" @@ -39384,13 +39801,13 @@ name = "Dormitory APC"; pixel_y = 24 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "uFq" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, -/obj/machinery/door/airlock/external{ +/obj/machinery/door/airlock/external/glass{ name = "Arrivals Airlock" }, /turf/open/floor/plating, @@ -39566,12 +39983,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/structure/window/plasma/reinforced{ - dir = 4 - }, -/obj/structure/window/plasma/reinforced{ - dir = 1 - }, /obj/structure/table, /obj/item/stack/sheet/glass/fifty, /obj/item/stack/sheet/glass/fifty, @@ -39582,6 +39993,12 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "uKy" = ( @@ -39769,12 +40186,14 @@ /obj/structure/cable, /obj/machinery/power/tracker, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/aft) "uRg" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/closet/bombcloset, -/turf/open/floor/plasteel/white, -/area/science/mixing) +/obj/machinery/door/airlock{ + id_tag = "Dorm7"; + name = "Room Six" + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "uRi" = ( /obj/structure/cable{ icon_state = "4-8" @@ -39843,8 +40262,14 @@ /turf/open/floor/plasteel, /area/engine/atmos) "uUi" = ( -/obj/machinery/computer/operating, -/turf/open/floor/plasteel/white, +/obj/machinery/mecha_part_fabricator, +/obj/item/stack/sheet/glass{ + amount = 20; + pixel_x = -3; + pixel_y = 6 + }, +/obj/item/stack/sheet/metal/fifty, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "uUk" = ( /obj/structure/disposalpipe/segment{ @@ -39937,6 +40362,7 @@ "uWn" = ( /obj/structure/table, /obj/item/toy/cards/deck, +/obj/item/storage/crayons, /turf/open/floor/plasteel/grimy, /area/crew_quarters/fitness/recreation) "uWo" = ( @@ -39968,6 +40394,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "uWW" = ( @@ -40246,11 +40673,9 @@ /turf/open/floor/circuit, /area/science/robotics/mechbay) "vdW" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/turf/closed/wall/r_wall, -/area/ai_monitored/turret_protected/ai_upload) +/obj/structure/table/wood, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "vem" = ( /obj/structure/table/wood, /obj/machinery/keycard_auth{ @@ -40268,7 +40693,7 @@ codes_txt = "patrol;next_patrol=CHW"; location = "Dorm" }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "veF" = ( /obj/structure/table/wood, @@ -40407,7 +40832,7 @@ /obj/machinery/light{ dir = 1 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "vhf" = ( /obj/effect/spawner/structure/window/reinforced, @@ -40485,6 +40910,11 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/fore) +"vko" = ( +/obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/machinery/light/floor, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "vkw" = ( /obj/structure/cable{ icon_state = "1-2" @@ -40608,13 +41038,10 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "vow" = ( -/obj/machinery/door/airlock/public/glass{ - name = "Holodeck Door" +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plasteel/white, +/turf/open/floor/wood, /area/crew_quarters/dorms) "voD" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -40703,7 +41130,7 @@ pixel_x = -24; specialfunctions = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "vqZ" = ( /obj/structure/window/plasma/reinforced{ @@ -40736,7 +41163,7 @@ "vrg" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "vrx" = ( /turf/closed/wall/r_wall, /area/crew_quarters/dorms) @@ -40812,7 +41239,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "vuk" = ( /obj/effect/spawner/structure/window/plasma/reinforced, @@ -41015,11 +41442,17 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "vzS" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible{ - dir = 5 +/obj/structure/bed, +/obj/effect/spawner/lootdrop/bedsheet, +/obj/machinery/button/door{ + id = "Dorm7"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 25; + specialfunctions = 4 }, -/turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "vAh" = ( /obj/structure/cable{ icon_state = "1-2" @@ -41193,12 +41626,12 @@ icon_state = "4-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/starboard/aft) "vDI" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "vEd" = ( /obj/effect/landmark/event_spawn, @@ -41208,7 +41641,7 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "vEi" = ( /obj/structure/cable{ @@ -41295,6 +41728,7 @@ c_tag = "Northwest Paramedic Post"; network = list("ss13","medbay") }, +/obj/item/wrench/medical, /turf/open/floor/plasteel/white, /area/medical/paramedic) "vFe" = ( @@ -41306,6 +41740,18 @@ "vFM" = ( /turf/open/floor/plasteel, /area/quartermaster/sorting) +"vFT" = ( +/obj/structure/bed, +/obj/effect/spawner/lootdrop/bedsheet, +/obj/machinery/button/door{ + id = "Dorm5"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 25; + specialfunctions = 4 + }, +/turf/open/floor/carpet/purple, +/area/crew_quarters/dorms) "vGi" = ( /obj/structure/cable{ icon_state = "1-2" @@ -41319,6 +41765,8 @@ /area/medical/virology) "vGn" = ( /obj/machinery/light, +/obj/vehicle/ridden/atv/snowmobile, +/obj/item/key, /turf/open/floor/pod/dark, /area/medical/paramedic) "vHU" = ( @@ -41430,17 +41878,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/pen/fourcolor, -/obj/item/paper_bin/bundlenatural{ - pixel_x = 6; - pixel_y = 4 - }, -/turf/open/floor/carpet, +/turf/open/floor/wood, /area/crew_quarters/dorms) "vKO" = ( /obj/effect/spawner/structure/window/reinforced, @@ -41457,16 +41895,15 @@ /turf/open/floor/plating, /area/bridge) "vKP" = ( -/obj/structure/weightmachine/stacklifter, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, /obj/machinery/computer/security/telescreen/entertainment{ pixel_y = -32 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "vKT" = ( @@ -41477,7 +41914,7 @@ dir = 1 }, /turf/open/floor/plating, -/area/storage/atmos) +/area/maintenance/department/electrical) "vLa" = ( /obj/structure/cable{ icon_state = "4-8" @@ -41601,6 +42038,10 @@ pixel_x = 3; pixel_y = 3 }, +/obj/item/reagent_containers/glass/beaker/cryoxadone{ + pixel_x = 5; + pixel_y = 9 + }, /turf/open/floor/plasteel/white, /area/medical/paramedic) "vNY" = ( @@ -41669,15 +42110,15 @@ dir = 8 }, /area/chapel/main) -"vQk" = ( -/obj/machinery/computer/holodeck{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/crew_quarters/dorms) "vQo" = ( /turf/closed/wall/r_wall, /area/engine/supermatter) +"vQz" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -27 + }, +/turf/open/floor/wood, +/area/crew_quarters/dorms) "vQW" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -41718,13 +42159,11 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/structure/disposalpipe/sorting/mail/flip{ dir = 4; sortType = 26 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "vSg" = ( @@ -41875,6 +42314,22 @@ }, /turf/open/floor/plating, /area/maintenance/department/electrical) +"vVJ" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8; + name = "west facing firelock" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "vVN" = ( /obj/effect/turf_decal/bot, /obj/structure/window/reinforced{ @@ -41887,7 +42342,7 @@ /area/crew_quarters/fitness) "vVZ" = ( /obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "vWg" = ( /obj/effect/turf_decal/delivery, @@ -42232,11 +42687,11 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "weS" = ( -/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/plating, /area/hallway/primary/aft) "wfN" = ( @@ -42262,7 +42717,7 @@ /obj/machinery/door/firedoor/border_only{ name = "south facing firelock" }, -/turf/open/floor/carpet, +/turf/open/floor/carpet/blue, /area/crew_quarters/dorms) "wgu" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible{ @@ -42281,6 +42736,20 @@ /obj/structure/chair/stool/bar, /turf/open/floor/wood, /area/crew_quarters/bar) +"wgM" = ( +/obj/structure/sink{ + dir = 8; + pixel_x = -12; + pixel_y = 2 + }, +/obj/structure/mirror{ + pixel_x = -28 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) "wha" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2o{ dir = 1 @@ -42733,7 +43202,7 @@ name = "Port Auxiliary Solar Array" }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, -/area/icemoon/surface/outdoors) +/area/solar/starboard/fore) "wuQ" = ( /obj/structure/table, /obj/machinery/plantgenes{ @@ -42925,7 +43394,7 @@ req_access_txt = "12;24" }, /turf/open/floor/plasteel, -/area/storage/atmos) +/area/maintenance/department/electrical) "wEm" = ( /obj/structure/barricade/wooden{ max_integrity = 10; @@ -43174,6 +43643,12 @@ /obj/machinery/chem_master/condimaster, /turf/open/floor/plasteel, /area/hydroponics) +"wMH" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/solar/starboard/aft) "wMJ" = ( /obj/structure/closet/secure_closet/bar{ req_access_txt = "25" @@ -43229,7 +43704,8 @@ icon_state = "4-8" }, /obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel/white, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "wPT" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, @@ -43331,11 +43807,9 @@ /turf/open/floor/plasteel/dark, /area/security/prison) "wSc" = ( -/obj/machinery/door/airlock/external{ - name = "Escape Airlock" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass, /turf/open/floor/carpet, /area/hallway/primary/port) "wSy" = ( @@ -43562,6 +44036,7 @@ /obj/machinery/light{ dir = 1 }, +/obj/machinery/vending/cigarette, /turf/open/floor/plasteel, /area/hallway/primary/fore) "xaS" = ( @@ -43613,22 +44088,10 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "xcL" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/window{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "xcY" = ( @@ -43658,6 +44121,14 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/central) +"xdr" = ( +/obj/item/storage/backpack/duffelbag/med/surgery, +/obj/structure/table, +/obj/structure/extinguisher_cabinet{ + pixel_y = 30 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "xdD" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ dir = 4 @@ -43666,9 +44137,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "xeI" = ( -/obj/machinery/conveyor_switch/oneway{ - id = "robo1" - }, /obj/structure/disposalpipe/segment{ dir = 9 }, @@ -43680,8 +44148,13 @@ /turf/open/floor/plasteel, /area/engine/atmos) "xfs" = ( -/obj/structure/table, -/obj/item/paicard, +/obj/machinery/door/airlock/public/glass{ + name = "Dormitory" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4; + name = "east facing firelock" + }, /turf/open/floor/carpet, /area/crew_quarters/dorms) "xfD" = ( @@ -43819,10 +44292,10 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, -/obj/machinery/door/airlock/external{ - name = "Escape Airlock" - }, /obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/glass{ + name = "Arrivals Airlock" + }, /turf/open/floor/plating, /area/hallway/secondary/exit/departure_lounge) "xka" = ( @@ -43885,6 +44358,7 @@ /obj/machinery/light{ dir = 4 }, +/obj/machinery/vending/wardrobe/robo_wardrobe, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "xmr" = ( @@ -44092,7 +44566,7 @@ /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "xtV" = ( /obj/structure/cable{ @@ -44104,6 +44578,7 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, +/obj/machinery/light/floor, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "xui" = ( @@ -44242,11 +44717,8 @@ /turf/open/floor/engine/plasma, /area/engine/atmos) "xAv" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible{ - dir = 6 - }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) +/turf/open/floor/carpet, +/area/crew_quarters/dorms) "xBi" = ( /obj/structure/cable{ icon_state = "4-8" @@ -44857,6 +45329,7 @@ /obj/structure/disposalpipe/trunk{ dir = 4 }, +/obj/machinery/disposal/bin, /turf/open/floor/wood, /area/crew_quarters/bar) "xUD" = ( @@ -44919,6 +45392,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"xWI" = ( +/obj/machinery/vending/cigarette, +/turf/open/floor/plasteel, +/area/hallway/primary/port) "xXS" = ( /obj/machinery/rnd/server, /obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ @@ -45156,7 +45633,7 @@ icon_state = "2-8" }, /turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) +/area/solar/port/aft) "ygB" = ( /obj/structure/cable{ icon_state = "2-8" @@ -45218,6 +45695,9 @@ icon_state = "1-8" }, /obj/effect/landmark/start/cyborg, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/service) "yiZ" = ( @@ -51538,17 +52018,17 @@ qrR qrR bTC avT -lbu -aQK -wuC +aPE +fne +iSB avT -lbu -aQK -wuC +aPE +fne +iSB avT -lbu -aQK -wuC +aPE +fne +iSB avT wuf yhx @@ -51795,17 +52275,17 @@ qrR qrR bTC avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT avT avT @@ -51853,7 +52333,7 @@ ydp ydp buI hnP -swQ +phs ghq ghq ghq @@ -52052,17 +52532,17 @@ qrR qrR bTC avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT avT avT @@ -52110,14 +52590,14 @@ ydp ydp buI buJ -cXI +ghq ghq hfZ shR ntV jso -shR -shR +tzb +iru hfZ ghq ghq @@ -52309,17 +52789,17 @@ avT avT avT avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT avT yhx @@ -52367,14 +52847,14 @@ ydp bTC buI buJ -cXI +ghq ghq shR shR -shR +onO liL scF -hse +lfD shR ghq ghq @@ -52566,17 +53046,17 @@ wuf wuf avT avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT -lbu +aPE qfJ -wuC +iSB avT wBg avT @@ -52585,12 +53065,12 @@ vrd vrd vrd vrd +nbC +nbC +nbC +nbC yhx -yhx -yhx -yhx -yhx -yhx +nbC yhx yhx yhx @@ -52624,12 +53104,12 @@ ydp buI fJZ phs -cXI +ghq ghq shR shR cpe -cpe +cUs cpe xIJ shR @@ -52824,15 +53304,15 @@ avT avT avT avT -hGK +guI avT avT avT -hGK +guI avT avT avT -hGK +guI avT aNg chZ @@ -52847,12 +53327,12 @@ avT avT avT avT +nbC +nbC +nbC +nbC yhx -yhx -yhx -yhx -yhx -yhx +nbC ydp ydp ydp @@ -52881,7 +53361,7 @@ ydp buI lGy ghq -cXI +ghq aJC shR qVf @@ -53077,21 +53557,21 @@ yhx yhx wuf avT -nuu -sXy -sXy -fNh -xUL -nyq -sXy -fNh -xUL -nyq -sXy -fNh -xUL -nyq -sXy +aKa +aPC +aPC +cXI +hrS +jvV +aPC +cXI +hrS +jvV +aPC +cXI +hrS +jvV +aPC eWw tnL iaq @@ -53138,12 +53618,12 @@ avT buI gJx ghq -cXI +ghq irN irr xIJ cpe -ooR +ghq cpe xIJ irr @@ -53338,15 +53818,15 @@ avT avT avT avT -clq +hse avT avT avT -clq +hse avT avT avT -clq +hse avT aNg chZ @@ -53395,9 +53875,9 @@ avT buI phs ghq -cXI +ghq +irr irr -tFu hmC rBA dfy @@ -53594,17 +54074,17 @@ fBG wuf avT avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT ajl avT @@ -53613,10 +54093,10 @@ vrd vrd vrd vrd -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC bBh avT avT @@ -53643,7 +54123,7 @@ avT avT avT avT -bmX +avT avT avT avT @@ -53652,8 +54132,8 @@ ayq ghq ghq ghq -tSd -lQp +ghq +vmr rQu rKd gHG @@ -53851,17 +54331,17 @@ qrR qrR avT avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT avT avT @@ -53873,7 +54353,7 @@ yhx yhx yhx yhx -yhx +nbC rUq sXy sXy @@ -54108,17 +54588,17 @@ qrR qrR wuf avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT avT avT @@ -54130,13 +54610,13 @@ yhx yhx yhx yhx +nbC +nbC +nbC +nbC yhx -yhx -yhx -yhx -yhx -yhx -yhx +nbC +nbC avT avT avT @@ -54152,7 +54632,7 @@ ydp avT avT avT -avT +bmX apJ apJ apJ @@ -54176,7 +54656,7 @@ cwT aAC mGl grZ -vdW +cIh ghq bUB bJf @@ -54365,17 +54845,17 @@ qrR qrR wuf avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT -lbu +aPE mmM -wuC +iSB avT avT avT @@ -54393,7 +54873,7 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT @@ -54433,7 +54913,7 @@ hva vZH lac iMX -lhr +cIh ghq bUB bJf @@ -54483,7 +54963,7 @@ wuf avT avT avT -bBh +fUc avT avT avT @@ -54622,17 +55102,17 @@ qrR qrR wuf avT -lbu -gTh -wuC +aPE +huF +iSB avT -lbu -gTh -wuC +aPE +huF +iSB avT -lbu -gTh -wuC +aPE +huF +iSB avT wuf avT @@ -54650,8 +55130,8 @@ yhx yhx yhx yhx -yhx -yhx +nbC +nbC ydp ydp ydp @@ -54740,7 +55220,7 @@ avT avT avT avT -bBh +fUc avT avT avT @@ -54997,7 +55477,7 @@ rxI rxI rxI avT -hGK +tEC avT rxI rxI @@ -55206,7 +55686,7 @@ nOG vEm fet avT -avT +stP avT ydp ydp @@ -55253,9 +55733,9 @@ pjD pjD pjD pjD -fNh -xUL -nyq +cih +pIs +ixO fsh fsh fsh @@ -55461,9 +55941,9 @@ azz aAF yiT pwE -fet -avT -avT +iMk +wMr +bEp bmX avT avT @@ -55511,7 +55991,7 @@ dfx dfx dfx avT -clq +uyV avT dfx dfx @@ -55720,7 +56200,7 @@ uKG vEm fet avT -avT +kHJ avT avT avT @@ -55768,7 +56248,7 @@ avT avT avT avT -bBh +fUc avT avT avT @@ -56025,7 +56505,7 @@ rxI rxI rxI avT -hGK +tEC avT rxI rxI @@ -56281,9 +56761,9 @@ pjD pjD pjD pjD -fNh -xUL -nyq +cih +pIs +ixO fsh fsh fsh @@ -56539,7 +57019,7 @@ dfx dfx dfx avT -clq +uyV avT dfx dfx @@ -56796,7 +57276,7 @@ avT avT avT avT -bBh +fUc avT avT avT @@ -57053,7 +57533,7 @@ rxI rxI rxI avT -hGK +tEC avT rxI rxI @@ -57309,9 +57789,9 @@ pjD pjD pjD pjD -fNh -xUL -nyq +cih +pIs +ixO fsh fsh fsh @@ -57567,7 +58047,7 @@ dfx dfx dfx avT -clq +uyV avT dfx dfx @@ -57824,7 +58304,7 @@ avT avT avT avT -bBh +fUc avT avT avT @@ -58007,7 +58487,7 @@ ydp ydp avT bBh -bmX +avT avT gLH ohf @@ -58081,7 +58561,7 @@ avT avT avT qlH -bBh +fUc qlH avT avT @@ -58286,8 +58766,8 @@ aFI iek wRz erO -aBK -dFJ +tmx +tmx kdA aFI avT @@ -58544,8 +59024,8 @@ cwH lam erO aBK -aDf -aEG +aBK +aBK aFI avT avT @@ -58800,8 +59280,8 @@ lWb dfa obB aAe -aBK -aDf +eXy +aEE aEE bxM avT @@ -59057,8 +59537,8 @@ aFI ays mQK auT -aBK -aDf +hBM +fol aEI bxM avT @@ -59314,7 +59794,7 @@ aFI uJF lam jcS -aBK +hBM aDc aEH bxM @@ -59571,8 +60051,8 @@ nEi jRU uzT gWn -aBK -aDf +hBM +jPf aEK bxM avT @@ -59828,7 +60308,7 @@ eGO ayt nuJ aAw -aBK +rRQ aEJ aEJ aIP @@ -60135,11 +60615,11 @@ yhx yhx yhx yhx -yhx +nbC xUL bBh xUL -yhx +nbC yhx yhx yhx @@ -60392,11 +60872,11 @@ yhx yhx yhx yhx -yhx +nbC xUL bBh xUL -yhx +nbC yhx yhx yhx @@ -60648,12 +61128,12 @@ yhx yhx yhx yhx -yhx -yhx +nbC +nbC xUL bBh xUL -yhx +nbC yhx yhx yhx @@ -60905,12 +61385,12 @@ yhx yhx yhx yhx -yhx +nbC avT xUL bBh xUL -yhx +nbC yhx yhx yhx @@ -61159,15 +61639,15 @@ yhx yhx yhx yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC euS sXy jAq -yhx -yhx +nbC +nbC yhx yhx yhx @@ -61417,13 +61897,13 @@ yhx yhx yhx yhx -yhx +nbC avT avT bBh xUL avT -yhx +nbC yhx yhx yhx @@ -61666,21 +62146,21 @@ yhx yhx yhx yhx +nbC +nbC +nbC +nbC +nbC +nbC +nbC yhx -yhx -yhx -yhx -yhx -yhx -yhx -yhx -yhx +nbC avT avT bBh xUL avT -yhx +nbC yhx yhx yhx @@ -61920,10 +62400,10 @@ yhx yhx yhx yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC avT xUL xUL @@ -61931,13 +62411,13 @@ xUL xUL avT avT -yhx +nbC xUL xUL bBh xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -62171,11 +62651,11 @@ yhx yhx yhx yhx -yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC +nbC yhx avT avT @@ -62193,7 +62673,7 @@ sXy sXy jAq xUL -yhx +nbC yhx yhx yhx @@ -62409,9 +62889,9 @@ odR dPx sPA sKh +dMo irt -irt -guI +srB avT avT avT @@ -62425,10 +62905,10 @@ ydp ydp ydp yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC avT avT avT @@ -62441,16 +62921,16 @@ xUL xUL xUL avT -yhx +nbC xUL xUL xUL xUL xUL avT -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -62666,7 +63146,7 @@ aLk aNo aOo sKh -irt +dMo srB bzc avT @@ -62682,7 +63162,7 @@ ydp ydp ydp yhx -yhx +nbC avT avT avT @@ -62696,16 +63176,16 @@ xUL xUL avT avT -yhx -yhx -yhx -yhx -yhx -yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC +nbC +nbC +nbC +nbC +nbC +nbC yhx yhx yhx @@ -62917,12 +63397,12 @@ aDb qWM hIH nuS -aPE +qsD wDR fHF -aPC -aPE -aPE +aVv +qsD +qsD hmM bzc bzc @@ -62949,11 +63429,11 @@ xUL xUL xUL avT -yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC +nbC yhx yhx yhx @@ -63174,12 +63654,12 @@ bxk bxk hIH iFl -aPC +aVv gCC qAF hOc aOp -aPE +qsD hmM bzc bzc @@ -63202,11 +63682,11 @@ avT euS jAq xUL -yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC +nbC yhx yhx yhx @@ -63431,12 +63911,12 @@ hTk vHU qTO aHD -aPC +aVv jOy lqt gPb hFv -aPC +aVv hmM bzc bzc @@ -63458,8 +63938,8 @@ avT euS jAq xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -63688,7 +64168,7 @@ srU aFO aFY aHD -aPC +aVv hxx vKT faR @@ -63714,8 +64194,8 @@ avT euS jAq xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -63945,7 +64425,7 @@ aDm hLZ aFY aHD -aPC +aVv cKK sub vrg @@ -63970,8 +64450,8 @@ avT euS jAq xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -64152,9 +64632,9 @@ ydp ydp ydp ydp -ydp -ydp -avT +bum +bum +bum avT mpj gNb @@ -64202,15 +64682,15 @@ aDp eZi aFU aHD -aPE +qsD jmf fLW utp itp -aPE +qsD aQV vcG -wgu +lzB avT avT ydp @@ -64226,8 +64706,8 @@ avT euS jAq xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -64410,8 +64890,8 @@ ydp ydp ydp ydp -ydp -avT +bum +bum avT mpj eSJ @@ -64459,12 +64939,12 @@ aDe rJk aFT jOj -aPE -aKa -aPE -aPE -aPE -aPE +qsD +mSN +qsD +qsD +qsD +qsD aQV vcG lzB @@ -64483,7 +64963,7 @@ euS jAq xUL avT -yhx +nbC yhx yhx yhx @@ -64667,7 +65147,7 @@ ydp ydp ydp ydp -ydp +bum ydp avT mpj @@ -64733,14 +65213,14 @@ ydp ydp ydp ydp -avT +bmX avT avT bBh xUL -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -64982,7 +65462,7 @@ xUL xUL vcG lzB -bmX +avT avT ydp ydp @@ -64995,8 +65475,8 @@ avT avT bBh xUL -yhx -yhx +nbC +nbC yhx yhx yhx @@ -65190,7 +65670,7 @@ avT avT avT xUL -vBe +xUL mbm iJl iJl @@ -65226,7 +65706,7 @@ xeI rqW rqW aGD -tJi +rqW myh qLm qTG @@ -65252,7 +65732,7 @@ avT avT bBh xUL -yhx +nbC yhx yhx yhx @@ -65479,9 +65959,9 @@ rQJ fwn awb rqW -ayC -rPU -fne +rqW +rqW +rqW rqW rqW fOA @@ -65509,7 +65989,7 @@ avT avT bBh xUL -yhx +nbC yhx yhx yhx @@ -65701,7 +66181,7 @@ ydp ydp avT avT -bmX +avT avT xUL ace @@ -65735,12 +66215,12 @@ iPX rQJ fpS wPD +ihY +rqW +rqW +rqW rqW -pIf -pIf -pIf rqW -aHK myh uJx ikk @@ -65766,7 +66246,7 @@ avT avT bBh xUL -yhx +nbC yhx yhx yhx @@ -65993,11 +66473,11 @@ rQJ fvz awb rqW -ayC -azH -fne rqW -aCr +rqW +rqW +rqW +rqW myh lHH oYn @@ -66008,7 +66488,7 @@ wUr avT avT avT -vcG +lcv wgu avT avT @@ -66023,7 +66503,7 @@ avT avT bBh xUL -yhx +nbC yhx yhx yhx @@ -66218,7 +66698,7 @@ avT avT avT avT -bGt +ace avT avT avT @@ -66475,7 +66955,7 @@ ydp avT avT avT -ace +bGt avT avT avT @@ -66510,8 +66990,8 @@ myh rQJ rQJ rQJ -myh -myh +eXO +kjx rQJ wUr wUr @@ -66767,9 +67247,9 @@ xxi ayD cGz sqg -avT -ydp -ydp +xdr +ihY +rQJ ydp ydp ydp @@ -67023,10 +67503,10 @@ oaS eqP tcj viF -ayG -avT -avT -ydp +sqg +pJm +ihY +rQJ ydp ydp ydp @@ -67281,9 +67761,9 @@ iat pEF nez sqg -avT -avT -avT +fEz +sae +rQJ ydp ydp ydp @@ -67538,9 +68018,9 @@ axr ayE nez sqg -ydp -ydp -avT +rQJ +rQJ +rQJ ydp ydp ydp @@ -67807,7 +68287,7 @@ ydp avT avT avT -vcG +lcv wgu avT avT @@ -68042,7 +68522,7 @@ ujE grz arP xWq -wje +xWI nrd wje sqg @@ -68792,7 +69272,7 @@ ace avT avT avT -bmX +avT avT avT avT @@ -69058,7 +69538,7 @@ avT avT avT vBe -xnm +tLb xUL rhX lXR @@ -69316,12 +69796,12 @@ avT avT xUL xnm -xUL +vBe eTu kHd ljT kHd -gVo +kHd rhX xUL xUL @@ -69573,7 +70053,7 @@ avT avT xUL xnm -xUL +vBe eTu kHd apK @@ -69606,7 +70086,7 @@ ydp ydp avT avT -vcG +lcv wgu avT avT @@ -69829,7 +70309,7 @@ avT avT avT vBe -xnm +tLb xUL rhX rhX @@ -70588,18 +71068,18 @@ avT avT avT ace -xUL vBe xUL -xUL -xUL -xUL vBe xUL xUL xUL vBe xUL +xUL +xUL +xUL +vBe xnm avT avT @@ -70626,9 +71106,9 @@ ydp ydp ydp ydp -avT -avT -avT +ydp +ydp +ydp avT avT avT @@ -70847,11 +71327,11 @@ avT pQd kLh kQr +qOJ lZn lZn lZn -lZn -lZn +qOJ lZn lZn lZn @@ -70881,12 +71361,12 @@ ydp ydp ydp avT -avT -avT -avT -avT -avT -avT +ydp +ydp +ydp +ydp +ydp +ydp avT avT avT @@ -71138,23 +71618,23 @@ ydp ydp avT avT +ydp +ydp +ydp +ydp +ydp +ydp avT avT avT -avT -avT -avT -avT -avT -avT -avT +xUL vcG lzB avT avT avT avT -bmX +avT ydp ydp ydp @@ -71360,7 +71840,7 @@ avT avT avT xZL -qZO +xBk avT avT avT @@ -71391,21 +71871,21 @@ ydp ydp ydp ydp +ydp avT avT +bmX +ydp +ydp +ydp +ydp +ydp +ydp +avT avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT -avT -vcG +lcv wgu xUL xUL @@ -71450,7 +71930,7 @@ nxv kYF bVM avT -bmX +avT ydp ydp ydp @@ -71629,7 +72109,7 @@ avT avT avT avT -bmX +avT avT avT ydp @@ -71651,17 +72131,17 @@ ydp avT avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL +ydp +ydp +ydp +ydp +ydp +ydp avT +avT +avT +avT +xUL vcG lzB xUL @@ -71873,8 +72353,8 @@ ydp avT avT avT -xZL -xBk +aez +qZO avT avT avT @@ -71907,18 +72387,18 @@ ydp avT avT avT +avT +ydp +ydp +ydp +ydp +ydp +ydp +ydp +avT +avT +avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB avT @@ -72164,17 +72644,17 @@ ydp avT avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL +avT +avT +ydp +ydp +ydp +ydp +ydp +avT +avT +avT +avT xUL vcG lzB @@ -72419,20 +72899,20 @@ ydp ydp ydp avT -bmX +avT +avT +avT +avT +avT +ydp +ydp +ydp +avT +avT +avT +avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB avT @@ -72678,18 +73158,18 @@ ydp avT avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL avT +avT +avT +avT +ydp +avT +avT +avT +avT +avT +avT +xUL vcG lzB avT @@ -72707,7 +73187,7 @@ avT avT avT avT -avT +bmX wql wql vEG @@ -72935,18 +73415,18 @@ ydp avT avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL avT +avT +avT +avT +avT +avT +avT +avT +avT +avT +avT +xUL vcG lzB avT @@ -73192,19 +73672,19 @@ ydp ydp avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL avT -vcG +avT +avT +avT +avT +avT +avT +ydp +ydp +avT +avT +xUL +lcv wgu avT avT @@ -73217,7 +73697,7 @@ ydp ydp ydp ydp -bmX +avT avT wql wql @@ -73429,7 +73909,8 @@ avT avT avT avT -avT +bmX +ydp ydp ydp ydp @@ -73449,18 +73930,17 @@ ydp ydp avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL avT +avT +avT +avT +avT +avT +ydp +ydp +ydp +avT +xUL vcG lzB avT @@ -73507,7 +73987,7 @@ bUD bVM avT avT -bmX +avT avT avT avT @@ -73704,20 +74184,20 @@ ydp ydp ydp ydp +ydp +ydp +avT +avT +avT +avT +avT +avT +avT +ydp +ydp avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB avT @@ -73929,7 +74409,7 @@ avT avT avT avT -xZL +aez qZO avT avT @@ -73961,20 +74441,20 @@ ydp ydp ydp ydp +ydp +ydp +avT +avT +avT +ydp +ydp +avT +avT +avT +avT avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB xUL @@ -74218,20 +74698,20 @@ ydp ydp ydp ydp +ydp +avT +avT +avT +avT +ydp +ydp +ydp +avT +avT +avT avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB xUL @@ -74477,20 +74957,20 @@ ydp ydp avT avT +ydp +ydp +avT +avT +avT +avT +avT +avT +avT +avT +avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -vcG -lzB +lcv +nDN xUL xUL xUL @@ -74733,19 +75213,19 @@ ydp ydp avT avT +ydp +ydp +ydp +avT +avT +avT +avT +avT +avT +avT +avT avT xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -avT vcG lzB xUL @@ -74800,7 +75280,7 @@ cer avT avT avT -bmX +avT avT avT avT @@ -74992,19 +75472,19 @@ avT avT avT avT -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL -xUL avT +avT +avT +avT +avT +avT +avT +avT +avT +avT +xUL vcG -wgu +lzB xUL xUL xUL @@ -75249,17 +75729,17 @@ avT avT avT avT -avT xUL xUL xUL -avT -avT xUL xUL xUL -avT -avT +xUL +xUL +xUL +xUL +xUL vcG lzB avT @@ -75512,7 +75992,7 @@ nGx nGx nGx nGx -nGx +hnN nGx nGx nGx @@ -75526,8 +76006,8 @@ avT avT bok unA -bJQ -bJQ +xjZ +xjZ unA avT avT @@ -75762,7 +76242,7 @@ avT avT avT avT -tFr +vcG dvc sLv sLv @@ -75985,7 +76465,7 @@ avT avT avT avT -xZL +aez qZO avT avT @@ -76033,7 +76513,7 @@ avT avT avT avT -bmX +avT avT avT bok @@ -76094,7 +76574,7 @@ ruD clR avT avT -bmX +avT avT avT avT @@ -76534,7 +77014,7 @@ gky vmM jOo azc -lzB +nDN avT avT avT @@ -76559,7 +77039,7 @@ wcB unA avT avT -bmX +avT avT bwt cTD @@ -76808,7 +77288,7 @@ ncg aXh jHC bok -ivM +uFq bok unA uFq @@ -77263,12 +77743,12 @@ ydp ydp ydp ydp -avT -avT -avT -avT -avT -avT +pgp +iHM +iHM +iHM +iHM +iHM avT xZL xBk @@ -77520,15 +78000,15 @@ ydp ydp ydp ydp +pgp +sTt +nRA +pDg +qSF +iHM avT -avT -avT -bHt -nZE -nZE -nZE aez -xBk +qZO avT avT ydp @@ -77561,7 +78041,7 @@ kxI dPM xNs wwx -nDd +aAh aDQ avT avT @@ -77777,15 +78257,15 @@ ydp ydp ydp avT -avT -avT -avT +pgp +xAv +xAv mps xAv -ruo -ruo +iHM +avT acQ -aUb +xBk avT avT avT @@ -78021,28 +78501,28 @@ yhx yhx yhx yhx -ydp -ydp -ydp -ydp -ydp -ydp +nbC +nbC +nbC +pgp +pgp +pgp +pgp +pgp +pgp +pgp +pgp +pgp +pgp +pgp +rKC +bjR +xAv +xAv +pgp avT -avT -avT -avT -avT -avT -avT -avT -avT -avT -axL -aaM -nZE -nZE -abU -vBe +xZL +nYd avT avT avT @@ -78278,28 +78758,28 @@ yhx yhx yhx yhx -ydp -ydp -ydp -ydp -ydp -ydp +nbC +nbC avT -avT -avT -avT -avT -avT -iHM +pgp +tJi +vdW +pgp +tJi +vdW +pgp +tJi +vdW +pgp tOz -iHM +tUq gCO -iHM -axN -ruo -ruo -aAh -vzS +hvG +pgp +pgp +pgp +xZL +xBk avT ydp ydp @@ -78535,27 +79015,27 @@ yhx yhx yhx yhx -ydp -ydp -ydp -ydp -ydp -ydp avT avT avT -avT -avT -avT -iHM -kRk -iHM -kRk -iHM -avT -avT -avT -xZL +pgp +tSd +vzS +pgp +tSd +rEF +pgp +tSd +vFT +pgp +vow +swQ +gCO +swQ +kXL +mtP +tWs +aez xBk avT ydp @@ -78591,13 +79071,13 @@ spa dIj pIH bpT +dMo irt irt +dMo irt irt -irt -irt -irt +dMo gZS uyK aRt @@ -78792,27 +79272,27 @@ yhx yhx yhx yhx -ydp -ydp -ydp -ydp -ydp -ydp avT -avT -iHM -iHM -iHM -iHM -iHM +pgp +pgp +pgp +uRg +pgp +pgp +kWz +pgp +pgp +eCS +pgp +pgp vow -iHM -vow -iHM -iHM -iHM -iHM -xZL +swQ +gCO +swQ +kXL +mtP +tWs +aez xBk avT ydp @@ -79048,26 +79528,26 @@ yhx yhx yhx yhx -yhx -ydp -ydp -ydp -ydp -ydp -ydp -avT +ooR avT iHM -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD +oME +rPU +swQ +fSb +pqm +swQ +swQ +rPU +swQ +swQ +vQz +vow +swQ +gCO +swQ +iHM +rbb iHM xZL xBk @@ -79103,8 +79583,8 @@ cPI hPe vAs ktw -xZL -lzB +aez +nDN avT avT avT @@ -79305,26 +79785,26 @@ ydp ydp ydp ydp -ydp -ydp -ydp -ydp -ydp -ydp -ydp avT avT iHM -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD +pIf +swQ +swQ +swQ +swQ +jjB +ugk +ugk +ugk +ugk +ugk +fkA +ugk +hUg +qim +iHM +iHM iHM xZL xBk @@ -79346,7 +79826,7 @@ ydp ydp ydp avT -bmX +avT avT avT avT @@ -79360,7 +79840,7 @@ spa vir fkr ktw -oME +xZL lzB avT avT @@ -79562,27 +80042,27 @@ ydp ydp ydp ydp -ydp -ydp -ydp -ydp -ydp -ydp -avT avT avT iHM -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD +ruo +tFu +swQ +swQ +hWp +ptH +iQu +iQu +iQu +iQu +mHm +bfo +swQ +gCO iHM +lJC +avT +avT xZL xBk avT @@ -79820,29 +80300,29 @@ ydp ydp ydp ydp -ydp -ydp -ydp -ydp -avT -avT -avT avT +pgp +pgp +pgp +raM +raM +raM +raM +mfU +raM +raM +raM +pgp +vVJ +hCx +lOa iHM -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -iHM -xZL -xBk -vBe +avT +avT +avT +aez +qZO +xUL ydp ydp ydp @@ -79957,7 +80437,7 @@ jQj avT avT avT -bmX +avT avT avT avT @@ -80078,25 +80558,25 @@ ydp ydp ydp ydp -ydp -ydp -ydp +pgp +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +raM +eoH +xAv +nJB +iHM +avT +avT avT -xUL -cav -xUL -iHM -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -kHD -iHM xZL xBk xUL @@ -80125,7 +80605,7 @@ sLv sLv sLv sLv -sLv +cEs sLv sLv sLv @@ -80335,25 +80815,25 @@ ydp ydp ydp ydp -ydp -ydp +raM +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +raM +nlF +xAv +oUT +iHM +avT avT avT -xUL -xUL -xUL -iHM -iHM -iHM -iHM -iHM -nlF -iHM -nlF -iHM -iHM -iHM -iHM xZL xBk avT @@ -80592,20 +81072,20 @@ ydp ydp ydp ydp -ydp -ydp -avT -avT -xUL -xUL -xUL -avT -avT -avT -avT -iHM -lJN -vQk +raM +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +raM +nlF +xAv gUc iHM avT @@ -80849,21 +81329,21 @@ ydp ydp ydp ydp -ydp -ydp -avT -pgp -xUL -xUL -xUL -pgp -avT -avT -avT -iHM -kRk -kRk -kRk +raM +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +kHD +raM +nlF +xAv +oUT iHM avT avT @@ -81106,28 +81586,28 @@ ydp ydp ydp ydp -ydp -avT -avT pgp -xUL -bSC -xUL -pgp -avT -avT -avT -iHM -vow -iHM -vow +kHD +kHD +kHD +fIk +kHD +kHD +kHD +kHD +kHD +kHD +raM +eoH +xAv +nJB iHM avT avT avT -xZL -xBk -iSB +aez +qZO +avT wdv xUL xUL @@ -81363,18 +81843,18 @@ ydp ydp ydp ydp -avT -avT -iHM -iHM +pgp +pgp pgp raM -iHM pgp -iHM -iHM -iHM -iHM +raM +raM +mfU +raM +raM +raM +pgp rRk xfs qHL @@ -81503,7 +81983,7 @@ avT avT avT avT -avT +bmX ydp ydp ydp @@ -81625,20 +82105,20 @@ xUL aNL mtP dvs -mtP -mtP -dAi -mtP -mtP -mtP -mtP -mtP -lLv -mtP +jjB +kIV +ugk +ugk +ugk +ugk +utY +mEH +ugk +hUg oBD iHM -lJC -lJC +iHM +iHM xZL xBk avT @@ -81661,7 +82141,7 @@ avT avT avT tFr -lzB +nDN avT avT avT @@ -81882,30 +82362,30 @@ xUL aNL fTM dvs -mtP +swQ naE -mtP +bqb aaU nOY -mtP -naE +iwH +hlQ duB tsK -tsK +nEH tsK iuC -tsK +cTV pXb aSE xBk xUL xUL xUL +xUL +xUL vBe xUL xUL -xUL -xUL vBe xUL xUL @@ -81915,7 +82395,7 @@ xUL vBe xUL xUL -xUL +vBe xUL vcG lzB @@ -81975,7 +82455,7 @@ anA wbT rTs hTL -uRg +hTL jab jFy qJV @@ -82140,39 +82620,39 @@ iHM pgp pgp pgp -pgp +eyc fPM pgp pgp pgp pgp vhb -mtP +swQ vDI ugk hAx -ugk +ord nrY -vsM +vko aUb xUL xUL xUL xUL xUL +vBe +xUL +xUL +vBe xUL xUL xUL xUL xUL +vBe xUL xUL -xUL -xUL -xUL -xUL -xUL -xUL +vBe xUL vcG lzB @@ -82392,19 +82872,19 @@ xUL ydp ydp ydp -bmX +avT avT pgp aab dZV -dZV -gLk +wgM +kdy pgp qFH nBd wfS iJs -mtP +swQ sgL qxk pgp @@ -82418,7 +82898,7 @@ xUL xUL xUL avT -bmX +avT avT avT avT @@ -82478,7 +82958,7 @@ vAs vAs krT pze -bEi +sLF bEi lbp bAs @@ -82654,25 +83134,25 @@ avT pgp aac gLk -gLk -gLk +hHV +kdy pgp vVZ mWy pgp iJs -mtP +swQ inA qMn pgp -wdv -wdv +pgp +pgp +xUL +xUL +xUL +xUL +vBe vBe -xUL -xUL -xUL -xUL -xUL xUL avT avT @@ -82740,7 +83220,7 @@ bFT bCO gRE thV -bCO +qBl bEa kxj aaw @@ -82911,7 +83391,7 @@ avT pgp aab aad -gLk +gdH fBs pgp pgp @@ -83457,10 +83937,10 @@ ydp ydp avT avT -bmX +avT avT tFr -lzB +nDN avT avT ydp @@ -84178,7 +84658,7 @@ ydp ydp ydp ydp -avT +bmX avT ydp ydp @@ -84693,7 +85173,7 @@ ydp ydp avT avT -bmX +avT avT avT avT @@ -84795,7 +85275,7 @@ hJE cmC aIt bCO -bBN +hyx vTF tRe eVp @@ -85080,7 +85560,7 @@ bPn avT avT avT -bmX +avT avT avT avT @@ -85259,7 +85739,7 @@ ydp avT avT tFr -lzB +nDN avT avT avT @@ -85432,23 +85912,23 @@ yhx wuf avT nuu -sXy -sXy +aar +aar fNh -xUL +abU nyq -sXy +aar fNh -xUL +abU nyq -sXy +aar fNh -xUL +abU nyq -sXy -sXy -sXy -sXy +aar +aar +aar +aar sDD eNK jwc @@ -86290,7 +86770,7 @@ vcG lzB avT avT -bmX +avT avT ydp ydp @@ -86512,7 +86992,7 @@ mGp rgm wAx wAx -wAx +ule uEz uEz wzf @@ -87026,11 +87506,11 @@ mKv sAh sAh acb -aar +urI +uEz +uEz uEz uEz -hrS -lQJ lia uvB tOY @@ -87058,7 +87538,7 @@ xUL xUL avT tFr -lzB +nDN avT avT ydp @@ -87103,7 +87583,7 @@ avT avT avT avT -bmX +avT avT avT avT @@ -87285,10 +87765,10 @@ sAh acb urI qkO -uEz -blD +qnx kge -gls +kge +qnx tgd tRC pJS @@ -87382,7 +87862,7 @@ avT avT avT avT -bmX +avT avT avT ydp @@ -87542,12 +88022,12 @@ qss qss ylW uoV -uEz -blD +qnx +pgk pgk bKl -iNK -chN +tgd +tRC pJS sWD bNF @@ -87799,9 +88279,9 @@ sAh acb urI uoV -uEz -blD -pgk +qnx +kbE +kbE qnx pbf sFw @@ -87884,7 +88364,7 @@ sXy ikA avT avT -bmX +avT avT avT avT @@ -88056,10 +88536,10 @@ sAh acb urI uoV -uEz -blD -eLl -igK +qnx +kge +kge +qnx xcL hop pJS @@ -88287,14 +88767,14 @@ ydp ydp ydp ydp -bmX +avT avT avT bBh avT aKf irQ -huF +cfp cfp gxY cfp @@ -88313,11 +88793,11 @@ qss oXl pPz uoV -uEz -hsQ -cDO -jAT -nmL +qnx +pgk +pgk +qnx +tgd vKP pJS hNg @@ -88405,7 +88885,7 @@ ydp ydp ydp ydp -avT +bmX avT ydp ydp @@ -88552,7 +89032,7 @@ avT aKf irQ jLG -piu +lhr piu xac gNI @@ -88570,12 +89050,12 @@ wAx wAx wAx hru -uEz -uEz -uEz -ejw -rTv -eOO +qnx +kbE +kbE +qnx +tgd +tRC pJS hNg bNF @@ -88802,7 +89282,7 @@ ydp ydp ydp avT -avT +bmX ydp bBh avT @@ -88830,9 +89310,9 @@ pbg uEz uEz uEz -ejw -rTv -eOO +cvN +gjZ +tRC pJS jiY bNF @@ -88857,7 +89337,7 @@ xUL xiw avT tFr -lzB +nDN avT avT avT @@ -88945,7 +89425,7 @@ ydp ydp ydp avT -bmX +avT avT ydp ydp @@ -90607,7 +91087,7 @@ bBh avT aKf gLO -jvV +cfp evO cfp kBe @@ -90656,7 +91136,7 @@ avT avT avT tFr -lzB +nDN avT avT avT @@ -91422,7 +91902,7 @@ uMF jsl gFM cuY -nGx +hnN nGx nGx nGx @@ -91679,11 +92159,11 @@ dks nEl ust sHJ +cEs sLv sLv sLv sLv -ybT asr avT avT @@ -91989,12 +92469,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT bBh avT -yhx +nbC yhx yhx yhx @@ -92195,7 +92675,7 @@ lGB jJu avT avT -bmX +avT avT avT avT @@ -92246,12 +92726,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT bBh avT -yhx +nbC yhx yhx yhx @@ -92399,8 +92879,8 @@ bqN avT xUL xUL -bmX avT +bmX bxL bxL bxL @@ -92408,7 +92888,7 @@ xUL bxL dri dri -dDC +uot nQp kVx eLQ @@ -92503,12 +92983,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT bBh avT -yhx +nbC yhx yhx yhx @@ -92641,7 +93121,7 @@ avT avT bzc xUL -avT +bmX avT ydp ydp @@ -92660,7 +93140,7 @@ avT avT bxL bxL -bum +axN xUL xUL dri @@ -92758,14 +93238,14 @@ yhx yhx yhx yhx -yhx -yhx -yhx +nbC +nbC +nbC avT avT bBh avT -yhx +nbC yhx yhx yhx @@ -92895,7 +93375,7 @@ ydp ydp ydp avT -avT +bum bzh xUL avT @@ -92917,7 +93397,7 @@ avT bxL bxL bum -bum +axN xUL xUL rww @@ -92925,7 +93405,7 @@ rww rww ttQ lNU -bZI +nDd bZI nNV dBP @@ -93015,14 +93495,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT avT bBh avT -yhx +nbC yhx yhx yhx @@ -93152,9 +93632,9 @@ ydp ydp ydp avT -avT -avT -bmX +bum +bum +bum avT avT ydp @@ -93174,7 +93654,7 @@ bxL bxL bum bum -bum +axN xUL xUL jrq @@ -93272,14 +93752,14 @@ yhx yhx yhx yhx -yhx +nbC avT euS sXy sXy jAq avT -yhx +nbC yhx yhx yhx @@ -93409,10 +93889,10 @@ ydp ydp ydp ydp -avT -avT -avT -avT +bum +bum +bum +bum ydp ydp ydp @@ -93431,7 +93911,7 @@ bKI bum bum bum -bum +axN xUL xUL rww @@ -93529,14 +94009,14 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT avT avT -yhx +nbC yhx yhx yhx @@ -93667,7 +94147,7 @@ ydp ydp avT avT -avT +bum avT avT ydp @@ -93688,7 +94168,7 @@ bKI bum bum bum -bum +axN xUL xUL dri @@ -93786,14 +94266,14 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -93945,7 +94425,7 @@ bKI bum bum bum -bum +axN xUL xUL wmB @@ -94043,12 +94523,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -94199,10 +94679,10 @@ bKI bCC bCC bKI -bum -bum -bum -bum +azH +azH +azH +aHK xUL xUL fen @@ -94245,7 +94725,7 @@ qzz uqa iIQ avT -bmX +avT avT avT ydp @@ -94300,12 +94780,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -94557,7 +95037,7 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT @@ -94709,7 +95189,7 @@ bqN bqN bqN bxL -bum +axN xUL xUL xUL @@ -94814,12 +95294,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -94966,8 +95446,8 @@ bqN bqN bxL bxL -bum -bum +ayC +aEG xUL xUL bKI @@ -95071,12 +95551,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -95224,7 +95704,7 @@ bqN bqN bxL bum -bum +axN xUL xUL bKI @@ -95328,12 +95808,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -95481,7 +95961,7 @@ bqN bxL bxL bum -bum +axN xUL xUL bKI @@ -95585,12 +96065,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -95737,8 +96217,8 @@ bqN bqN bxL bxL -bum -bum +azH +aHK xUL xUL bKI @@ -95840,14 +96320,14 @@ yhx yhx yhx yhx -yhx -yhx -yhx +nbC +nbC +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -96005,7 +96485,7 @@ bKI bKI bMT fgj -nOk +lQp lfG sdr gyE @@ -96097,14 +96577,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -96359,9 +96839,9 @@ avT avT avT bBh -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -96508,9 +96988,9 @@ bqN bqN bxL bxL -bum -bum -bum +aCr +aCr +aEG xUL bOb bKI @@ -96611,7 +97091,7 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT @@ -96767,7 +97247,7 @@ bqN bxL bum bum -bum +axN xUL bOb bKI @@ -96868,12 +97348,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -97024,7 +97504,7 @@ bqN bxL bum bum -bum +axN xUL bOb bKI @@ -97073,7 +97553,7 @@ wFO mZp avT avT -bmX +avT avT avT avT @@ -97125,12 +97605,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -97281,7 +97761,7 @@ bqN bxL bum bum -bum +axN xUL bOb bKI @@ -97382,12 +97862,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -97538,13 +98018,13 @@ bqN bxL bum bum -bum +axN xUL bOb -xUL -xUL -xUL -xUL +dDC +bum +bum +axN xbp onY gNy @@ -97639,12 +98119,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -97795,13 +98275,13 @@ bxL bxL bxL bum -bum +axN xUL bOb -bum -bum -bum -bum +dFJ +azH +azH +aHK xbp fen eHK @@ -97896,12 +98376,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -98052,7 +98532,7 @@ bxL bxL bxL bum -bum +axN bDA bGW bYY @@ -98153,12 +98633,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -98309,7 +98789,7 @@ bxL bxL bxL bum -bum +axN bFx bOb bKI @@ -98410,7 +98890,7 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT @@ -98566,7 +99046,7 @@ bqN bqN bxL bum -bum +axN bFx bRD caS @@ -98667,14 +99147,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -98823,7 +99303,7 @@ bqN bxL bxL bum -bum +axN aEF bYY ccD @@ -98924,14 +99404,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -99079,8 +99559,8 @@ bqN bqN bxL bxL -bum -bum +azH +aHK xUL xUL bKI @@ -99181,14 +99661,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -99340,12 +99820,13 @@ xUL xUL xUL xUL +dDC bum bum -bum -bum +axN xbp xUL +dDC bum bum bum @@ -99359,8 +99840,7 @@ bum bum bum bum -bum -bum +axN rGc jPj ucC @@ -99438,14 +99918,14 @@ yhx yhx yhx yhx -yhx -yhx -yhx +nbC +nbC +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -99597,27 +100077,27 @@ xUL xUL xUL xUL -bum -bum -bum -bum +dFJ +azH +azH +aHK xbp xUL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +dFJ +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +aHK dQW jls ucC @@ -99697,12 +100177,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -99850,8 +100330,8 @@ bqN bqN bxL bxL -bum -bum +aCr +aEG xUL xUL xUL @@ -99954,7 +100434,7 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT @@ -100108,7 +100588,7 @@ bqN bxL bxL bum -bum +axN xUL xUL xUL @@ -100211,12 +100691,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -100366,24 +100846,24 @@ bxL bxL bxL bum -bum -bum -bum -bum -bum -bum +aCr +aCr +aCr +aCr +aCr +aEG xbp xUL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +lQJ +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aEG rGc tdX tdX @@ -100397,7 +100877,7 @@ aNU kVD noQ leT -leT +mqd leT iCq leT @@ -100408,7 +100888,7 @@ wku xGy lBH bnU -bmX +avT avT ydp ydp @@ -100468,12 +100948,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -100628,9 +101108,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -100639,8 +101120,7 @@ bum bum bum bum -bum -bum +axN dQW tdX tdX @@ -100725,12 +101205,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -100885,9 +101365,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -100896,8 +101377,7 @@ bum bum bum bum -bum -bum +axN rGc tdX tdX @@ -100982,12 +101462,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -101142,9 +101622,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -101153,8 +101634,7 @@ bum bum bum bum -bum -bum +axN dQW tdX tdX @@ -101244,7 +101724,7 @@ avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -101399,9 +101879,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -101410,8 +101891,7 @@ bum bum bum bum -bum -bum +axN rGc jPj dQW @@ -101494,14 +101974,14 @@ yhx yhx yhx yhx -yhx -yhx -yhx +nbC +nbC +nbC avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -101656,9 +102136,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -101667,8 +102148,7 @@ bum bum bum bum -bum -bum +axN dQW cly cly @@ -101751,14 +102231,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -101913,9 +102393,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -101924,8 +102405,7 @@ bum bum bum bum -bum -bum +axN xUL xUL xUL @@ -102008,14 +102488,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh avT avT -yhx +nbC yhx yhx yhx @@ -102170,9 +102650,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -102181,8 +102662,7 @@ bum bum bum bum -bum -bum +axN xUL xUL xUL @@ -102265,14 +102745,14 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx -yhx -yhx +nbC +nbC +nbC yhx yhx yhx @@ -102427,9 +102907,10 @@ bum bum bum bum -bum +axN xbp xUL +dDC bum bum bum @@ -102438,16 +102919,15 @@ bum bum bum bum -bum -bum +axN xUL xUL xUL xUL xUL -bum -bum -bum +lQJ +aCr +aCr hBq pCv iuP @@ -102522,12 +103002,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -102679,24 +103159,24 @@ bqN bxL bxL bxL -bum -bum -bum -bum -bum -bum +azH +azH +azH +azH +azH +aHK xbp xUL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +dFJ +azH +azH +azH +azH +azH +azH +azH +azH +aHK xUL xUL xUL @@ -102779,12 +103259,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -103036,12 +103516,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -103293,12 +103773,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -103450,27 +103930,27 @@ bqN bqN bxL bxL -bum -bum -bum -bum -bum -bum +aCr +aCr +aCr +aCr +aCr +aEG xUL xUL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +lQJ +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aEG xUL xbp sTq @@ -103550,12 +104030,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -103712,9 +104192,10 @@ bum bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -103726,11 +104207,10 @@ bum bum bum bum -bum -bum +axN xUL xbp -sTq +lgg hBq xBV hBq @@ -103750,7 +104230,7 @@ avT avT avT avT -bmX +avT ydp ydp ydp @@ -103807,12 +104287,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -103969,9 +104449,10 @@ bum bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -103983,8 +104464,7 @@ bum bum bum bum -bum -bum +axN rGc rvf umD @@ -104064,12 +104544,12 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx +nbC yhx yhx yhx @@ -104226,9 +104706,10 @@ bum bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -104240,8 +104721,7 @@ bum bum bum bum -bum -bum +axN odg xbp bZa @@ -104321,13 +104801,13 @@ yhx yhx yhx yhx -yhx +nbC avT avT avT bBh -yhx -yhx +nbC +nbC yhx yhx yhx @@ -104351,7 +104831,7 @@ faJ rot avT jxB -aQK +sQk rot avT wuf @@ -104483,9 +104963,10 @@ bum bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -104497,12 +104978,11 @@ bum bum bum bum -bum -bum +axN odg xbp -sTq -sTq +cVa +qZb lHa nQd umD @@ -104584,8 +105064,8 @@ avT avT bBh avT -yhx -yhx +nbC +nbC yhx yhx yhx @@ -104608,7 +105088,7 @@ vDy rot avT jxB -qfJ +qjF rot avT wuf @@ -104740,9 +105220,10 @@ bum bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -104754,12 +105235,11 @@ bum bum bum bum -bum -bum +axN odg xbp -sTq -sTq +lgg +oGZ pQg tFN tFN @@ -104835,13 +105315,13 @@ yhx yhx yhx yhx -yhx -yhx -yhx +nbC +nbC +nbC avT bBh avT -yhx +nbC yhx yhx yhx @@ -104865,7 +105345,7 @@ vDy rot avT jxB -qfJ +qjF rot avT wuf @@ -104997,9 +105477,10 @@ bxL bum bum bum -bum +axN xUL xUL +dDC bum bum bum @@ -105011,8 +105492,7 @@ bum bum bum bum -bum -bum +axN dQW rvf cly @@ -105094,12 +105574,12 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT -yhx -yhx +nbC +nbC yhx yhx yhx @@ -105122,7 +105602,7 @@ vDy rot avT jxB -qfJ +qjF rot avT avT @@ -105254,9 +105734,10 @@ bxL bxL bxL bum -bum +axN xUL xUL +dDC bum bum bum @@ -105268,8 +105749,7 @@ bum bum bum bum -bum -bum +axN xUL wDd alE @@ -105351,7 +105831,7 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT @@ -105379,7 +105859,7 @@ vDy rot avT jxB -qfJ +qjF rot avT avT @@ -105514,22 +105994,22 @@ bKI bKI xUL xUL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +dFJ +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +azH +aHK +xUL +xUL +xUL xUL bOb xUL @@ -105608,7 +106088,7 @@ yhx yhx yhx yhx -yhx +nbC avT bBh avT @@ -105628,15 +106108,15 @@ avT avT avT avT -hGK +jEm avT avT avT -hGK +jEm avT avT avT -hGK +jEm avT avT avT @@ -105865,7 +106345,7 @@ yhx yhx yhx yhx -yhx +nbC avT rUq sXy @@ -105877,26 +106357,26 @@ oBl uyM dUH fUm -sXy -sXy -sXy -sXy -sXy -sXy -sXy -fNh -xUL -xUL -xUL -xUL -xUL -nyq -sXy -fNh -xUL -nyq -sXy -sXy +wMH +wMH +wMH +wMH +wMH +wMH +wMH +cWI +jWw +jWw +jWw +jWw +jWw +gIW +wMH +cWI +jWw +gIW +wMH +wMH uRc avT wuf @@ -106122,8 +106602,8 @@ yhx yhx yhx yhx -yhx -yhx +nbC +nbC avT avT avT @@ -106142,15 +106622,15 @@ avT avT avT avT -clq +oPk avT avT avT -clq +oPk avT avT avT -clq +oPk avT avT avT @@ -106285,24 +106765,24 @@ bKI bKI bxL bxL -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum -bum +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr +aCr bxL bqN bqN @@ -106311,7 +106791,7 @@ bqN avT avT avT -bmX +avT avT avT avT @@ -106399,15 +106879,15 @@ avT avT avT jxB -mmM +qIW rot avT jxB -mmM +qIW rot avT jxB -knR +lQd rot avT avT @@ -106637,11 +107117,11 @@ yhx yhx yhx yhx -yhx -yhx -yhx -yhx -yhx +nbC +nbC +nbC +nbC +nbC yhx yhx yhx @@ -106656,15 +107136,15 @@ avT avT avT jxB -mmM +qIW rot avT jxB -mmM +qIW rot avT jxB -knR +lQd rot avT avT @@ -106913,15 +107393,15 @@ avT avT avT jxB -mmM +qIW rot avT jxB -mmM +qIW rot avT jxB -knR +lQd rot avT wuf @@ -107170,15 +107650,15 @@ avT avT avT jxB -mmM +qIW rot avT jxB -mmM +qIW rot avT jxB -knR +lQd rot avT wuf @@ -107427,15 +107907,15 @@ avT avT avT jxB -gTh +pvP rot avT jxB -gTh +pvP rot avT jxB -gTh +pvP rot avT wuf diff --git a/_maps/shuttles/emergency_arena.dmm b/_maps/shuttles/emergency_arena.dmm index 1314b8a732..2ba9206830 100644 --- a/_maps/shuttles/emergency_arena.dmm +++ b/_maps/shuttles/emergency_arena.dmm @@ -43,7 +43,7 @@ }, /area/shuttle/escape/arena) "l" = ( -/obj/structure/closet/crate/necropolis/tendril, +/obj/structure/closet/crate/necropolis/tendril/magic, /turf/open/indestructible/necropolis/air, /area/shuttle/escape/arena) "m" = ( @@ -65,10 +65,18 @@ /obj/structure/healingfountain, /turf/open/indestructible/necropolis/air, /area/shuttle/escape/arena) +"t" = ( +/obj/structure/closet/crate/necropolis/tendril/misc, +/turf/open/indestructible/necropolis/air, +/area/shuttle/escape/arena) "z" = ( /obj/effect/landmark/shuttle_arena_safe, /turf/open/indestructible/necropolis/air, /area/shuttle/escape/arena) +"H" = ( +/obj/structure/closet/crate/necropolis/tendril/weapon_armor, +/turf/open/indestructible/necropolis/air, +/area/shuttle/escape/arena) (1,1,1) = {" a @@ -264,16 +272,16 @@ m l j m -l +H j k -l +H j m -l +t j m -j +t j p g @@ -524,16 +532,16 @@ m l j m -l +H j m -l +H j m -l +t j m -j +t j p g diff --git a/byond-extools.dll b/byond-extools.dll index bd6b34c48e..af036e9147 100644 Binary files a/byond-extools.dll and b/byond-extools.dll differ diff --git a/byond-extools.pdb b/byond-extools.pdb new file mode 100644 index 0000000000..c80101f6b5 Binary files /dev/null and b/byond-extools.pdb differ diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 035563627f..a8026f752b 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -79,21 +79,22 @@ //DNA - Because fuck you and your magic numbers being all over the codebase. #define DNA_BLOCK_SIZE 3 -#define DNA_UNI_IDENTITY_BLOCKS 14 +#define DNA_UNI_IDENTITY_BLOCKS 15 #define DNA_HAIR_COLOR_BLOCK 1 #define DNA_FACIAL_HAIR_COLOR_BLOCK 2 #define DNA_SKIN_TONE_BLOCK 3 -#define DNA_EYE_COLOR_BLOCK 4 -#define DNA_GENDER_BLOCK 5 -#define DNA_FACIAL_HAIR_STYLE_BLOCK 6 -#define DNA_HAIR_STYLE_BLOCK 7 -#define DNA_COLOR_ONE_BLOCK 8 -#define DNA_COLOR_TWO_BLOCK 9 -#define DNA_COLOR_THREE_BLOCK 10 -#define DNA_MUTANTTAIL_BLOCK 11 -#define DNA_MUTANTEAR_BLOCK 12 -#define DNA_MUTANTMARKING_BLOCK 13 -#define DNA_TAUR_BLOCK 14 +#define DNA_LEFT_EYE_COLOR_BLOCK 4 +#define DNA_RIGHT_EYE_COLOR_BLOCK 5 +#define DNA_GENDER_BLOCK 6 +#define DNA_FACIAL_HAIR_STYLE_BLOCK 7 +#define DNA_HAIR_STYLE_BLOCK 8 +#define DNA_COLOR_ONE_BLOCK 9 +#define DNA_COLOR_TWO_BLOCK 10 +#define DNA_COLOR_THREE_BLOCK 11 +#define DNA_MUTANTTAIL_BLOCK 12 +#define DNA_MUTANTEAR_BLOCK 13 +#define DNA_MUTANTMARKING_BLOCK 14 +#define DNA_TAUR_BLOCK 15 #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 diff --git a/code/__DEFINES/_extools.dm b/code/__DEFINES/_extools.dm new file mode 100644 index 0000000000..4513243aae --- /dev/null +++ b/code/__DEFINES/_extools.dm @@ -0,0 +1 @@ +#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so") diff --git a/code/__DEFINES/admin/keybindings.dm b/code/__DEFINES/admin/keybindings.dm index fcfe7c5e58..e8616fd3ce 100644 --- a/code/__DEFINES/admin/keybindings.dm +++ b/code/__DEFINES/admin/keybindings.dm @@ -1,6 +1,6 @@ // Defines for managed input/keybinding system. /// Max length of a keypress command before it's considered to be a forged packet/bogus command -#define MAX_KEYPRESS_COMMANDLENGTH 32 +#define MAX_KEYPRESS_COMMANDLENGTH 64 /// Maximum keys that can be bound to one button #define MAX_COMMANDS_PER_KEY 5 /// Maximum keys per keybind diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 621af2c811..dad2a38afd 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -281,8 +281,6 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) #define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1 #endif -#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so") - GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_monstermos will be called twice because reasons #define ATMOS_EXTOOLS_CHECK if(!GLOB.atmos_extools_initialized){\ GLOB.atmos_extools_initialized=TRUE;\ diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 585e8da7d7..58125b5497 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -47,7 +47,7 @@ #define BALLS_SIZE_DEF 2 #define BALLS_SIZE_MAX 3 -#define CUM_RATE 2 // holy shit what a really shitty define name - relates to units per arbitrary measure of time? +#define CUM_RATE 2 // units per 10 seconds #define CUM_RATE_MULT 1 #define CUM_EFFICIENCY 1 //amount of nutrition required per life() @@ -58,7 +58,7 @@ #define DEF_BREASTS_SHAPE "Pair" -#define MILK_RATE 5 +#define MILK_RATE 3 #define MILK_RATE_MULT 1 #define MILK_EFFICIENCY 1 @@ -99,7 +99,8 @@ #define NO_ASS_SLAP (1<<10) #define BIMBOFICATION (1<<11) #define NO_AUTO_WAG (1<<12) - +#define GENITAL_EXAMINE (1<<13) +#define VORE_EXAMINE (1<<14) #define TOGGLES_CITADEL 0 //belly sound pref things diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 3d15412efe..2273d34c82 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -2,19 +2,6 @@ #define COLOR_INPUT_DISABLED "#F0F0F0" #define COLOR_INPUT_ENABLED "#D3B5B5" - -#define COLOR_DARKMODE_INFO_BUTTONS_BG "#40628A" -#define COLOR_DARKMODE_ISSUE_BUTTON_BG "#A92C2C" -#define COLOR_DARKMODE_BACKGROUND "#272727" -#define COLOR_DARKMODE_DARKBACKGROUND "#242424" -#define COLOR_DARKMODE_TEXT "#E0E0E0" - -#define COLOR_WHITEMODE_INFO_BUTTONS_BG "#90B3DD" -#define COLOR_WHITEMODE_ISSUE_BUTTON_BG "#EF7F7F" -#define COLOR_WHITEMODE_BACKGROUND "#F0F0F0" -#define COLOR_WHITEMODE_DARKBACKGROUND "#E6E6E6" -#define COLOR_WHITEMODE_TEXT "#000000" - #define COLOR_FLOORTILE_GRAY "#8D8B8B" #define COLOR_ALMOST_BLACK "#333333" #define COLOR_BLACK "#000000" @@ -64,4 +51,4 @@ #define COLOR_ASSEMBLY_LBLUE "#5D99BE" #define COLOR_ASSEMBLY_BLUE "#38559E" #define COLOR_ASSEMBLY_PURPLE "#6F6192" -#define COLOR_ASSEMBLY_PINK "#ff4adc" \ No newline at end of file +#define COLOR_ASSEMBLY_PINK "#ff4adc" diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index a4bf69b2ad..e9881677ba 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -1,6 +1,7 @@ //config files #define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X) #define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y) +/// Gets the datum of the object, for when editing a const define. #define CONFIG_GET_ENTRY(X) global.config.GetEntryDatum(/datum/config_entry/##X) #define CONFIG_MAPS_FILE "maps.txt" diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 65994dda5a..02e3fe6f3d 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -32,7 +32,7 @@ #define COMSIG_ELEMENT_DETACH "element_detach" /// sent to the component itself when unregistered from a parent -#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" +#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" /// sent to the component itself when registered to a parent #define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" @@ -43,6 +43,8 @@ // /atom signals //from base of atom/proc/Initialize(): sent any time a new atom is created #define COMSIG_ATOM_CREATED "atom_created" +//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization +#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success" #define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) #define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called #define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human) @@ -184,6 +186,7 @@ // #define HEARING_SOURCE 8 #define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) #define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination) +#define COMSIG_MOVABLE_CHASM_DROP "movable_chasm_drop" //from base of /datum/component/chasm/drop() (/datum/component/chasm) // /mind signals #define COMSIG_PRE_MIND_TRANSFER "pre_mind_transfer" //from base of mind/transfer_to() before it's done: (new_character, old_character) @@ -243,6 +246,8 @@ #define COMPONENT_BLOCK_SWAP 1 #define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge" +///from base of mob/AltClickOn(): (atom/A) +#define COMSIG_MOB_ALTCLICKON "mob_altclickon" // /client signals #define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) @@ -287,6 +292,10 @@ #define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes #define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling +#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (seconds, times_fired) + +#define COMSIG_LIVING_PHYSICAL_LIFE "physical_life" //from base of mob/living/PhysicalLife() (seconds, times_fired) + // /mob/living/carbon physiology signals #define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L) #define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L) diff --git a/code/__DEFINES/dye_keys.dm b/code/__DEFINES/dye_keys.dm index 133f9c47d3..a01dcacc18 100644 --- a/code/__DEFINES/dye_keys.dm +++ b/code/__DEFINES/dye_keys.dm @@ -4,6 +4,7 @@ #define DYE_REGISTRY_SNEAKERS "sneakers" #define DYE_REGISTRY_FANNYPACK "fannypack" #define DYE_REGISTRY_BEDSHEET "bedsheet" +#define DYE_LAWYER_SPECIAL "lawyer_special" #define DYE_RED "red" #define DYE_ORANGE "orange" @@ -16,6 +17,7 @@ #define DYE_RAINBOW "rainbow" #define DYE_MIME "mime" #define DYE_COSMIC "cosmic" +#define DYE_SYNDICATE "syndicate" #define DYE_QM "qm" #define DYE_LAW "law" #define DYE_CAPTAIN "captain" @@ -26,3 +28,5 @@ #define DYE_CMO "cmo" #define DYE_REDCOAT "redcoat" #define DYE_CLOWN "clown" +#define DYE_CHAP "chap" +#define DYE_CENTCOM "centcom" diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index 77e8d82aca..03110ad04e 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -12,6 +12,7 @@ #define TOXIC (1<<11) #define PINEAPPLE (1<<12) #define BREAKFAST (1<<13) +#define ANTITOXIC (1<<14) #define DRINK_NICE 1 #define DRINK_GOOD 2 diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 94059c0880..767894050d 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -54,3 +54,16 @@ //donator items #define LOADOUT_CATEGORY_DONATOR "Donator" + +//how many prosthetics can we have +#define MAXIMUM_LOADOUT_PROSTHETICS 2 + +//what limbs can be amputated or be prosthetic +#define LOADOUT_ALLOWED_LIMB_TARGETS list(BODY_ZONE_L_ARM,BODY_ZONE_R_ARM,BODY_ZONE_L_LEG,BODY_ZONE_R_LEG) + +//options for modifiying limbs +#define LOADOUT_LIMB_NORMAL "Normal" +#define LOADOUT_LIMB_PROSTHETIC "Prosthetic" +#define LOADOUT_LIMB_AMPUTATED "Amputated" + +#define LOADOUT_LIMBS list(LOADOUT_LIMB_NORMAL,LOADOUT_LIMB_PROSTHETIC,LOADOUT_LIMB_AMPUTATED) //you can amputate your legs/arms though \ No newline at end of file diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 0e8e34d20e..df5b7d9f11 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -41,11 +41,13 @@ #define MC_HDD "HDD" #define MC_SDD "SDD" #define MC_CARD "CARD" +#define MC_CARD2 "CARD2" #define MC_NET "NET" #define MC_PRINT "PRINT" #define MC_CELL "CELL" #define MC_CHARGE "CHARGE" #define MC_AI "AI" +#define MC_SENSORS "SENSORS" //NTNet stuff, for modular computers // NTNet module-configuration values. Do not change these. If you need to add another use larger number (5..6..7 etc) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 927b661898..0704947dda 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -116,6 +116,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define CRAYON_FONT "Comic Sans MS" #define PRINTER_FONT "Times New Roman" #define SIGNFONT "Times New Roman" +#define CHARCOAL_FONT "Candara" #define RESIZE_DEFAULT_SIZE 1 @@ -318,9 +319,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" //debug printing macros -#define debug_world(msg) if (GLOB.Debug2) to_chat(world, "DEBUG: [msg]") -#define debug_usr(msg) if (GLOB.Debug2&&usr) to_chat(usr, "DEBUG: [msg]") -#define debug_admins(msg) if (GLOB.Debug2) to_chat(GLOB.admins, "DEBUG: [msg]") +#define debug_world(msg) if (GLOB.Debug2) to_chat(world, "DEBUG: [msg]") +#define debug_usr(msg) if (GLOB.Debug2&&usr) to_chat(usr, "DEBUG: [msg]") +#define debug_admins(msg) if (GLOB.Debug2) to_chat(GLOB.admins, "DEBUG: [msg]") #define debug_world_log(msg) if (GLOB.Debug2) log_world("DEBUG: [msg]") #define INCREMENT_TALLY(L, stat) if(L[stat]){L[stat]++}else{L[stat] = 1} diff --git a/code/__DEFINES/procpath.dm b/code/__DEFINES/procpath.dm index 1180058358..642ca3eab6 100644 --- a/code/__DEFINES/procpath.dm +++ b/code/__DEFINES/procpath.dm @@ -22,3 +22,5 @@ var/category as text /// Only clients/mobs with `see_invisibility` higher can use the verb. var/invisibility as num + /// Whether or not the verb appears in statpanel and commandbar when you press space + var/hidden as num diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm new file mode 100644 index 0000000000..35d99a982d --- /dev/null +++ b/code/__DEFINES/research/anomalies.dm @@ -0,0 +1,21 @@ +// Anomaly core types +/// Bluespace cores +#define ANOMALY_CORE_BLUESPACE /obj/item/assembly/signaler/anomaly/bluespace +/// Gravitational cores +#define ANOMALY_CORE_GRAVITATIONAL /obj/item/assembly/signaler/anomaly/grav +/// Flux +#define ANOMALY_CORE_FLUX /obj/item/assembly/signaler/anomaly/flux +/// Vortex +#define ANOMALY_CORE_VORTEX /obj/item/assembly/signaler/anomaly/vortex +/// Pyro +#define ANOMALY_CORE_PYRO /obj/item/assembly/signaler/anomaly/pyro + +// Max amounts of cores you can make +#define MAX_CORES_BLUESPACE 8 +#define MAX_CORES_GRAVITATIONAL 8 +#define MAX_CORES_FLUX 8 +#define MAX_CORES_VORTEX 8 +#define MAX_CORES_PYRO 8 + +/// chance supermatter anomalies drop real cores +#define SUPERMATTER_ANOMALY_DROP_CHANCE 20 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index bfff1dc629..d6db35e68d 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -30,6 +30,8 @@ #define STATUS_EFFECT_FLESHMEND /datum/status_effect/fleshmend //Very fast healing; suppressed by fire, and heals less fire damage +#define STATUS_EFFECT_PANACEA /datum/status_effect/panacea //Anatomic panacea that directly heals, rather than injecting a small chemical cocktail + #define STATUS_EFFECT_EXERCISED /datum/status_effect/exercised //Prevents heart disease #define STATUS_EFFECT_HIPPOCRATIC_OATH /datum/status_effect/hippocraticOath //Gives you an aura of healing as well as regrowing the Rod of Asclepius if lost diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 81b5c5620f..9deddd4b46 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -51,7 +51,8 @@ #define INIT_ORDER_FAIL2TOPIC 99 #define INIT_ORDER_TITLE 98 #define INIT_ORDER_GARBAGE 95 -#define INIT_ORDER_DBCORE 93 +#define INIT_ORDER_DBCORE 94 +#define INIT_ORDER_STATPANELS 93 #define INIT_ORDER_BLACKBOX 92 #define INIT_ORDER_SERVER_MAINT 91 #define INIT_ORDER_INPUT 90 @@ -86,6 +87,7 @@ #define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_PATH -50 #define INIT_ORDER_PERSISTENCE -95 +#define INIT_ORDER_DEMO -99 // o avoid a bunch of changes related to initialization being written, do this last #define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init. @@ -93,7 +95,6 @@ // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) #define FIRE_PRIORITY_VORE 5 -#define FIRE_PRIORITY_PING 10 #define FIRE_PRIORITY_IDLE_NPC 10 #define FIRE_PRIORITY_SERVER_MAINT 10 #define FIRE_PRIORITY_RESEARCH 10 @@ -121,6 +122,7 @@ #define FIRE_PRIORITY_PROJECTILES 200 #define FIRE_PRIORITY_TICKER 200 #define FIRE_PRIORITY_ATMOS_ADJACENCY 300 +#define FIRE_PRIORITY_STATPANEL 390 #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. diff --git a/code/__DEFINES/tgui.dm b/code/__DEFINES/tgui.dm index f5adeadade..467058f27a 100644 --- a/code/__DEFINES/tgui.dm +++ b/code/__DEFINES/tgui.dm @@ -26,3 +26,10 @@ #define TGUI_WINDOW_ID(index) "tgui-window-[index]" /// Get a pool index of the provided window id #define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13)) + +/// Creates a message packet for sending via output() +#define TGUI_CREATE_MESSAGE(type, payload) ( \ + url_encode(json_encode(list( \ + "type" = type, \ + "payload" = payload, \ + )))) \ No newline at end of file diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 5e57dd5328..a5ffda36f9 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -17,7 +17,7 @@ var/matrix/mtrx=new() return mtrx.Scale(0.65) -proc/get_racelist(var/mob/user)//This proc returns a list of species that 'user' has available to them. It searches the list of ckeys attached to the 'whitelist' var for a species and also checks if they're an admin. +/proc/get_racelist(mob/user)//This proc returns a list of species that 'user' has available to them. It searches the list of ckeys attached to the 'whitelist' var for a species and also checks if they're an admin. for(var/spath in subtypesof(/datum/species)) var/datum/species/S = new spath() var/list/wlist = S.whitelist diff --git a/code/__HELPERS/_extools_api.dm b/code/__HELPERS/_extools_api.dm new file mode 100644 index 0000000000..af348dc939 --- /dev/null +++ b/code/__HELPERS/_extools_api.dm @@ -0,0 +1,5 @@ +#define EXTOOLS_LOGGING // rust_g is used as a fallback if this is undefined + +/proc/extools_log_write() + +/proc/extools_finalize_logging() diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 719735392d..3efb50ef65 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -553,12 +553,6 @@ if(D.vars[varname] == value) return D -//remove all nulls from a list -/proc/removeNullsFromList(list/L) - while(L.Remove(null)) - continue - return L - //Copies a list, and all lists inside it recusively //Does not copy any other reference type /proc/deepCopyList(list/l) @@ -681,3 +675,11 @@ continue if(istype(D, path)) return TRUE + +/proc/safe_json_encode(list/L, default = "") + . = default + return json_encode(L) + +/proc/safe_json_decode(string, default = list()) + . = default + return json_decode(string) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 62e6c4daf9..583427cab7 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -4,10 +4,15 @@ #define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound) #define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text) #define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text) +#ifdef EXTOOLS_LOGGING +// proc hooked, so we can just put in standard TRUE and FALSE +#define WRITE_LOG(log, text) extools_log_write(log,text,TRUE) +#define WRITE_LOG_NO_FORMAT(log, text) extools_log_write(log,text,FALSE) +#else //This is an external call, "true" and "false" are how rust parses out booleans #define WRITE_LOG(log, text) rustg_log_write(log, text, "true") #define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false") - +#endif //print a warning message to world.log #define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].") /proc/warning(msg) @@ -200,23 +205,45 @@ /proc/start_log(log) WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") -/* ui logging */ -/proc/log_tgui(user_or_client, text) +/** + * Appends a tgui-related log entry. All arguments are optional. + */ +/proc/log_tgui(user, message, context, + datum/tgui_window/window, + datum/src_object) var/entry = "" - if(!user_or_client) - entry += "no user" - else if(istype(user_or_client, /mob)) - var/mob/user = user_or_client - entry += "[user.ckey] (as [user])" - else if(istype(user_or_client, /client)) - var/client/client = user_or_client + // Insert user info + if(!user) + entry += "" + else if(istype(user, /mob)) + var/mob/mob = user + entry += "[mob.ckey] (as [mob] at [mob.x],[mob.y],[mob.z])" + else if(istype(user, /client)) + var/client/client = user entry += "[client.ckey]" - entry += ":\n[text]" + // Insert context + if(context) + entry += " in [context]" + else if(window) + entry += " in [window.id]" + // Resolve src_object + if(!src_object && window && window.locked_by) + src_object = window.locked_by.src_object + // Insert src_object info + if(src_object) + entry += "\nUsing: [src_object.type] [REF(src_object)]" + // Insert message + if(message) + entry += "\n[message]" WRITE_LOG(GLOB.tgui_log, entry) /* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ /proc/shutdown_logging() +#ifdef EXTOOLS_LOGGING + extools_finalize_logging() +#else rustg_log_close_all() +#endif /* Helper procs for building detailed log lines */ diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index 8b4f8d5b54..aad5b4cab1 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -71,3 +71,18 @@ /proc/pathflatten(path) return replacetext(path, "/", "_") + +/// Returns the md5 of a file at a given path. +/proc/md5filepath(path) + . = md5(file(path)) + +/// Save file as an external file then md5 it. +/// Used because md5ing files stored in the rsc sometimes gives incorrect md5 results. +/proc/md5asfile(file) + var/static/notch = 0 + // its importaint this code can handle md5filepath sleeping instead of hard blocking, if it's converted to use rust_g. + var/filename = "tmp/md5asfile.[world.realtime].[world.timeofday].[world.time].[world.tick_usage].[notch]" + notch = WRAP(notch+1, 0, 2^15) + fcopy(file, filename) + . = md5filepath(filename) + fdel(filename) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 3155fe2548..4723577fad 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1103,24 +1103,36 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 alpha += 25 obj_flags &= ~FROZEN +/// Save file used in icon2base64. Used for converting icons to base64. +GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of icons for the browser output -//Converts an icon to base64. Operates by putting the icon in the iconCache savefile, -// exporting it as text, and then parsing the base64 from that. -// (This relies on byond automatically storing icons in savefiles as base64) -/proc/icon2base64(icon/icon, iconKey = "misc") + +/// Generate a filename for this asset +/// The same asset will always lead to the same asset name +/// (Generated names do not include file extention.) +/proc/generate_asset_name(file) + return "asset.[md5(fcopy_rsc(file))]" + +/** + * Converts an icon to base64. Operates by putting the icon in the iconCache savefile, + * exporting it as text, and then parsing the base64 from that. + * (This relies on byond automatically storing icons in savefiles as base64) + */ +/proc/icon2base64(icon/icon) if (!isicon(icon)) return FALSE - WRITE_FILE(GLOB.iconCache[iconKey], icon) - var/iconData = GLOB.iconCache.ExportText(iconKey) + WRITE_FILE(GLOB.dummySave["dummy"], icon) + var/iconData = GLOB.dummySave.ExportText("dummy") var/list/partial = splittext(iconData, "{") return replacetext(copytext_char(partial[2], 3, -5), "\n", "") -/proc/icon2html(thing, target, icon_state, dir, frame = 1, moving = FALSE) +/proc/icon2html(thing, target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE) if (!thing) return var/key var/icon/I = thing + if (!target) return if (target == world) @@ -1136,17 +1148,26 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 if (!isicon(I)) if (isfile(thing)) //special snowflake var/name = sanitize_filename("[generate_asset_name(thing)].png") - if(!SSassets.cache[name]) - register_asset(name, thing) + if (!SSassets.cache[name]) + SSassets.transport.register_asset(name, thing) for (var/thing2 in targets) - send_asset(thing2, key) - return "" + SSassets.transport.send_assets(thing2, name) + if(sourceonly) + return SSassets.transport.get_asset_url(name) + return "" var/atom/A = thing - if (isnull(dir)) - dir = A.dir + + I = A.icon if (isnull(icon_state)) icon_state = A.icon_state - I = A.icon + if (!(icon_state in icon_states(I, 1))) + icon_state = initial(A.icon_state) + if (isnull(dir)) + dir = initial(A.dir) + + if (isnull(dir)) + dir = A.dir + if (ishuman(thing)) // Shitty workaround for a BYOND issue. var/icon/temp = I I = icon() @@ -1162,11 +1183,11 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 key = "[generate_asset_name(I)].png" if(!SSassets.cache[key]) - register_asset(key, I) + SSassets.transport.register_asset(key, I) for (var/thing2 in targets) - send_asset(thing2, key) + SSassets.transport.send_assets(thing2, key) - return "" + return "" /proc/icon2base64html(thing) if (!thing) @@ -1202,7 +1223,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 return "" //Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs. -/proc/costly_icon2html(thing, target) +/proc/costly_icon2html(thing, target, sourceonly = FALSE) if (!thing) return @@ -1210,4 +1231,5 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 return icon2html(thing, target) var/icon/I = getFlatIcon(thing) - return icon2html(I, target) + return icon2html(I, target, sourceonly = sourceonly) + diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 045ca2c519..e4a2e6521a 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -349,7 +349,7 @@ if(!previous) var/list/report_parts = list(personal_report(C), GLOB.common_report) content = report_parts.Join() - C.verbs -= /client/proc/show_previous_roundend_report + remove_verb(C, /client/proc/show_previous_roundend_report) fdel(filename) text2file(content, filename) else @@ -358,7 +358,7 @@ roundend_report.stylesheets = list() roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css') roundend_report.add_stylesheet("font-awesome", 'html/font-awesome/css/all.min.css') - roundend_report.open(0) + roundend_report.open(FALSE) /datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount) var/list/parts = list() @@ -402,7 +402,7 @@ for (var/i in GLOB.ai_list) var/mob/living/silicon/ai/aiPlayer = i if(aiPlayer.mind) - parts += "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:" + parts += "[aiPlayer.name][aiPlayer.mind.hide_ckey ? "" : " (Played by: [aiPlayer.mind.key])"]'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:" parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE) parts += "Total law changes: [aiPlayer.law_change_counter]" @@ -413,14 +413,14 @@ for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) borg_num-- if(robo.mind) - robolist += "[robo.name] (Played by: [robo.mind.key])[robo.stat == DEAD ? " (Deactivated)" : ""][borg_num ?", ":""]
" + robolist += "[robo.name][robo.mind.hide_ckey ? "" : " (Played by: [robo.mind.key])"] [robo.stat == DEAD ? " (Deactivated)" : ""][borg_num ?", ":""]
" parts += "[robolist]" if(!borg_spacer) borg_spacer = TRUE for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs) if (!robo.connected_ai && robo.mind) - parts += "[borg_spacer?"
":""][robo.name] (Played by: [robo.mind.key]) [(robo.stat != DEAD)? "survived as an AI-less borg!" : "was unable to survive the rigors of being a cyborg without an AI."] Its laws were:" + parts += "[borg_spacer?"
":""][robo.name][robo.mind.hide_ckey ? "" : " (Played by: [robo.mind.key])"] [(robo.stat != DEAD)? "survived as an AI-less borg!" : "was unable to survive the rigors of being a cyborg without an AI."] Its laws were:" if(robo) //How the hell do we lose robo between here and the world messages directly above this? parts += robo.laws.get_law_list(include_zeroth=TRUE) @@ -529,7 +529,7 @@ var/jobtext = "" if(ply.assigned_role) jobtext = " the [ply.assigned_role]" - var/text = "[ply.key] was [ply.name][jobtext] and" + var/text = "[ply.hide_ckey ? "[ply.name][jobtext] " : "[ply.key] was [ply.name][jobtext] and "]" if(ply.current) if(ply.current.stat == DEAD) text += " died" diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 7a18d2ce01..bbbf99c9de 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -462,16 +462,14 @@ else . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) -/proc/fusionpower2text(power) //used when displaying fusion power on analyzers - switch(power) - if(0 to 5) - return "low" - if(5 to 20) - return "mid" - if(20 to 50) - return "high" - if(50 to INFINITY) - return "super" +/proc/instability2text(instability) //used when displaying fusion power on analyzers + switch(instability) + if(0 to 2) + return "stable, meaning that its heat will always increase." + if(2 to 3) + return "metastable, meaning that its heat will trend upwards." + if (3 to INFINITY) + return "unstable, meaning that its heat will trend downwards." /proc/color2hex(color) //web colors if(!color) @@ -620,6 +618,12 @@ else //regex everything else (works for /proc too) return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", "")) + +/// Return html to load a url. +/// for use inside of browse() calls to html assets that might be loaded on a cdn. +/proc/url2htmlloader(url) + return {""} + /proc/strtohex(str) if(!istext(str)||!str) return diff --git a/code/__HELPERS/verbs.dm b/code/__HELPERS/verbs.dm new file mode 100644 index 0000000000..3606c7d918 --- /dev/null +++ b/code/__HELPERS/verbs.dm @@ -0,0 +1,96 @@ +/** + * handles adding verbs and updating the stat panel browser + * + * pass the verb type path to this instead of adding it directly to verbs so the statpanel can update + * Arguments: + * * target - Who the verb is being added to, client or mob typepath + * * verb - typepath to a verb, or a list of verbs, supports lists of lists + */ +/proc/add_verb(client/target, verb_or_list_to_add) + if(!target) + CRASH("add_verb called without a target") + if(IsAdminAdvancedProcCall()) + return + var/mob/mob_target = null + + if(ismob(target)) + mob_target = target + target = mob_target.client + else if(!istype(target, /client)) + CRASH("add_verb called on a non-mob and non-client") + var/list/verbs_list = list() + if(!islist(verb_or_list_to_add)) + verbs_list += verb_or_list_to_add + else + var/list/verb_listref = verb_or_list_to_add + var/list/elements_to_process = verb_listref.Copy() + while(length(elements_to_process)) + var/element_or_list = elements_to_process[length(elements_to_process)] //Last element + elements_to_process.len-- + if(islist(element_or_list)) + elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself + else + verbs_list += element_or_list + + if(mob_target) + mob_target.verbs += verbs_list + if(!target) + return //Our work is done. + else + target.verbs += verbs_list + + var/list/output_list = list() + for(var/thing in verbs_list) + var/procpath/verb_to_add = thing + output_list[++output_list.len] = list(verb_to_add.category, verb_to_add.name) + output_list = url_encode(json_encode(output_list)) + + target << output("[output_list];", "statbrowser:add_verb_list") + +/** + * handles removing verb and sending it to browser to update, use this for removing verbs + * + * pass the verb type path to this instead of removing it from verbs so the statpanel can update + * Arguments: + * * target - Who the verb is being removed from, client or mob typepath + * * verb - typepath to a verb, or a list of verbs, supports lists of lists + */ +/proc/remove_verb(client/target, verb_or_list_to_remove) + if(IsAdminAdvancedProcCall()) + return + + var/mob/mob_target = null + if(ismob(target)) + mob_target = target + target = mob_target.client + else if(!istype(target, /client)) + CRASH("remove_verb called on a non-mob and non-client") + + var/list/verbs_list = list() + if(!islist(verb_or_list_to_remove)) + verbs_list += verb_or_list_to_remove + else + var/list/verb_listref = verb_or_list_to_remove + var/list/elements_to_process = verb_listref.Copy() + while(length(elements_to_process)) + var/element_or_list = elements_to_process[length(elements_to_process)] //Last element + elements_to_process.len-- + if(islist(element_or_list)) + elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself + else + verbs_list += element_or_list + + if(mob_target) + mob_target.verbs -= verbs_list + if(!target) + return //Our work is done. + else + target.verbs -= verbs_list + + var/list/output_list = list() + for(var/thing in verbs_list) + var/procpath/verb_to_remove = thing + output_list[++output_list.len] = list(verb_to_remove.category, verb_to_remove.name) + output_list = url_encode(json_encode(output_list)) + + target << output("[output_list];", "statbrowser:remove_verb_list") diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 71c2b2e13b..e8726f8316 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -267,7 +267,7 @@ GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARC GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) -GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "declares", "bellows", "buzzes" ,"beeps", "chirps" ,"hisses" ,"poofs" ,"rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters")) +GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps" ,"hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles")) GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc)) @@ -279,7 +279,8 @@ GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff")) //parts in either of the above two lists that require a second option that allows them to be coloured GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color")) -//species ids that have greyscale sprites +//body ids that have greyscale sprites GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","lum","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic")) -//species ids that need snowflake coloring applied +//body ids that have prosthetic sprites +GLOBAL_LIST_INIT(prosthetic_limb_types, list("xion","bishop","cybersolutions","grayson","hephaestus","nanotrasen","talon")) diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index 865f405442..14a1924e76 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -107,13 +107,8 @@ GLOBAL_LIST_INIT(maintenance_loot, list( /obj/item/toy/eightball = 1, /obj/item/reagent_containers/pill/floorpill = 1, /obj/item/reagent_containers/food/snacks/cannedpeaches/maint = 2, - /obj/item/storage/daki = 3, //VERY IMPORTANT CIT CHANGE - adds bodypillows to maint - /obj/item/storage/pill_bottle/penis_enlargement = 2, - /obj/item/storage/pill_bottle/breast_enlargement = 2, /obj/item/clothing/shoes/wheelys = 1, /obj/item/clothing/shoes/kindleKicks = 1, - /obj/item/autosurgeon/penis = 1, - /obj/item/autosurgeon/testicles = 1, /obj/item/storage/box/marshmallow = 2, /obj/item/clothing/gloves/tackler/offbrand = 1, /obj/item/stack/sticky_tape = 1, diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index fee70ee3d5..706a5ed955 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -13,6 +13,7 @@ GLOBAL_LIST_EMPTY(deliverybeacontags) //list of all tags associated with d GLOBAL_LIST_EMPTY(nuke_list) GLOBAL_LIST_EMPTY(alarmdisplay) //list of all machines or programs that can display station alerts GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the station (actually technically all engines) +GLOBAL_LIST_EMPTY(grounding_rods) //list of all grounding rods on the station GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datums. Used during chemical reactions GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 18aaf66659..59b78577af 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -112,8 +112,8 @@ /mob/living/silicon/ai/CtrlClickOn(var/atom/A) A.AICtrlClick(src) /mob/living/silicon/ai/AltClickOn(var/atom/A) - if(!A.AIAltClick(src)) - altclick_listed_turf(A) + A.AIAltClick(src) + /* The following criminally helpful code is just the previous code cleaned up; diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 042ab3aaee..2e52fa5bd7 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -319,20 +319,13 @@ return ..() /* Alt click - Unused except for AI + Used as an alternate way to interact with things. */ /mob/proc/AltClickOn(atom/A) - if(!A.AltClick(src)) - altclick_listed_turf(A) - -/mob/proc/altclick_listed_turf(atom/A) - var/turf/T = get_turf(A) - if(T == A.loc || T == A) - if(T == listed_turf) - listed_turf = null - else if(TurfAdjacent(T)) - listed_turf = T - client.statpanel = T.name + . = SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, A) + if(. & COMSIG_MOB_CANCEL_CLICKON) + return + A.AltClick(src) /mob/living/carbon/AltClickOn(atom/A) if(!stat && mind && iscarbon(A) && A != src) @@ -344,7 +337,18 @@ ..() /atom/proc/AltClick(mob/user) - . = SEND_SIGNAL(src, COMSIG_CLICK_ALT, user) + SEND_SIGNAL(src, COMSIG_CLICK_ALT, user) + var/turf/T = get_turf(src) + if(T && (isturf(loc) || isturf(src)) && user.TurfAdjacent(T)) + user.listed_turf = T + user.client << output("[url_encode(json_encode(T.name))];", "statbrowser:create_listedturf") + +/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction +/atom/proc/AltClickNoInteract(mob/user, atom/A) + var/turf/T = get_turf(A) + if(T && user.TurfAdjacent(T)) + user.listed_turf = T + user.client << output("[url_encode(json_encode(T.name))];", "statbrowser:create_listedturf") /mob/proc/TurfAdjacent(turf/T) return T.Adjacent(src) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 372fe46046..afc01a6ec0 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -98,8 +98,7 @@ /mob/living/silicon/robot/CtrlClickOn(atom/A) A.BorgCtrlClick(src) /mob/living/silicon/robot/AltClickOn(atom/A) - if(!A.BorgAltClick(src)) - altclick_listed_turf(A) + A.BorgAltClick(src) /atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden CtrlShiftClick(user) diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 6dc1433bc8..980ec38909 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -184,14 +184,23 @@ /obj/screen/alert/hot name = "Too Hot" - desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit." + desc = "The air around you is pretty toasty! Consider putting on some insulating clothing, or moving to a cooler area." icon_state = "hot" /obj/screen/alert/cold name = "Too Cold" - desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit." + desc = "The air around you is pretty cold! Consider wearing a coat, or moving to a warmer area." icon_state = "cold" +/obj/screen/alert/sweat + name = "Sweating" + desc = "You're sweating! Get somewhere cooler and take off any insulating clothing like a fire suit." + icon_state = "sweat" + +/obj/screen/alert/shiver + name = "Shivering" + desc = "You're shivering! Get somewhere warmer and take off any insulating clothing like a space suit." + /obj/screen/alert/lowpressure name = "Low Pressure" desc = "The air around you is hazardously thin. A space suit would protect you." diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm index 2cd0ddedaa..31ea453d4a 100644 --- a/code/_onclick/hud/credits.dm +++ b/code/_onclick/hud/credits.dm @@ -11,7 +11,7 @@ var/icon/credits_icon = new(CREDITS_PATH) LAZYINITLIST(credits) var/list/_credits = credits - verbs += /client/proc/ClearCredits + add_verb(src, /client/proc/ClearCredits) var/static/list/credit_order_for_this_round if(isnull(credit_order_for_this_round)) credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!") @@ -21,13 +21,13 @@ _credits += new /obj/screen/credit(null, I, src, credits_icon) sleep(CREDIT_SPAWN_SPEED) sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) - verbs -= /client/proc/ClearCredits + remove_verb(src, /client/proc/ClearCredits) qdel(credits_icon) /client/proc/ClearCredits() set name = "Hide Credits" set category = "OOC" - verbs -= /client/proc/ClearCredits + remove_verb(src, /client/proc/ClearCredits) QDEL_LIST(credits) credits = null diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 8a1e745308..d431e6d3cd 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -31,7 +31,7 @@ ShiftClickOn(A) return if(modifiers["alt"]) - altclick_listed_turf(A) + AltClickNoInteract(src, A) return if(modifiers["ctrl"]) CtrlClickOn(A) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 1c6e96f9e4..3ea4d0a870 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -14,13 +14,15 @@ var/list/modes // allowed modes var/list/gamemode_cache var/list/votable_modes // votable modes - // var/list/ic_filter_regex var/list/storyteller_cache var/list/mode_names var/list/mode_reports var/list/mode_false_report_weight var/motd + // var/policy + + // var/static/regex/ic_filter_regex /datum/controller/configuration/proc/admin_reload() if(IsAdminAdvancedProcCall()) @@ -50,6 +52,11 @@ break loadmaplist(CONFIG_MAPS_FILE) LoadMOTD() + // LoadPolicy() + // LoadChatFilter() + + if (Master) + Master.OnConfigLoad() /datum/controller/configuration/proc/full_wipe() if(IsAdminAdvancedProcCall()) @@ -135,7 +142,7 @@ if(entry == "$include") if(!value) - log_config("LINE [linenumber]: Invalid $include directive: [value]") + log_config("LINE [linenumber]: Warning: Invalid $include directive: [value]") else LoadEntries(value, stack) ++. @@ -143,7 +150,7 @@ var/datum/config_entry/E = _entries[entry] if(!E) - log_config("LINE [linenumber]: Unknown setting: '[entry]'") + log_config("LINE [linenumber]: Unknown setting in configuration: '[entry]'") continue if(lockthis) @@ -153,9 +160,9 @@ var/datum/config_entry/new_ver = entries_by_type[E.deprecated_by] var/new_value = E.DeprecationUpdate(value) var/good_update = istext(new_value) - log_config("LINE [linenumber]: [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]") + log_config("LINE [linenumber]: Entry [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]") if(!warned_deprecated_configs) - addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, "This server is using deprecated configuration settings. Please check the logs and update accordingly."), 0) + DelayedMessageAdmins("This server is using deprecated configuration settings. Please check the logs and update accordingly.") warned_deprecated_configs = TRUE if(good_update) value = new_value @@ -163,7 +170,7 @@ else warning("[new_ver.type] is deprecated but gave no proper return for DeprecationUpdate()") - var/validated = E.ValidateAndSet(value, TRUE) + var/validated = E.ValidateAndSet(value) if(!validated) log_config("LINE [linenumber]: Failed to validate setting \"[value]\" for [entry]") else @@ -190,18 +197,11 @@ var/list/banned_edits = list(NAMEOF(src, entries_by_type), NAMEOF(src, entries), NAMEOF(src, directory)) return !(var_name in banned_edits) && ..() -/datum/controller/configuration/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Edit", src) - stat("[name]:", statclick) - -/datum/controller/configuration/proc/Get(entry_type) - var/datum/config_entry/E = GetEntryDatum(entry_type) - if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") - log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]") - return - return E.config_entry_value +/datum/controller/configuration/stat_entry(msg) + msg = "Edit" + return msg +/// Your typical GET but returns a config. /datum/controller/configuration/proc/GetEntryDatum(entry_type) var/datum/config_entry/E = entry_type var/entry_is_abstract = initial(E.abstract_type) == entry_type @@ -210,8 +210,24 @@ E = entries_by_type[entry_type] if(!E) CRASH("Missing config entry for [entry_type]!") + if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") + log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]") + return return E +/datum/controller/configuration/proc/Get(entry_type) + var/datum/config_entry/E = entry_type + var/entry_is_abstract = initial(E.abstract_type) == entry_type + if(entry_is_abstract) + CRASH("Tried to retrieve an abstract config_entry: [entry_type]") + E = entries_by_type[entry_type] + if(!E) + CRASH("Missing config entry for [entry_type]!") + if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") + log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]") + return + return E.config_entry_value + /datum/controller/configuration/proc/Set(entry_type, new_val) var/datum/config_entry/E = entry_type var/entry_is_abstract = initial(E.abstract_type) == entry_type @@ -236,7 +252,6 @@ for(var/T in gamemode_cache) // I wish I didn't have to instance the game modes in order to look up // their information, but it is the only way (at least that I know of). - // for future reference: just use initial() lol var/datum/game_mode/M = new T() if(M.config_tag) @@ -258,7 +273,37 @@ var/tm_info = GLOB.revdata.GetTestMergeInfo() if(motd || tm_info) motd = motd ? "[motd]
[tm_info]" : tm_info +/* +Policy file should be a json file with a single object. +Value is raw html. +Possible keywords : +Job titles / Assigned roles (ghost spawners for example) : Assistant , Captain , Ash Walker +Mob types : /mob/living/simple_animal/hostile/carp +Antagonist types : /datum/antagonist/highlander +Species types : /datum/species/lizard +special keywords defined in _DEFINES/admin.dm + +Example config: +{ + "Assistant" : "Don't kill everyone", + "/datum/antagonist/highlander" : "Kill everyone", + "Ash Walker" : "Kill all spacemans" +} + +*/ +/* +/datum/controller/configuration/proc/LoadPolicy() + policy = list() + var/rawpolicy = file2text("[directory]/policy.json") + if(rawpolicy) + var/parsed = safe_json_decode(rawpolicy) + if(!parsed) + log_config("JSON parsing failure for policy.json") + DelayedMessageAdmins("JSON parsing failure for policy.json") + else + policy = parsed +*/ /datum/controller/configuration/proc/loadmaplist(filename) log_config("Loading config file [filename]...") filename = "[directory]/[filename]" @@ -305,6 +350,8 @@ currentmap.voteweight = text2num(data) if ("default","defaultmap") defaultmap = currentmap + //if ("votable") + // currentmap.votable = TRUE if ("endmap") LAZYINITLIST(maplist) maplist[currentmap.map_name] = currentmap @@ -326,6 +373,7 @@ return new T return new /datum/game_mode/extended() +/// For dynamic. /datum/controller/configuration/proc/pick_storyteller(storyteller_name) for(var/T in storyteller_cache) var/datum/dynamic_storyteller/S = T @@ -334,6 +382,32 @@ return T return /datum/dynamic_storyteller/classic +/// Same with this +/datum/controller/configuration/proc/get_runnable_storytellers() + var/list/datum/dynamic_storyteller/runnable_storytellers = new + var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight) + var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust) + var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players) + for(var/T in storyteller_cache) + var/datum/dynamic_storyteller/S = T + var/config_tag = initial(S.config_tag) + var/probability = (config_tag in probabilities) ? probabilities[config_tag] : initial(S.weight) + var/min_players = (config_tag in min_player_counts) ? min_player_counts[config_tag] : initial(S.min_players) + if(probability <= 0) + continue + if(length(GLOB.player_list) < min_players) + continue + if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len) + var/name = initial(S.name) + var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3) + var/adjustment = 0 + while(recent_round) + adjustment += repeated_mode_adjust[recent_round] + recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0) + probability *= ((100-adjustment)/100) + runnable_storytellers[S] = probability + return runnable_storytellers + /datum/controller/configuration/proc/get_runnable_modes() var/list/datum/game_mode/runnable_modes = new var/list/probabilities = Get(/datum/config_entry/keyed_list/probability) @@ -367,32 +441,6 @@ runnable_modes[M] = final_weight return runnable_modes -/datum/controller/configuration/proc/get_runnable_storytellers() - var/list/datum/dynamic_storyteller/runnable_storytellers = new - var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight) - var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust) - var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players) - for(var/T in storyteller_cache) - var/datum/dynamic_storyteller/S = T - var/config_tag = initial(S.config_tag) - var/probability = (config_tag in probabilities) ? probabilities[config_tag] : initial(S.weight) - var/min_players = (config_tag in min_player_counts) ? min_player_counts[config_tag] : initial(S.min_players) - if(probability <= 0) - continue - if(length(GLOB.player_list) < min_players) - continue - if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len) - var/name = initial(S.name) - var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3) - var/adjustment = 0 - while(recent_round) - adjustment += repeated_mode_adjust[recent_round] - recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0) - probability *= ((100-adjustment)/100) - runnable_storytellers[S] = probability - return runnable_storytellers - - /datum/controller/configuration/proc/get_runnable_midround_modes(crew) var/list/datum/game_mode/runnable_modes = new var/list/probabilities = Get(/datum/config_entry/keyed_list/probability) @@ -418,7 +466,6 @@ /* /datum/controller/configuration/proc/LoadChatFilter() var/list/in_character_filter = list() - if(!fexists("[directory]/in_character_filter.txt")) return log_config("Loading config file in_character_filter.txt...") @@ -428,8 +475,8 @@ if(findtextEx(line,"#",1,2)) continue in_character_filter += REGEX_QUOTE(line) - ic_filter_regex = in_character_filter.len ? regex("\\b([jointext(in_character_filter, "|")])\\b", "i") : null - - syncChatRegexes() */ +//Message admins when you can. +/datum/controller/configuration/proc/DelayedMessageAdmins(text) + addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, text), 0) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 2d5e69f149..273ac7fd3e 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -368,6 +368,10 @@ /datum/config_entry/flag/allow_map_voting +/datum/config_entry/number/client_warn_version + config_entry_value = null + min_val = 500 + /datum/config_entry/number/client_warn_version config_entry_value = null min_val = 500 @@ -384,6 +388,10 @@ /datum/config_entry/string/client_error_message config_entry_value = "Your version of byond is too old, may have issues, and is blocked from accessing this server." +/datum/config_entry/number/client_error_build + config_entry_value = null + min_val = 0 + /datum/config_entry/number/minute_topic_limit config_entry_value = null min_val = 0 diff --git a/code/controllers/configuration/entries/resources.dm b/code/controllers/configuration/entries/resources.dm new file mode 100644 index 0000000000..c839ccc078 --- /dev/null +++ b/code/controllers/configuration/entries/resources.dm @@ -0,0 +1,30 @@ +/datum/config_entry/keyed_list/external_rsc_urls + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_FLAG + +/datum/config_entry/flag/asset_simple_preload + +/datum/config_entry/string/asset_transport +/datum/config_entry/string/asset_transport/ValidateAndSet(str_val) + return (lowertext(str_val) in list("simple", "webroot")) && ..(lowertext(str_val)) + +/datum/config_entry/string/asset_cdn_webroot + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/string/asset_cdn_webroot/ValidateAndSet(str_var) + if (!str_var || trim(str_var) == "") + return FALSE + if (str_var && str_var[length(str_var)] != "/") + str_var += "/" + return ..(str_var) + +/datum/config_entry/string/asset_cdn_url + protection = CONFIG_ENTRY_LOCKED + default = null + +/datum/config_entry/string/asset_cdn_url/ValidateAndSet(str_var) + if (!str_var || trim(str_var) == "") + return FALSE + if (str_var && str_var[length(str_var)] != "/") + str_var += "/" + return ..(str_var) diff --git a/code/controllers/controller.dm b/code/controllers/controller.dm index 06547d120d..1f0a01a072 100644 --- a/code/controllers/controller.dm +++ b/code/controllers/controller.dm @@ -16,4 +16,4 @@ /datum/controller/proc/Recover() -/datum/controller/proc/stat_entry() \ No newline at end of file +/datum/controller/proc/stat_entry(msg) diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index 3ce770b66d..148822cdd1 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -95,8 +95,6 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) /datum/controller/failsafe/proc/defcon_pretty() return defcon -/datum/controller/failsafe/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) - - stat("Failsafe Controller:", statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])")) +/datum/controller/failsafe/stat_entry(msg) + msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])" + return msg diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm index a085b26410..6b5fb294ea 100644 --- a/code/controllers/globals.dm +++ b/code/controllers/globals.dm @@ -24,11 +24,9 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) //fuck off kevinz return QDEL_HINT_IWILLGC -/datum/controller/global_vars/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) - - stat("Globals:", statclick.update("Edit")) +/datum/controller/global_vars/stat_entry(msg) + msg = "Edit" + return msg /datum/controller/global_vars/vv_edit_var(var_name, var_value) if(gvars_datum_protected_varlist[var_name]) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index cdbea1de85..1b5c7e5e83 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -76,7 +76,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // Highlander-style: there can only be one! Kill off the old and replace it with the new. if(!random_seed) - random_seed = (TEST_RUN_PARAMETER in world.params) ? 29051994 : rand(1, 1e9) + #ifdef UNIT_TESTS + random_seed = 29051994 + #else + random_seed = rand(1, 1e9) + #endif rand_seed(random_seed) var/list/_subsystems = list() @@ -184,9 +188,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(delay) sleep(delay) - if(tgs_prime) - world.TgsInitializationComplete() - if(init_sss) init_subtypes(/datum/controller/subsystem, subsystems) @@ -219,6 +220,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new world.fps = CONFIG_GET(number/fps) var/initialized_tod = REALTIMEOFDAY + if(tgs_prime) + world.TgsInitializationComplete() + if(sleep_offline_after_initializations) world.sleep_offline = TRUE sleep(1) @@ -611,13 +615,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new skip_ticks = 1 -/datum/controller/master/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) +/datum/controller/master/stat_entry(msg) + msg = "(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])" + return msg - stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)") - stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])")) - stat("Misc Subsystems", misc_statclick) /datum/controller/master/StartLoadingMap() //disallow more than one map to load at once, multithreading it will just cause race conditions @@ -643,3 +644,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new processing = CONFIG_GET(number/mc_tick_rate/base_mc_tick_rate) else if (client_count > CONFIG_GET(number/mc_tick_rate/high_pop_mc_mode_amount)) processing = CONFIG_GET(number/mc_tick_rate/high_pop_mc_tick_rate) + +/datum/controller/master/proc/OnConfigLoad() + for (var/thing in subsystems) + var/datum/controller/subsystem/SS = thing + SS.OnConfigLoad() diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 4ee3a01956..bb8ce951f5 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -1,39 +1,91 @@ +/** + * # Subsystem base class + * + * Defines a subsystem to be managed by the [Master Controller][/datum/controller/master] + * + * Simply define a child of this subsystem, using the [SUBSYSTEM_DEF] macro, and the MC will handle registration. + * Changing the name is required +**/ /datum/controller/subsystem // Metadata; you should define these. - name = "fire coderbus" //name of the subsystem - var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Use defines in __DEFINES/subsystems.dm for easy understanding of order. - var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer. - var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep - var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again) + /// Name of the subsystem - you must change this + name = "fire coderbus" - var/initialized = FALSE //set to TRUE after it has been initialized, will obviously never be set if the subsystem doesn't initialize + /// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file. + var/init_order = INIT_ORDER_DEFAULT - //set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later - // use the SS_NO_FIRE flag instead for systems that never fire to keep it from even being added to the list + /// Time to wait (in deciseconds) between each call to fire(). Must be a positive integer. + var/wait = 20 + + /// Priority Weight: When mutiple subsystems need to run in the same tick, higher priority subsystems will be given a higher share of the tick before MC_TICK_CHECK triggers a sleep, higher priority subsystems also run before lower priority subsystems + var/priority = FIRE_PRIORITY_DEFAULT + + /// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again) + var/flags = 0 + + /// This var is set to TRUE after the subsystem has been initialized. + var/initialized = FALSE + + /// Set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later + /// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick var/can_fire = TRUE - // Bookkeeping variables; probably shouldn't mess with these. - var/last_fire = 0 //last world.time we called fire() - var/next_fire = 0 //scheduled world.time for next fire() - var/cost = 0 //average time to execute - var/tick_usage = 0 //average tick usage - var/tick_overrun = 0 //average tick overrun - var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc. - var/paused_ticks = 0 //ticks this ss is taking to run right now. - var/paused_tick_usage //total tick_usage of all of our runs while pausing this run - var/ticks = 1 //how many ticks does this ss take to run on avg. - var/times_fired = 0 //number of times we have called fire() - var/queued_time = 0 //time we entered the queue, (for timing and priority reasons) - var/queued_priority //we keep a running total to make the math easier, if priority changes mid-fire that would break our running total, so we store it here - //linked list stuff for the queue - var/datum/controller/subsystem/queue_next - var/datum/controller/subsystem/queue_prev - + ///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details. var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire - var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out! + /* + * The following variables are managed by the MC and should not be modified directly. + */ + + /// Last world.time the subsystem completed a run (as in wasn't paused by [MC_TICK_CHECK]) + var/last_fire = 0 + + /// Scheduled world.time for next fire() + var/next_fire = 0 + + /// Running average of the amount of milliseconds it takes the subsystem to complete a run (including all resumes but not the time spent paused) + var/cost = 0 + + /// Running average of the amount of tick usage in percents of a tick it takes the subsystem to complete a run + var/tick_usage = 0 + + /// Running average of the amount of tick usage (in percents of a game tick) the subsystem has spent past its allocated time without pausing + var/tick_overrun = 0 + + /// Tracks the current execution state of the subsystem. Used to handle subsystems that sleep in fire so the mc doesn't run them again while they are sleeping + var/state = SS_IDLE + + /// Tracks how many fires the subsystem has consecutively paused on in the current run + var/paused_ticks = 0 + + /// Tracks how much of a tick the subsystem has consumed in the current run + var/paused_tick_usage + + /// Tracks how many fires the subsystem takes to complete a run on average. + var/ticks = 1 + + /// Tracks the amount of completed runs for the subsystem + var/times_fired = 0 + + /// Time the subsystem entered the queue, (for timing and priority reasons) + var/queued_time = 0 + + /// Priority at the time the subsystem entered the queue. Needed to avoid changes in priority (by admins and the like) from breaking things. + var/queued_priority + + /// How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out! + var/static/list/failure_strikes + + /// Next subsystem in the queue of subsystems to run this tick + var/datum/controller/subsystem/queue_next + /// Previous subsystem in the queue of subsystems to run this tick + var/datum/controller/subsystem/queue_prev + + //Do not blindly add vars here to the bottom, put it where it goes above + //If your var only has two values, put it in as a flag. + //Do not override ///datum/controller/subsystem/New() @@ -46,6 +98,7 @@ //This is used so the mc knows when the subsystem sleeps. do not override. /datum/controller/subsystem/proc/ignite(resumed = 0) + SHOULD_NOT_OVERRIDE(TRUE) set waitfor = 0 . = SS_SLEEPING fire(resumed) @@ -87,7 +140,7 @@ queue_node_flags = queue_node.flags if (queue_node_flags & SS_TICKER) - if (!(SS_flags & SS_TICKER)) + if ((SS_flags & (SS_TICKER|SS_BACKGROUND)) != SS_TICKER) continue if (queue_node_priority < SS_priority) break @@ -155,6 +208,9 @@ if(SS_SLEEPING) state = SS_PAUSING +/// Called after the config has been loaded or reloaded. +/datum/controller/subsystem/proc/OnConfigLoad() + /datum/controller/subsystem/proc/subsystem_log(msg) return log_subsystem(name, msg) @@ -167,23 +223,12 @@ log_subsystem("INIT", msg) return time -//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc. /datum/controller/subsystem/stat_entry(msg) - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) - - - if(can_fire && !(SS_NO_FIRE & flags)) msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]" else msg = "OFFLINE\t[msg]" - - var/title = name - if (can_fire) - title = "\[[state_letter()]][title]" - - stat(title, statclick.update(msg)) + return msg /datum/controller/subsystem/proc/state_letter() switch (state) diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm index 7c9e7634ab..25d080a1b1 100644 --- a/code/controllers/subsystem/acid.dm +++ b/code/controllers/subsystem/acid.dm @@ -7,8 +7,9 @@ SUBSYSTEM_DEF(acid) var/list/currentrun = list() var/list/processing = list() -/datum/controller/subsystem/acid/stat_entry() - ..("P:[processing.len]") +/datum/controller/subsystem/acid/stat_entry(msg) + msg = "P:[length(processing)]" + return ..() /datum/controller/subsystem/acid/fire(resumed = 0) diff --git a/code/controllers/subsystem/adjacent_air.dm b/code/controllers/subsystem/adjacent_air.dm index 8395eda708..ccbf8ffc65 100644 --- a/code/controllers/subsystem/adjacent_air.dm +++ b/code/controllers/subsystem/adjacent_air.dm @@ -6,12 +6,13 @@ SUBSYSTEM_DEF(adjacent_air) priority = FIRE_PRIORITY_ATMOS_ADJACENCY var/list/queue = list() -/datum/controller/subsystem/adjacent_air/stat_entry() +/datum/controller/subsystem/adjacent_air/stat_entry(msg) #ifdef TESTING - ..("P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]") + msg = "P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]" #else - ..("P:[length(queue)]") + msg = "P:[length(queue)]" #endif + return ..() /datum/controller/subsystem/adjacent_air/Initialize() while(length(queue)) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index baceb4d055..e0c6c48eaa 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -16,7 +16,6 @@ SUBSYSTEM_DEF(air) var/cost_atmos_machinery = 0 var/cost_equalize = 0 - var/list/active_turfs = list() var/list/hotspots = list() var/list/networks = list() var/list/pipenets_needing_rebuilt = list() @@ -54,14 +53,17 @@ SUBSYSTEM_DEF(air) msg += "PN:[round(cost_pipenets,1)]|" msg += "AM:[round(cost_atmos_machinery,1)]" msg += "} " - msg += "AT:[active_turfs.len]|" + var/active_turfs_len = get_amt_active_turfs() + msg += "AT:[active_turfs_len]|" msg += "EG:[get_amt_excited_groups()]|" msg += "HS:[hotspots.len]|" msg += "PN:[networks.len]|" msg += "HP:[high_pressure_delta.len]|" msg += "AS:[active_super_conductivity.len]|" - msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]" - ..(msg) + msg += "GA:[get_amt_gas_mixes()]|" + msg += "MG:[get_max_gas_mixes()]|" + msg += "AT/MS:[round((cost ? active_turfs_len/cost : 0),0.1)]" + return ..() /datum/controller/subsystem/air/Initialize(timeofday) extools_update_ssair() @@ -70,9 +72,12 @@ SUBSYSTEM_DEF(air) setup_atmos_machinery() setup_pipenets() gas_reactions = init_gas_reactions() + extools_update_reactions() return ..() /datum/controller/subsystem/air/proc/extools_update_ssair() +/datum/controller/subsystem/air/proc/extools_update_reactions() +/datum/controller/subsystem/air/proc/scan_for_active_turfs() /datum/controller/subsystem/air/fire(resumed = 0) var/timer = TICK_USAGE_REAL @@ -160,6 +165,8 @@ SUBSYSTEM_DEF(air) if(state != SS_RUNNING) return resumed = 0 + if(get_amt_active_turfs() < 3000 && !TICK_CHECK) + scan_for_active_turfs() currentpart = SSAIR_REBUILD_PIPENETS @@ -237,6 +244,8 @@ SUBSYSTEM_DEF(air) return /datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0) + return process_turf_equalize_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + /* //cache for sanic speed var/fire_count = times_fired if (!resumed) @@ -251,8 +260,11 @@ SUBSYSTEM_DEF(air) //equalize_pressure_in_zone(T, fire_count) if (MC_TICK_CHECK) return + */ /datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0) + return process_active_turfs_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + /* //cache for sanic speed var/fire_count = times_fired if (!resumed) @@ -266,10 +278,10 @@ SUBSYSTEM_DEF(air) T.process_cell(fire_count) if (MC_TICK_CHECK) return + */ /datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0) - if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) - sleep() + return process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) /* if (!resumed) src.currentrun = excited_groups.Copy() @@ -288,13 +300,20 @@ SUBSYSTEM_DEF(air) return */ +/datum/controller/subsystem/air/proc/process_active_turfs_extools() +/datum/controller/subsystem/air/proc/process_turf_equalize_extools() /datum/controller/subsystem/air/proc/process_excited_groups_extools() /datum/controller/subsystem/air/proc/get_amt_excited_groups() +/datum/controller/subsystem/air/proc/get_amt_active_turfs() +/datum/controller/subsystem/air/proc/get_amt_gas_mixes() +/datum/controller/subsystem/air/proc/get_max_gas_mixes() +/datum/controller/subsystem/air/proc/add_to_active_extools() +/datum/controller/subsystem/air/proc/remove_from_active_extools() +/datum/controller/subsystem/air/proc/get_active_turfs() +/datum/controller/subsystem/air/proc/clear_active_turfs() /datum/controller/subsystem/air/proc/remove_from_active(turf/open/T) - active_turfs -= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun -= T + remove_from_active_extools(T) #ifdef VISUALIZE_ACTIVE_TURFS T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00") #endif @@ -308,9 +327,7 @@ SUBSYSTEM_DEF(air) T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY) #endif T.set_excited(TRUE) - active_turfs |= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun |= T + add_to_active_extools(T) if(blockchanges) T.eg_garbage_collect() else if(T.flags_1 & INITIALIZED_1) @@ -335,12 +352,11 @@ SUBSYSTEM_DEF(air) /datum/controller/subsystem/air/proc/setup_allturfs() var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz)) - var/list/active_turfs = src.active_turfs var/times_fired = ++src.times_fired // Clear active turfs - faster than removing every single turf in the world // one-by-one, and Initalize_Atmos only ever adds `src` back in. - active_turfs.Cut() + clear_active_turfs() for(var/thing in turfs_to_init) var/turf/T = thing @@ -348,28 +364,27 @@ SUBSYSTEM_DEF(air) continue T.Initalize_Atmos(times_fired) CHECK_TICK - - if(active_turfs.len) - var/starting_ats = active_turfs.len + var/starting_ats = get_amt_active_turfs() + if(starting_ats) sleep(world.tick_lag) var/timer = world.timeofday log_mapping("There are [starting_ats] active turfs at roundstart caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required).") - for(var/turf/T in active_turfs) + var/list/turfs_to_check = get_amt_active_turfs() + for(var/T in turfs_to_check) GLOB.active_turfs_startlist += T //now lets clear out these active turfs - var/list/turfs_to_check = active_turfs.Copy() do var/list/new_turfs_to_check = list() for(var/turf/open/T in turfs_to_check) new_turfs_to_check += T.resolve_active_graph() CHECK_TICK - - active_turfs += new_turfs_to_check + for(var/T in new_turfs_to_check) + add_to_active_extools(T) turfs_to_check = new_turfs_to_check while (turfs_to_check.len) - var/ending_ats = active_turfs.len + var/ending_ats = get_amt_active_turfs() /*for(var/thing in excited_groups) var/datum/excited_group/EG = thing //EG.self_breakdown(space_is_all_consuming = 1) @@ -445,6 +460,8 @@ SUBSYSTEM_DEF(air) return pipe_init_dirs_cache[type]["[dir]"] +/proc/get_extools_benchmarks() + #undef SSAIR_PIPENETS #undef SSAIR_ATMOSMACHINERY #undef SSAIR_ACTIVETURFS diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index 7285298283..4f02d32ad0 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -4,6 +4,23 @@ SUBSYSTEM_DEF(assets) flags = SS_NO_FIRE var/list/cache = list() var/list/preload = list() + var/datum/asset_transport/transport = new() + +/datum/controller/subsystem/assets/OnConfigLoad() + var/newtransporttype = /datum/asset_transport + switch (CONFIG_GET(string/asset_transport)) + if ("webroot") + newtransporttype = /datum/asset_transport/webroot + + if (newtransporttype == transport.type) + return + + var/datum/asset_transport/newtransport = new newtransporttype () + if (newtransport.validate_config()) + transport = newtransport + transport.Load() + + /datum/controller/subsystem/assets/Initialize(timeofday) for(var/type in typesof(/datum/asset)) @@ -11,8 +28,6 @@ SUBSYSTEM_DEF(assets) if (type != initial(A._abstract)) get_asset_datum(type) - preload = cache.Copy() //don't preload assets generated during the round + transport.Initialize(cache) - for(var/client/C in GLOB.clients) - addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, preload, FALSE), 10) ..() diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index db1fced637..b9a4785f49 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -90,6 +90,8 @@ SUBSYSTEM_DEF(atoms) qdeleted = TRUE else if(!(A.flags_1 & INITIALIZED_1)) BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT + else + SEND_SIGNAL(A,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) return qdeleted || QDELING(A) diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm index 1b1c7bc3b7..53c86004a6 100644 --- a/code/controllers/subsystem/augury.dm +++ b/code/controllers/subsystem/augury.dm @@ -9,7 +9,8 @@ SUBSYSTEM_DEF(augury) var/list/observers_given_action = list() /datum/controller/subsystem/augury/stat_entry(msg) - ..("W:[watchers.len]|D:[doombringers.len]") + msg = "W:[watchers.len]|D:[length(doombringers)]" + return ..() /datum/controller/subsystem/augury/proc/register_doom(atom/A, severity) doombringers[A] = severity diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm index ba2794d00f..f2e9da704f 100644 --- a/code/controllers/subsystem/chat.dm +++ b/code/controllers/subsystem/chat.dm @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + SUBSYSTEM_DEF(chat) name = "Chat" flags = SS_TICKER @@ -5,91 +10,29 @@ SUBSYSTEM_DEF(chat) priority = FIRE_PRIORITY_CHAT init_order = INIT_ORDER_CHAT - var/list/payload = list() - + var/list/payload_by_client = list() /datum/controller/subsystem/chat/fire() - for(var/i in payload) - var/client/C = i - C << output(payload[C], "browseroutput:output") - payload -= C - + for(var/key in payload_by_client) + var/client/client = key + var/payload = payload_by_client[key] + payload_by_client -= key + if(client) + // Send to tgchat + client.tgui_panel?.window.send_message("chat/message", payload) + // Send to old chat + for(var/message in payload) + SEND_TEXT(client, message_to_html(message)) if(MC_TICK_CHECK) return - -/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = TRUE) - if(!target || !message) - return - - if(!istext(message)) - stack_trace("to_chat called with invalid input type") - return - - if(target == world) - target = GLOB.clients - - //Some macros remain in the string even after parsing and fuck up the eventual output - var/original_message = message - - //url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. - //Do the double-encoding here to save nanoseconds - var/twiceEncoded - +/datum/controller/subsystem/chat/proc/queue(target, message) if(islist(target)) - var/sanitized_message = FALSE - for(var/I in target) - var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible - - if(!C) - continue - - //Send it to the old style output window. - SEND_TEXT(C, original_message) - - if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. - continue - - if(!sanitized_message) - message = replacetext(message, "\improper", "") - message = replacetext(message, "\proper", "") - if(handle_whitespace) - message = replacetext(message, "\n", "
") - message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") - if (trailing_newline) - message += "
" - twiceEncoded = url_encode(url_encode(message)) - sanitized_message = TRUE - - if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue - C.chatOutput.messageQueue += message - continue - - payload[C] += twiceEncoded - - else - var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible - - if(!C) - return - - //Send it to the old style output window. - SEND_TEXT(C, original_message) - - if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. - return - - message = replacetext(message, "\improper", "") - message = replacetext(message, "\proper", "") - if(handle_whitespace) - message = replacetext(message, "\n", "
") - message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") - if (trailing_newline) - message += "
" - twiceEncoded = url_encode(url_encode(message)) - - if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue - C.chatOutput.messageQueue += message - return - - payload[C] += twiceEncoded + for(var/_target in target) + var/client/client = CLIENT_FROM_VAR(_target) + if(client) + LAZYADD(payload_by_client[client], list(message)) + return + var/client/client = CLIENT_FROM_VAR(target) + if(client) + LAZYADD(payload_by_client[client], list(message)) diff --git a/code/controllers/subsystem/disease.dm b/code/controllers/subsystem/disease.dm index 9be1d8d90c..4fe5533e16 100644 --- a/code/controllers/subsystem/disease.dm +++ b/code/controllers/subsystem/disease.dm @@ -20,7 +20,8 @@ SUBSYSTEM_DEF(disease) return ..() /datum/controller/subsystem/disease/stat_entry(msg) - ..("P:[active_diseases.len]") + msg = "P:[length(active_diseases)]" + return ..() /datum/controller/subsystem/disease/proc/get_disease_name(id) var/datum/disease/advance/A = archive_diseases[id] diff --git a/code/controllers/subsystem/fire_burning.dm b/code/controllers/subsystem/fire_burning.dm index db6dc6513e..3251285ade 100644 --- a/code/controllers/subsystem/fire_burning.dm +++ b/code/controllers/subsystem/fire_burning.dm @@ -7,8 +7,9 @@ SUBSYSTEM_DEF(fire_burning) var/list/currentrun = list() var/list/processing = list() -/datum/controller/subsystem/fire_burning/stat_entry() - ..("P:[processing.len]") +/datum/controller/subsystem/fire_burning/stat_entry(msg) + msg = "P:[length(processing)]" + return ..() /datum/controller/subsystem/fire_burning/fire(resumed = 0) @@ -34,4 +35,3 @@ SUBSYSTEM_DEF(fire_burning) if (MC_TICK_CHECK) return - diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index b46e22c1fa..51d56545b6 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(garbage) msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%" msg += " P:[pass_counts.Join(",")]" msg += "|F:[fail_counts.Join(",")]" - ..(msg) + return ..() /datum/controller/subsystem/garbage/Shutdown() //Adds the del() log to the qdel log file diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm index 8992fa7b92..03b7931d82 100644 --- a/code/controllers/subsystem/idlenpcpool.dm +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -8,10 +8,11 @@ SUBSYSTEM_DEF(idlenpcpool) var/list/currentrun = list() var/static/list/idle_mobs_by_zlevel[][] -/datum/controller/subsystem/idlenpcpool/stat_entry() +/datum/controller/subsystem/idlenpcpool/stat_entry(msg) var/list/idlelist = GLOB.simple_animals[AI_IDLE] var/list/zlist = GLOB.simple_animals[AI_Z_OFF] - ..("IdleNPCS:[idlelist.len]|Z:[zlist.len]") + msg = "IdleNPCS:[length(idlelist)]|Z:[length(zlist)]" + return ..() /datum/controller/subsystem/idlenpcpool/proc/MaxZChanged() if (!islist(idle_mobs_by_zlevel)) diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index c6e6a84bcf..e193c68536 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -7,8 +7,9 @@ SUBSYSTEM_DEF(lighting) wait = 2 init_order = INIT_ORDER_LIGHTING -/datum/controller/subsystem/lighting/stat_entry() - ..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]") +/datum/controller/subsystem/lighting/stat_entry(msg) + msg = "L:[length(GLOB.lighting_update_lights)]|C:[length(GLOB.lighting_update_corners)]|O:[length(GLOB.lighting_update_objects)]" + return ..() /datum/controller/subsystem/lighting/Initialize(timeofday) diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index c4b09d1b87..f356009569 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -22,8 +22,9 @@ SUBSYSTEM_DEF(machines) NewPN.add_cable(PC) propagate_network(PC,PC.powernet) -/datum/controller/subsystem/machines/stat_entry() - ..("M:[processing.len]|PN:[powernets.len]") +/datum/controller/subsystem/machines/stat_entry(msg) + msg = "M:[length(processing)]|PN:[length(powernets)]" + return ..() /datum/controller/subsystem/machines/fire(resumed = 0) diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm index 885587ff55..5a7dd30ce3 100644 --- a/code/controllers/subsystem/mobs.dm +++ b/code/controllers/subsystem/mobs.dm @@ -10,8 +10,9 @@ SUBSYSTEM_DEF(mobs) var/static/list/cubemonkeys = list() var/static/list/cheeserats = list() -/datum/controller/subsystem/mobs/stat_entry() - ..("P:[GLOB.mob_living_list.len]") +/datum/controller/subsystem/mobs/stat_entry(msg) + msg = "P:[length(GLOB.mob_living_list)]" + return ..() /datum/controller/subsystem/mobs/proc/MaxZChanged() if (!islist(clients_by_zlevel)) diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 2d2fbb0704..c67deaede1 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -6,9 +6,10 @@ SUBSYSTEM_DEF(npcpool) var/list/currentrun = list() -/datum/controller/subsystem/npcpool/stat_entry() +/datum/controller/subsystem/npcpool/stat_entry(msg) var/list/activelist = GLOB.simple_animals[AI_ON] - ..("NPCS:[activelist.len]") + msg = "NPCS:[length(activelist)]" + return ..() /datum/controller/subsystem/npcpool/fire(resumed = FALSE) diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm index ea0f82436c..b42a1e6b7e 100644 --- a/code/controllers/subsystem/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -22,8 +22,9 @@ SUBSYSTEM_DEF(overlays) return ..() -/datum/controller/subsystem/overlays/stat_entry() - ..("Ov:[length(queue)]") +/datum/controller/subsystem/overlays/stat_entry(msg) + msg = "Ov:[length(queue)]" + return ..() /datum/controller/subsystem/overlays/Shutdown() diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index 5b60747725..e1b6e6f6e2 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -48,25 +48,6 @@ SUBSYSTEM_DEF(persistence) /datum/controller/subsystem/persistence/proc/LoadSatchels() var/placed_satchel = 0 var/path - if(fexists("data/npc_saves/SecretSatchels.sav")) //legacy conversion. Will only ever run once. - var/savefile/secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav") - for(var/map in secret_satchels) - var/json_file = file("data/npc_saves/SecretSatchels[map].json") - var/list/legacy_secret_satchels = splittext(secret_satchels[map],"#") - var/list/satchels = list() - for(var/i=1,i<=legacy_secret_satchels.len,i++) - var/satchel_string = legacy_secret_satchels[i] - var/list/chosen_satchel = splittext(satchel_string,"|") - if(chosen_satchel.len == 3) - var/list/data = list() - data["x"] = text2num(chosen_satchel[1]) - data["y"] = text2num(chosen_satchel[2]) - data["saved_obj"] = chosen_satchel[3] - satchels += list(data) - var/list/file_data = list() - file_data["data"] = satchels - WRITE_FILE(json_file, json_encode(file_data)) - fdel("data/npc_saves/SecretSatchels.sav") var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") var/list/json = list() diff --git a/code/controllers/subsystem/ping.dm b/code/controllers/subsystem/ping.dm deleted file mode 100644 index c5c9bb3933..0000000000 --- a/code/controllers/subsystem/ping.dm +++ /dev/null @@ -1,33 +0,0 @@ -SUBSYSTEM_DEF(ping) - name = "Ping" - priority = FIRE_PRIORITY_PING - wait = 3 SECONDS - flags = SS_NO_INIT - runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME - - var/list/currentrun = list() - -/datum/controller/subsystem/ping/stat_entry() - ..("P:[GLOB.clients.len]") - - -/datum/controller/subsystem/ping/fire(resumed = 0) - if (!resumed) - src.currentrun = GLOB.clients.Copy() - - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while (currentrun.len) - var/client/C = currentrun[currentrun.len] - currentrun.len-- - - if (!C || !C.chatOutput || !C.chatOutput.loaded) - if (MC_TICK_CHECK) - return - continue - - // softPang isn't handled anywhere but it'll always reset the opts.lastPang. - C.chatOutput.ehjax_send(data = C.is_afk(29) ? "softPang" : "pang") - if (MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm index c5d6dfa126..637b04993d 100644 --- a/code/controllers/subsystem/processing/processing.dm +++ b/code/controllers/subsystem/processing/processing.dm @@ -10,8 +10,9 @@ SUBSYSTEM_DEF(processing) var/list/processing = list() var/list/currentrun = list() -/datum/controller/subsystem/processing/stat_entry() - ..("[stat_tag]:[processing.len]") +/datum/controller/subsystem/processing/stat_entry(msg) + msg = "[stat_tag]:[length(processing)]" + return ..() /datum/controller/subsystem/processing/fire(resumed = 0) if (!resumed) diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm index ef10e0626c..81fa77dc6c 100644 --- a/code/controllers/subsystem/profiler.dm +++ b/code/controllers/subsystem/profiler.dm @@ -12,7 +12,7 @@ SUBSYSTEM_DEF(profiler) /datum/controller/subsystem/profiler/stat_entry(msg) msg += "F:[round(fetch_cost,1)]ms" msg += "|W:[round(write_cost,1)]ms" - ..(msg) + return msg /datum/controller/subsystem/profiler/Initialize() if(CONFIG_GET(flag/auto_profile)) diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index 60c5dd5b99..ac9db60ccc 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -294,6 +294,17 @@ SUBSYSTEM_DEF(research) //[88nodes * 5000points/node] / [1.5hr * 90min/hr * 60s/min] //Around 450000 points max??? + /// The global list of raw anomaly types that have been refined, for hard limits. + var/list/created_anomaly_types = list() + /// The hard limits of cores created for each anomaly type. For faster code lookup without switch statements. + var/list/anomaly_hard_limit_by_type = list( + ANOMALY_CORE_BLUESPACE = MAX_CORES_BLUESPACE, + ANOMALY_CORE_PYRO = MAX_CORES_PYRO, + ANOMALY_CORE_GRAVITATIONAL = MAX_CORES_GRAVITATIONAL, + ANOMALY_CORE_VORTEX = MAX_CORES_VORTEX, + ANOMALY_CORE_FLUX = MAX_CORES_FLUX + ) + /datum/controller/subsystem/research/Initialize() point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES initialize_all_techweb_designs() diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index b77c78c4bb..2427fbd277 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -76,9 +76,7 @@ SUBSYSTEM_DEF(server_maint) if(!thing) continue var/client/C = thing - var/datum/chatOutput/co = C.chatOutput - if(co) - co.ehjax_send(data = "roundrestart") + C?.tgui_panel?.send_roundrestart() if(server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite C << link("byond://[server]") var/datum/tgs_version/tgsversion = world.TgsVersion() diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm index c251492227..c3261df304 100644 --- a/code/controllers/subsystem/spacedrift.dm +++ b/code/controllers/subsystem/spacedrift.dm @@ -8,8 +8,9 @@ SUBSYSTEM_DEF(spacedrift) var/list/currentrun = list() var/list/processing = list() -/datum/controller/subsystem/spacedrift/stat_entry() - ..("P:[processing.len]") +/datum/controller/subsystem/spacedrift/stat_entry(msg) + msg = "P:[length(processing)]" + return ..() /datum/controller/subsystem/spacedrift/fire(resumed = 0) @@ -56,4 +57,3 @@ SUBSYSTEM_DEF(spacedrift) AM.inertia_last_loc = AM.loc if (MC_TICK_CHECK) return - diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm new file mode 100644 index 0000000000..cf7d4ba533 --- /dev/null +++ b/code/controllers/subsystem/statpanel.dm @@ -0,0 +1,195 @@ +SUBSYSTEM_DEF(statpanels) + name = "Stat Panels" + wait = 4 + init_order = INIT_ORDER_STATPANELS + priority = FIRE_PRIORITY_STATPANEL + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + var/list/currentrun = list() + var/encoded_global_data + var/mc_data_encoded + var/list/cached_images = list() + +/datum/controller/subsystem/statpanels/fire(resumed = FALSE) + if (!resumed) + var/datum/map_config/cached = SSmapping.next_map_config + var/round_time = world.time - SSticker.round_start_time + var/list/global_data = list( + "Map: [SSmapping.config?.map_name || "Loading..."]", + cached ? "Next Map: [cached.map_name]" : null, + "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]", + "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]", + "Round Time: [round_time > MIDNIGHT_ROLLOVER ? "[round(round_time/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]", + "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]", + "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)" + ) + + if(SSshuttle.emergency) + var/ETA = SSshuttle.emergency.getModeStr() + if(ETA) + global_data += "[ETA] [SSshuttle.emergency.getTimerStr()]" +/* Please fix + if(SSvote.mode) + var/static/list/supported = list(PLURALITY_VOTING, APPROVAL_VOTING) + global_data += "Vote active!, There is currently a vote running. Question: [SSvote.question]" + if(!(SSvote.vote_system in supported)) + global_data += ", The current vote system is not supported by statpanel rendering. Please vote manually by opening the vote popup using the action button or chat link." + return + global_data += "Time Left:, [round(SSvote.end_time - world.time)] seconds" + + global_data += "Choices:" + for(var/i in 1 to SSvote.choice_statclicks.len) + var/choice = SSvote.choice_statclicks[i] + var/ivotedforthis = FALSE + if(usr.ckey) + switch(SSvote.vote_system) + if(APPROVAL_VOTING) + ivotedforthis = SSvote.voted[usr.ckey] && (i in SSvote.voted[usr.ckey]) + if(PLURALITY_VOTING) + ivotedforthis = SSvote.voted[usr.ckey] == i + + global_data += (ivotedforthis? "\[X\]" : "\[ \]", SSvote.choice_statclicks[choice]) +*/ + + encoded_global_data = url_encode(json_encode(global_data)) + src.currentrun = GLOB.clients.Copy() + mc_data_encoded = null + var/list/currentrun = src.currentrun + while(length(currentrun)) + var/client/target = currentrun[length(currentrun)] + currentrun.len-- + if(!target.statbrowser_ready) + continue + if(target.stat_tab == "Status") + var/ping_str = url_encode("Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)") + var/other_str = url_encode(json_encode(target.mob.get_status_tab_items())) + target << output("[encoded_global_data];[ping_str];[other_str]", "statbrowser:update") + if(!target.holder) + target << output("", "statbrowser:remove_admin_tabs") + else + if(!("MC" in target.panel_tabs) || !("Tickets" in target.panel_tabs)) + target << output("[url_encode(target.holder.href_token)]", "statbrowser:add_admin_tabs") + if(target.stat_tab == "MC") + var/turf/eye_turf = get_turf(target.eye) + var/coord_entry = url_encode(COORD(eye_turf)) + if(!mc_data_encoded) + generate_mc_data() + target << output("[mc_data_encoded];[coord_entry]", "statbrowser:update_mc") + if(target.stat_tab == "Tickets") + var/list/ahelp_tickets = GLOB.ahelp_tickets.stat_entry() + target << output("[url_encode(json_encode(ahelp_tickets))];", "statbrowser:update_tickets") + if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs)) + target << output("", "statbrowser:remove_sdql2") + else if(length(GLOB.sdql2_queries) && (target.stat_tab == "SDQL2" || !("SDQL2" in target.panel_tabs))) + var/list/sdql2A = list() + sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj)) + var/list/sdql2B = list() + for(var/i in GLOB.sdql2_queries) + var/datum/SDQL2_query/Q = i + sdql2B = Q.generate_stat() + sdql2A += sdql2B + target << output(url_encode(json_encode(sdql2A)), "statbrowser:update_sdql2") + if(target.mob) + var/mob/M = target.mob + if((target.stat_tab in target.spell_tabs) || !length(target.spell_tabs) && (length(M.mob_spell_list) || length(M.mind?.spell_list))) + var/list/proc_holders = M.get_proc_holders() + target.spell_tabs.Cut() + for(var/phl in proc_holders) + var/list/proc_holder_list = phl + target.spell_tabs |= proc_holder_list[1] + var/proc_holders_encoded = "" + if(length(proc_holders)) + proc_holders_encoded = url_encode(json_encode(proc_holders)) + target << output("[url_encode(json_encode(target.spell_tabs))];[proc_holders_encoded]", "statbrowser:update_spells") + if(M?.listed_turf) + var/mob/target_mob = M + if(!target_mob.TurfAdjacent(target_mob.listed_turf)) + target << output("", "statbrowser:remove_listedturf") + target_mob.listed_turf = null + else if(target.stat_tab == M?.listed_turf.name || !(M?.listed_turf.name in target.panel_tabs)) + var/list/overrides = list() + var/list/turfitems = list() + for(var/img in target.images) + var/image/target_image = img + if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override) + continue + overrides += target_image.loc + turfitems[++turfitems.len] = list("[target_mob.listed_turf]", REF(target_mob.listed_turf), icon2html(target_mob.listed_turf, target, sourceonly=TRUE)) + for(var/tc in target_mob.listed_turf) + var/atom/movable/turf_content = tc + if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) + continue + if(turf_content.invisibility > target_mob.see_invisible) + continue + if(turf_content in overrides) + continue + if(turf_content.IsObscured()) + continue + if(length(turfitems) < 30) // only create images for the first 30 items on the turf, for performance reasons + if(!(REF(turf_content) in cached_images)) + cached_images += REF(turf_content) + turf_content.RegisterSignal(turf_content, COMSIG_PARENT_QDELETING, /atom/.proc/remove_from_cache) // we reset cache if anything in it gets deleted + if(ismob(turf_content) || length(turf_content.overlays) > 2) + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), costly_icon2html(turf_content, target, sourceonly=TRUE)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), icon2html(turf_content, target, sourceonly=TRUE)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content)) + turfitems = url_encode(json_encode(turfitems)) + target << output("[turfitems];", "statbrowser:update_listedturf") + if(MC_TICK_CHECK) + return + + +/datum/controller/subsystem/statpanels/proc/generate_mc_data() + var/list/mc_data = list( + list("CPU:", world.cpu), + list("Instances:", "[num2text(world.contents.len, 10)]"), + list("World Time:", "[world.time]"), + list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"), + list("[config]:", config.stat_entry(), "\ref[config]"), + list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), + list("Master Controller:", Master.stat_entry(), "\ref[Master]"), + list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"), + list("","") + ) + for(var/ss in Master.subsystems) + var/datum/controller/subsystem/sub_system = ss + mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]") + mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", "\ref[GLOB.cameranet]") + mc_data_encoded = url_encode(json_encode(mc_data)) + +/atom/proc/remove_from_cache() + SSstatpanels.cached_images -= REF(src) + +/// verbs that send information from the browser UI +/client/verb/set_tab(tab as text|null) + set name = "Set Tab" + set hidden = TRUE + + stat_tab = tab + +/client/verb/send_tabs(tabs as text|null) + set name = "Send Tabs" + set hidden = TRUE + + panel_tabs |= tabs + +/client/verb/remove_tabs(tabs as text|null) + set name = "Remove Tabs" + set hidden = TRUE + + panel_tabs -= tabs + +/client/verb/reset_tabs() + set name = "Reset Tabs" + set hidden = TRUE + + panel_tabs = list() + +/client/verb/panel_ready() + set name = "Panel Ready" + set hidden = TRUE + + statbrowser_ready = TRUE diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm index a5526d2c03..511ab623da 100644 --- a/code/controllers/subsystem/tgui.dm +++ b/code/controllers/subsystem/tgui.dm @@ -24,15 +24,16 @@ SUBSYSTEM_DEF(tgui) var/basehtml /datum/controller/subsystem/tgui/PreInit() - basehtml = file2text('tgui/packages/tgui/public/tgui.html') + basehtml = file2text('tgui/public/tgui.html') /datum/controller/subsystem/tgui/Shutdown() close_all_uis() -/datum/controller/subsystem/tgui/stat_entry() - ..("P:[open_uis.len]") +/datum/controller/subsystem/tgui/stat_entry(msg) + msg = "P:[length(open_uis)]" + return ..() -/datum/controller/subsystem/tgui/fire(resumed = 0) +/datum/controller/subsystem/tgui/fire(resumed = FALSE) if(!resumed) src.current_run = open_uis.Copy() // Cache for sanic speed (lists are references anyways) @@ -81,7 +82,8 @@ SUBSYSTEM_DEF(tgui) window_found = TRUE break if(!window_found) - log_tgui(user, "Error: Pool exhausted") + log_tgui(user, "Error: Pool exhausted", + context = "SStgui/request_pooled_window") return null return window @@ -93,7 +95,7 @@ SUBSYSTEM_DEF(tgui) * required user mob */ /datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user) - log_tgui(user, "force_close_all_windows") + log_tgui(user, context = "SStgui/force_close_all_windows") if(user.client) user.client.tgui_windows = list() for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) @@ -109,7 +111,7 @@ SUBSYSTEM_DEF(tgui) * required window_id string */ /datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id) - log_tgui(user, "force_close_window") + log_tgui(user, context = "SStgui/force_close_window") // Close all tgui datums based on window_id. for(var/datum/tgui/ui in user.tgui_open_uis) if(ui.window && ui.window.id == window_id) diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index d757b00493..8c5abc5469 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -11,8 +11,9 @@ SUBSYSTEM_DEF(throwing) var/list/currentrun var/list/processing = list() -/datum/controller/subsystem/throwing/stat_entry() - ..("P:[processing.len]") +/datum/controller/subsystem/throwing/stat_entry(msg) + msg = "P:[length(processing)]" + return ..() /datum/controller/subsystem/throwing/fire(resumed = 0) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 0bc4e6665a..19f19f05ac 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -396,6 +396,7 @@ SUBSYSTEM_DEF(ticker) SSjob.EquipRank(N, player.mind.assigned_role, 0) if(CONFIG_GET(flag/roundstart_traits) && ishuman(N.new_character)) SSquirks.AssignQuirks(N.new_character, N.client, TRUE, TRUE, SSjob.GetJob(player.mind.assigned_role), FALSE, N) + N.client.prefs.post_copy_to(player) CHECK_TICK if(captainless) for(var/mob/dead/new_player/N in GLOB.player_list) @@ -416,6 +417,7 @@ SUBSYSTEM_DEF(ticker) living.client.prefs.chat_toggles ^= CHAT_OOC var/obj/screen/splash/S = new(living.client, TRUE) S.Fade(TRUE) + living.client.init_verbs() livings += living if(livings.len) addtimer(CALLBACK(src, .proc/release_characters, livings), 30, TIMER_CLIENT_TIME) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 36bf992cfb..398e23cdc1 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -34,7 +34,8 @@ SUBSYSTEM_DEF(timer) bucket_resolution = world.tick_lag /datum/controller/subsystem/timer/stat_entry(msg) - ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]") + msg = "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]" + return ..() /datum/controller/subsystem/timer/fire(resumed = FALSE) var/lit = last_invoke_tick diff --git a/code/datums/accents.dm b/code/datums/accents.dm new file mode 100644 index 0000000000..ce32aa0884 --- /dev/null +++ b/code/datums/accents.dm @@ -0,0 +1,106 @@ +/datum/accent + +/datum/accent/proc/modify_speech(list/speech_args, datum/source, mob/living/carbon/owner) //transforms the message in some way + return speech_args + +/datum/accent/lizard/modify_speech(list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + var/static/regex/lizard_hiss = new("s+", "g") + var/static/regex/lizard_hiSS = new("S+", "g") + if(message[1] != "*") + message = lizard_hiss.Replace(message, "sss") + message = lizard_hiSS.Replace(message, "SSS") + speech_args[SPEECH_MESSAGE] = message + return speech_args + +/datum/accent/fly/modify_speech(list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + var/static/regex/fly_buzz = new("z+", "g") + var/static/regex/fly_buZZ = new("Z+", "g") + if(message[1] != "*") + message = fly_buzz.Replace(message, "zzz") + message = fly_buZZ.Replace(message, "ZZZ") + speech_args[SPEECH_MESSAGE] = message + return speech_args + +/datum/accent/abductor/modify_speech(list/speech_args, datum/source) + var/message = speech_args[SPEECH_MESSAGE] + var/mob/living/carbon/human/user = source + var/rendered = "[user.name]: [message]" + user.log_talk(message, LOG_SAY, tag="abductor") + for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) + var/obj/item/organ/tongue/T = H.getorganslot(ORGAN_SLOT_TONGUE) + if(!T || T.type != type) + continue + if(H.dna && H.dna.species.id == "abductor" && user.dna && user.dna.species.id == "abductor") + var/datum/antagonist/abductor/A = user.mind.has_antag_datum(/datum/antagonist/abductor) + if(!A || !(H.mind in A.team.members)) + continue + to_chat(H, rendered) + for(var/mob/M in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(M, user) + to_chat(M, "[link] [rendered]") + speech_args[SPEECH_MESSAGE] = "" + return speech_args + +/datum/accent/zombie/modify_speech(list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + var/list/message_list = splittext(message, " ") + var/maxchanges = max(round(message_list.len / 1.5), 2) + + for(var/i = rand(maxchanges / 2, maxchanges), i > 0, i--) + var/insertpos = rand(1, message_list.len - 1) + var/inserttext = message_list[insertpos] + + if(!(copytext(inserttext, -3) == "..."))//3 == length("...") + message_list[insertpos] = inserttext + "..." + + if(prob(20) && message_list.len > 3) + message_list.Insert(insertpos, "[pick("BRAINS", "Brains", "Braaaiinnnsss", "BRAAAIIINNSSS")]...") + + speech_args[SPEECH_MESSAGE] = jointext(message_list, " ") + return speech_args + +/datum/accent/alien/modify_speech(list/speech_args, datum/source) + playsound(source, "hiss", 25, 1, 1) + return speech_args + +/datum/accent/fluffy/modify_speech(list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + if(message[1] != "*") + message = replacetext(message, "ne", "nye") + message = replacetext(message, "nu", "nyu") + message = replacetext(message, "na", "nya") + message = replacetext(message, "no", "nyo") + message = replacetext(message, "ove", "uv") + message = replacetext(message, "l", "w") + message = replacetext(message, "r", "w") + speech_args[SPEECH_MESSAGE] = lowertext(message) + return speech_args + +/datum/accent/span + var/span_flag + +/datum/accent/span/modify_speech(list/speech_args) + speech_args[SPEECH_SPANS] |= span_flag + return speech_args + +//bone tongues either have the sans accent or the papyrus accent +/datum/accent/span/sans + span_flag = SPAN_SANS + +/datum/accent/span/papyrus + span_flag = SPAN_PAPYRUS + +/datum/accent/span/robot + span_flag = SPAN_ROBOT + +/datum/accent/dullahan/modify_speech(list/speech_args, datum/source, mob/living/carbon/owner) + if(owner) + if(isdullahan(owner)) + var/datum/species/dullahan/D = owner.dna.species + if(isobj(D.myhead.loc)) + var/obj/O = D.myhead.loc + O.say(speech_args[SPEECH_MESSAGE]) + speech_args[SPEECH_MESSAGE] = "" + return speech_args diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 96b2a2a294..dbe60817bd 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -8,14 +8,14 @@ var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id var/stylesheets[0] var/scripts[0] - var/title_image var/head_elements var/body_elements var/head_content = "" var/content = "" + var/static/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) -/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) +/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null) user = nuser window_id = nwindow_id @@ -27,7 +27,6 @@ height = nheight if (nref) ref = nref - add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs /datum/browser/proc/add_head_content(nhead_content) head_content = nhead_content @@ -35,22 +34,21 @@ /datum/browser/proc/set_window_options(nwindow_options) window_options = nwindow_options -/datum/browser/proc/set_title_image(ntitle_image) - //title_image = ntitle_image - /datum/browser/proc/add_stylesheet(name, file) if(istype(name, /datum/asset/spritesheet)) var/datum/asset/spritesheet/sheet = name stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]" else var/asset_name = "[name].css" + stylesheets[asset_name] = file - if(!SSassets.cache[asset_name]) - register_asset(asset_name, file) + + if (!SSassets.cache[asset_name]) + SSassets.transport.register_asset(asset_name, file) /datum/browser/proc/add_script(name, file) scripts["[ckey(name)].js"] = file - register_asset("[ckey(name)].js", file) + SSassets.transport.register_asset("[ckey(name)].js", file) /datum/browser/proc/set_content(ncontent) content = ncontent @@ -60,15 +58,13 @@ /datum/browser/proc/get_header() var/file + head_content += "" for (file in stylesheets) - head_content += "" + head_content += "" + for (file in scripts) - head_content += "" - - var/title_attributes = "class='uiTitle'" - if (title_image) - title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" + head_content += "" return {" @@ -79,7 +75,7 @@
- [title ? "
[title]
" : ""] + [title ? "
[title]
" : ""]
"} //" This is here because else the rest of the file looks like a string in notepad++. @@ -105,10 +101,11 @@ var/window_size = "" if(width && height) window_size = "size=[width]x[height];" + common_asset.send(user) if(stylesheets.len) - send_asset_list(user, stylesheets) + SSassets.transport.send_assets(user, stylesheets) if(scripts.len) - send_asset_list(user, scripts) + SSassets.transport.send_assets(user, scripts) user << browse(get_content(), "window=[window_id];[window_size][window_options]") if(use_onclose) setup_onclose() @@ -169,7 +166,7 @@ return Button3 //Same shit, but it returns the button number, could at some point support unlimited button amounts. -/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) +/proc/askuser(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) if (!istype(User)) if (istype(User, /client/)) var/client/C = User @@ -188,7 +185,7 @@ var/selectedbutton = 0 var/stealfocus -/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, StealFocus = 1, Timeout = 6000) +/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null, StealFocus = 1, Timeout = 6000) ..() stealfocus = StealFocus if (!StealFocus) diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index 0bb6c4a0af..f5a34bfca2 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -76,19 +76,11 @@ return FALSE if(M.is_flying()) return FALSE - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(istype(H.belt, /obj/item/wormhole_jaunter)) - var/obj/item/wormhole_jaunter/J = H.belt - //To freak out any bystanders - H.visible_message("[H] falls into [parent]!") - J.chasm_react(H) - return FALSE return TRUE /datum/component/chasm/proc/drop(atom/movable/AM) //Make sure the item is still there after our sleep - if(!AM || QDELETED(AM)) + if(!AM || QDELETED(AM) || SEND_SIGNAL(AM, COMSIG_MOVABLE_CHASM_DROP, src)) return falling_atoms[AM] = (falling_atoms[AM] || 0) + 1 var/turf/T = target_turf diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm index 717e99e8b2..df0a2a091a 100644 --- a/code/datums/components/crafting/recipes/recipes_clothing.dm +++ b/code/datums/components/crafting/recipes/recipes_clothing.dm @@ -273,6 +273,16 @@ time = 30 category = CAT_CLOTHING +/datum/crafting_recipe/twinsheath + name = "Twin Sword Sheath" + result = /obj/item/storage/belt/sabre/twin + reqs = list(/obj/item/stack/sheet/mineral/wood = 3, + /obj/item/stack/sheet/leather = 8) + tools = list(TOOL_WIRECUTTER) + time = 70 + category = CAT_CLOTHING + + /datum/crafting_recipe/durathread_reinforcement_kit name = "Durathread Reinforcement Kit" result = /obj/item/armorkit diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm index f113be728d..14987bac44 100644 --- a/code/datums/components/crafting/recipes/recipes_misc.dm +++ b/code/datums/components/crafting/recipes/recipes_misc.dm @@ -120,6 +120,53 @@ category = CAT_MISC always_availible = FALSE // Disabled til learned +/datum/crafting_recipe/furnace + name = "Sandstone Furnace" + result = /obj/structure/furnace + time = 300 + reqs = list(/obj/item/stack/sheet/mineral/sandstone = 15, + /obj/item/stack/sheet/metal = 4, + /obj/item/stack/rods = 2) + tools = list(TOOL_CROWBAR) + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + +/datum/crafting_recipe/tableanvil + name = "Table Anvil" + result = /obj/structure/anvil/obtainable/table + time = 300 + reqs = list(/obj/item/stack/sheet/metal = 4, + /obj/item/stack/rods = 2) + tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER) + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + +/datum/crafting_recipe/sandvil + name = "Sandstone Anvil" + result = /obj/structure/anvil/obtainable/sandstone + time = 300 + reqs = list(/obj/item/stack/sheet/mineral/sandstone = 24) + tools = list(TOOL_CROWBAR) + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + +/datum/crafting_recipe/basaltblock + name = "Sintered Basalt Block" + result = /obj/item/basaltblock + time = 200 + reqs = list(/obj/item/stack/ore/glass/basalt = 50) + tools = list(TOOL_WELDER) + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + +/datum/crafting_recipe/basaltanvil + name = "Basalt Anvil" + result = /obj/structure/anvil/obtainable/basalt + time = 200 + reqs = list(/obj/item/basaltblock = 5) + tools = list(TOOL_CROWBAR) + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC /////////////////// //Tools & Storage// /////////////////// @@ -175,6 +222,17 @@ subcategory = CAT_TOOL category = CAT_MISC +/datum/crafting_recipe/toolboxhammer + name = "Toolbox Hammer" + result = /obj/item/melee/smith/hammer/toolbox + tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER) + reqs = list(/obj/item/storage/toolbox = 1, + /obj/item/stack/sheet/metal = 4, + /obj/item/stack/rods = 2) + time = 40 + subcategory = CAT_TOOL + category = CAT_MISC + /datum/crafting_recipe/papersack name = "Paper Sack" result = /obj/item/storage/box/papersack @@ -358,6 +416,25 @@ //Unsorted// //////////// + + +/datum/crafting_recipe/stick + name = "Stick" + time = 30 + reqs = list(/obj/item/stack/sheet/mineral/wood = 1) + result = /obj/item/stick + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + + +/datum/crafting_recipe/swordhilt + name = "Sword Hilt" + time = 30 + reqs = list(/obj/item/stack/sheet/mineral/wood = 2) + result = /obj/item/swordhandle + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + /datum/crafting_recipe/blackcarpet name = "Black Carpet" reqs = list(/obj/item/stack/tile/carpet = 50, /obj/item/toy/crayon/black = 1) diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm index b6de85cab0..0ada00a2e8 100644 --- a/code/datums/components/fantasy/prefixes.dm +++ b/code/datums/components/fantasy/prefixes.dm @@ -45,8 +45,9 @@ /datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) var/obj/item/master = comp.parent - master.AddElement(/datum/element/tactical) - comp.appliedElements += list(/datum/element/tactical) + var/list/dat = list(/datum/element/tactical) + master._AddElement(dat) + comp.appliedElements += list(dat) return "tactical [newName]" /datum/fantasy_affix/pyromantic diff --git a/code/datums/components/honkspam.dm b/code/datums/components/honkspam.dm new file mode 100644 index 0000000000..73b5e3335a --- /dev/null +++ b/code/datums/components/honkspam.dm @@ -0,0 +1,22 @@ +// This used to be in paper.dm, it was some snowflake code that was +// used ONLY on april's fool. I moved it to a component so it could be +// used in other places + +/datum/component/honkspam + dupe_mode = COMPONENT_DUPE_UNIQUE + var/spam_flag = FALSE + +/datum/component/honkspam/Initialize() + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact) + +/datum/component/honkspam/proc/reset_spamflag() + spam_flag = FALSE + +/datum/component/honkspam/proc/interact(mob/user) + if(!spam_flag) + spam_flag = TRUE + var/obj/item/parent_item = parent + playsound(parent_item.loc, 'sound/items/bikehorn.ogg', 50, TRUE) + addtimer(CALLBACK(src, .proc/reset_spamflag), 2 SECONDS) diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm new file mode 100644 index 0000000000..c6d0c595eb --- /dev/null +++ b/code/datums/components/label.dm @@ -0,0 +1,87 @@ +/** + The label component. + + This component is used to manage labels applied by the hand labeler. + + Atoms can only have one instance of this component, and therefore only one label at a time. + This is to avoid having names like "Backpack (label1) (label2) (label3)". This is annoying and abnoxious to read. + + When a player clicks the atom with a hand labeler to apply a label, this component gets applied to it. + If the labeler is off, the component will be removed from it, and the label will be removed from its name. + */ +/datum/component/label + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The name of the label the player is applying to the parent. + var/label_name + +/datum/component/label/Initialize(_label_name) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + label_name = _label_name + apply_label() + +/datum/component/label/RegisterWithParent() + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackby) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/Examine) + +/datum/component/label/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE)) + +/** + This proc will fire after the parent is hit by a hand labeler which is trying to apply another label. + Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one. +*/ +/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, _label_name) + remove_label() + if(new_comp) + label_name = new_comp.label_name + else + label_name = _label_name + apply_label() + +/** + This proc will trigger when any object is used to attack the parent. + + If the attacking object is not a hand labeler, it will return. + If the attacking object is a hand labeler it will restore the name of the parent to what it was before this component was added to it, and the component will be deleted. + + Arguments: + * source: The parent. + * attacker: The object that is hitting the parent. + * user: The mob who is wielding the attacking object. +*/ +/datum/component/label/proc/OnAttackby(datum/source, obj/item/attacker, mob/user) + // If the attacking object is not a hand labeler or its mode is 1 (has a label ready to apply), return. + // The hand labeler should be off (mode is 0), in order to remove a label. + var/obj/item/hand_labeler/labeler = attacker + if(!istype(labeler) || labeler.mode) + return + + remove_label() + playsound(parent, 'sound/items/poster_ripped.ogg', 20, TRUE) + to_chat(user, "You remove the label from [parent].") + qdel(src) // Remove the component from the object. + +/** + This proc will trigger when someone examines the parent. + It will attach the text found in the body of the proc to the `examine_list` and display it to the player examining the parent. + + Arguments: + * source: The parent. + * user: The mob exmaining the parent. + * examine_list: The current list of text getting passed from the parent's normal examine() proc. +*/ +/datum/component/label/proc/Examine(datum/source, mob/user, list/examine_list) + examine_list += "It has a label with some words written on it. Use a hand labeler to remove it." + +/// Applies a label to the name of the parent in the format of: "parent_name (label)" +/datum/component/label/proc/apply_label() + var/atom/owner = parent + owner.name += " ([label_name])" + +/// Removes the label from the parent's name +/datum/component/label/proc/remove_label() + var/atom/owner = parent + owner.name = replacetext(owner.name, "([label_name])", "") // Remove the label text from the parent's name, wherever it's located. + owner.name = trim(owner.name) // Shave off any white space from the beginning or end of the parent's name. diff --git a/code/datums/components/ntnet_interface.dm b/code/datums/components/ntnet_interface.dm index 6159c7c2c4..06d69f0ce3 100644 --- a/code/datums/components/ntnet_interface.dm +++ b/code/datums/components/ntnet_interface.dm @@ -1,4 +1,4 @@ -//Thing meant for allowing datums and objects to access a NTnet network datum. +//Thing meant for allowing datums and objects to access an NTnet network datum. /datum/proc/ntnet_receive(datum/netdata/data) return diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm index ea1897b67d..c30da0614a 100644 --- a/code/datums/diseases/advance/symptoms/fire.dm +++ b/code/datums/diseases/advance/symptoms/fire.dm @@ -99,7 +99,6 @@ Bonus */ /datum/symptom/alkali - name = "Alkali perspiration" desc = "The virus attaches to sudoriparous glands, synthesizing a chemical that bursts into flames when reacting with water, leading to self-immolation." stealth = 2 @@ -113,9 +112,9 @@ Bonus symptom_delay_max = 90 var/chems = FALSE var/explosion_power = 1 - threshold_desc = "Resistance 9: Doubles the intensity of the effect, but reduces its frequency.
\ - Stage Speed 8: Increases explosion radius when the host is wet.
\ - Transmission 8: Additionally synthesizes chlorine trifluoride and napalm inside the host." + threshold_desc = list("Resistance 9" = "Doubles the intensity of the effect, but reduces its frequency.", + "Stage Speed 8" = "Increases explosion radius when the host is wet.", + "Transmission 8" = "Additionally synthesizes chlorine trifluoride and napalm inside the host.") /datum/symptom/alkali/Start(datum/disease/advance/A) if(!..()) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 9486029fdd..843ea06f74 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -132,7 +132,8 @@ L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len) L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) - L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) + L[DNA_LEFT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.left_eye_color) + L[DNA_RIGHT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.right_eye_color) L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6) L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6) L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6) @@ -224,8 +225,10 @@ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) if(DNA_SKIN_TONE_BLOCK) setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) - if(DNA_EYE_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) + if(DNA_LEFT_EYE_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.left_eye_color)) + if(DNA_RIGHT_EYE_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.right_eye_color)) if(DNA_GENDER_BLOCK) switch(H.gender) if(MALE) @@ -464,7 +467,8 @@ hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK)) facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) skin_tone = dna.skin_tone_override || GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] - eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) + left_eye_color = sanitize_hexcolor(getblock(structure, DNA_LEFT_EYE_COLOR_BLOCK)) + right_eye_color = sanitize_hexcolor(getblock(structure, DNA_RIGHT_EYE_COLOR_BLOCK)) facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)] hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)] if(icon_update) diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decal.dm index 50519b08e7..a20d46c813 100644 --- a/code/datums/elements/decal.dm +++ b/code/datums/elements/decal.dm @@ -32,6 +32,7 @@ RegisterSignal(A, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react) if(description) RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine) + RegisterSignal(A, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE) num_decals_per_atom[A]++ apply(A) @@ -39,21 +40,28 @@ /datum/element/decal/Detach(datum/target) var/atom/A = target num_decals_per_atom[A]-- - apply(A, TRUE) if(!num_decals_per_atom[A]) - UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS)) + UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, + COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS)) LAZYREMOVE(num_decals_per_atom, A) + apply(A) return ..() -/datum/element/decal/proc/apply(atom/target, removing = FALSE) - if(num_decals_per_atom[target] == 1 && !removing) - RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE) - target.update_icon() +/datum/element/decal/proc/apply(atom/target) + if(target.flags_1 & INITIALIZED_1) + target.update_icon() //could use some queuing here now maybe. + else if(!QDELETED(target) && num_decals_per_atom[target] == 1) + RegisterSignal(target, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, .proc/late_update_icon) if(isitem(target)) addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE) +/datum/element/decal/proc/late_update_icon(atom/source) + source.update_icon() + UnregisterSignal(source,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) + /datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list) - pic.dir = first_dir == NORTH ? source.dir : turn(first_dir, dir2angle(source.dir)) + if(first_dir) + pic.dir = first_dir == SOUTH ? source.dir : turn(first_dir, dir2angle(source.dir)-180) //Never turn a dir by 0. for(var/i in 1 to num_decals_per_atom[source]) overlay_list += pic diff --git a/code/datums/elements/flavor_text.dm b/code/datums/elements/flavor_text.dm index 3562345d26..ae139104f0 100644 --- a/code/datums/elements/flavor_text.dm +++ b/code/datums/elements/flavor_text.dm @@ -51,7 +51,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code LAZYREMOVE(GLOB.mobs_with_editable_flavor_text[M], src) if(!GLOB.mobs_with_editable_flavor_text[M]) GLOB.mobs_with_editable_flavor_text -= M - M.verbs -= /mob/proc/manage_flavor_tests + remove_verb(M, /mob/proc/manage_flavor_tests) /datum/element/flavor_text/proc/show_flavor(atom/target, mob/user, list/examine_list) if(!always_show && isliving(target)) diff --git a/code/datums/elements/polychromic.dm b/code/datums/elements/polychromic.dm index 1c438c86c5..7ae0d04b05 100644 --- a/code/datums/elements/polychromic.dm +++ b/code/datums/elements/polychromic.dm @@ -61,7 +61,7 @@ A.AddElement(/datum/element/update_icon_updates_onmob) RegisterSignal(A, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays) if(suits_with_helmet_typecache[A.type]) - RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet) + RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet) //you better work now you slut else if(_flags & POLYCHROMIC_ACTION && ismob(A)) //in the event mob update icon procs are ever standarized. var/datum/action/polychromic/P = new(A) RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action) @@ -166,6 +166,15 @@ examine_list += "Alt-click to recolor it." /datum/element/polychromic/proc/register_helmet(atom/source, obj/item/clothing/head/H) + if(!isitem(H)) //backup in case if it messes up somehow + if(istype(source,/obj/item/clothing/suit/hooded)) //so how come it be like this, where toggleable headslots are named separately (helmet/hood) anyways? + var/obj/item/clothing/suit/hooded/sourcesuit = source + H = sourcesuit.hood + else if(istype(source,/obj/item/clothing/suit/space/hardsuit)) + var/obj/item/clothing/suit/space/hardsuit/sourcesuit = source + H = sourcesuit.helmet + else + return suit_by_helmet[H] = source helmet_by_suit[source] = H colors_by_atom[H] = colors_by_atom[source] diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 6660bafcaf..e1147df225 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -102,8 +102,9 @@ /datum/emote/proc/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE) . = TRUE - if(!is_type_in_typecache(user, mob_type_allowed_typecache)) - return FALSE + if(mob_type_allowed_typecache) //empty list = anyone can use it unless specifically blacklisted + if(!is_type_in_typecache(user, mob_type_allowed_typecache)) + return FALSE if(is_type_in_typecache(user, mob_type_blacklist_typecache)) return FALSE if(status_check && !is_type_in_typecache(user, mob_type_ignore_stat_typecache)) diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index 1581323f89..bc48e82395 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -64,7 +64,7 @@ else if(make_temporary) base = H.mind.default_martial_art if(help_verb) - H.verbs += help_verb + add_verb(H, help_verb) H.mind.martial_art = src if(pugilist) ADD_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT) @@ -90,7 +90,7 @@ /datum/martial_art/proc/on_remove(mob/living/carbon/human/H) if(help_verb) - H.verbs -= help_verb + remove_verb(H, help_verb) return ///Gets called when a projectile hits the owner. Returning anything other than BULLET_ACT_HIT will stop the projectile from hitting the mob. diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 1469965b57..76e60bc6dc 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -35,23 +35,24 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.025 beauty_modifier = 0.075 -///Slight force increase +///Slight force decrease. It's gold, it's soft as fuck. /datum/material/gold name = "gold" desc = "Gold" color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium - strength_modifier = 1.2 + strength_modifier = 0.8 categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold value_per_unit = 0.0625 beauty_modifier = 0.15 armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 1.15, "energy" = 1.15, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1.1) -///Has no special properties +///Small force increase, for diamond swords /datum/material/diamond name = "diamond" desc = "Highly pressurized carbon" color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) + strength_modifier = 1.1 alpha = 132 categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond @@ -106,6 +107,7 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bluespace crystal" desc = "Crystals with bluespace properties" color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) + integrity_modifier = 0.2 //these things shatter when thrown. alpha = 200 categories = list(MAT_CATEGORY_ORE = TRUE) beauty_modifier = 0.5 @@ -139,7 +141,7 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "titanium" desc = "Titanium" color = "#b3c0c7" - strength_modifier = 1.3 + strength_modifier = 1.1 categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium value_per_unit = 0.0625 @@ -203,7 +205,7 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "adamantine" desc = "A powerful material made out of magic, I mean science!" color = "#6d7e8e" - strength_modifier = 1.5 + strength_modifier = 1.3 categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/adamantine value_per_unit = 0.25 @@ -276,16 +278,29 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Mir'ntrath barhah Nar'sie." color = "#3C3434" categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + strength_modifier = 1.2 sheet_type = /obj/item/stack/sheet/runed_metal value_per_unit = 0.75 armor_modifiers = list("melee" = 1.2, "bullet" = 1.2, "laser" = 1, "energy" = 1, "bomb" = 1.2, "bio" = 1.2, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) beauty_modifier = -0.15 texture_layer_icon_state = "runed" +/datum/material/brass + name = "brass" + desc = "Tybel gb-Ratvar" + color = "#917010" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + strength_modifier = 1.3 // Replicant Alloy is very good for skull beatings.. + sheet_type = /obj/item/stack/tile/brass + value_per_unit = 0.75 + armor_modifiers = list("melee" = 1.4, "bullet" = 1.4, "laser" = 0, "energy" = 0, "bomb" = 1.4, "bio" = 1.2, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) //But it has.. a few problems that can't easily be compensated for. + beauty_modifier = 0.3 //It really beats the cold plain plating of the station, doesn't it? + /datum/material/bronze name = "bronze" desc = "Clock Cult? Never heard of it." color = "#92661A" + strength_modifier = 1.1 categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/bronze value_per_unit = 0.025 diff --git a/code/datums/mind.dm b/code/datums/mind.dm index cb99fdc5a3..897e2e7d71 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -41,6 +41,8 @@ var/special_role var/list/restricted_roles = list() + var/hide_ckey = FALSE //hide ckey from round-end report + var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button. var/linglink @@ -69,6 +71,7 @@ ///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not var/mob/original_character + /datum/mind/New(var/key) skill_holder = new(src) src.key = key @@ -129,6 +132,7 @@ new_character.key = key //now transfer the key to link the client to our new body if(new_character.client) LAZYCLEARLIST(new_character.client.recent_examines) + new_character.client.init_verbs() // re-initialize character specific verbs current.update_atom_languages() //CIT CHANGE - makes arousal update when transfering bodies @@ -137,6 +141,8 @@ if(L.client?.prefs && L.client.prefs.auto_ooc && L.client.prefs.chat_toggles & CHAT_OOC) DISABLE_BITFIELD(L.client.prefs.chat_toggles,CHAT_OOC) + hide_ckey = current.client?.prefs?.hide_ckey + SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND) @@ -688,6 +694,7 @@ if(istype(S, spell)) spell_list -= S qdel(S) + current?.client << output(null, "statbrowser:check_spells") /datum/mind/proc/RemoveAllSpells() for(var/obj/effect/proc_holder/S in spell_list) @@ -780,6 +787,7 @@ if(!mind.name) mind.name = real_name mind.current = src + mind.hide_ckey = client?.prefs?.hide_ckey /mob/living/carbon/mind_initialize() ..() diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 38b004a657..1abe077980 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -204,6 +204,11 @@ mood_change = -1 timeout = 2 MINUTES +/datum/mood_event/plush_bite + description = "IT BIT ME!! OW!\n" + mood_change = -3 + timeout = 2 MINUTES + //Cursed stuff below /datum/mood_event/emptypred diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm index fb5f6ed5f6..3bddfdaa63 100644 --- a/code/datums/mutations/_mutations.dm +++ b/code/datums/mutations/_mutations.dm @@ -11,7 +11,7 @@ var/lowest_value = 256 * 8 var/text_gain_indication = "" var/text_lose_indication = "" - var/list/mutable_appearance/visual_indicators = list() + var/list/visual_indicators = list() var/obj/effect/proc_holder/spell/power var/layer_used = MUTATIONS_LAYER //which mutation layer to use var/list/species_allowed = list() //to restrict mutation to only certain species diff --git a/code/datums/skills/_skill_holder.dm b/code/datums/skills/_skill_holder.dm index 73748417c3..83c95c6439 100644 --- a/code/datums/skills/_skill_holder.dm +++ b/code/datums/skills/_skill_holder.dm @@ -110,7 +110,7 @@ /** * Automatic skill increase, multiplied by skill affinity if existing. - * Only works if skill is numerical. + * Only works if skill is numerical or levelled.. */ /datum/mind/proc/auto_gain_experience(skill, value, maximum, silent = FALSE) if(!ispath(skill, /datum/skill)) diff --git a/code/datums/skills/blacksmithing.dm b/code/datums/skills/blacksmithing.dm new file mode 100644 index 0000000000..0bddae5562 --- /dev/null +++ b/code/datums/skills/blacksmithing.dm @@ -0,0 +1,6 @@ +/datum/skill/level/dorfy/blacksmithing + name = "Blacksmithing" + desc = "Making metal into fancy shapes using heat and force. Higher levels increase both your working speed at an anvil as well as the quality of your works." + name_color = COLOR_FLOORTILE_GRAY + skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE, SKILL_USE_TOOL, SKILL_TRAINING_TOOL) + ui_category = SKILL_UI_CAT_MISC diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 179ed765c5..ef3979d822 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -580,4 +580,63 @@ /datum/status_effect/regenerative_core/on_remove() . = ..() REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, "regenerative_core") - owner.updatehealth() \ No newline at end of file + owner.updatehealth() + +/datum/status_effect/panacea + id = "Anatomic Panacea" + duration = 100 + tick_interval = 10 + alert_type = /obj/screen/alert/status_effect/panacea + +/obj/screen/alert/status_effect/panacea + name = "Panacea" + desc = "We purge the impurities from our body." + icon_state = "panacea" + +// Changeling's anatomic panacea now in buff form. Directly fixes issues instead of injecting chems +/datum/status_effect/panacea/tick() + var/mob/living/carbon/M = owner + + //Heal brain damage and toxyloss, alongside trauma + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -8) + owner.adjustToxLoss(-6, forced = TRUE) + M.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) + //Purges 50 rads per tick + if(owner.radiation > 0) + owner.radiation -= min(owner.radiation, 50) + //Mutadone effects + owner.jitteriness = 0 + if(owner.has_dna()) + M.dna.remove_all_mutations(mutadone = TRUE) + if(!QDELETED(owner)) //We were a monkey, now a human + ..() + // Purges toxins + for(var/datum/reagent/toxin/R in owner.reagents.reagent_list) + owner.reagents.remove_reagent(R.type, 5) + //Antihol effects + M.reagents.remove_all_type(/datum/reagent/consumable/ethanol, 10, 0, 1) + M.drunkenness = max(M.drunkenness - 10, 0) + owner.dizziness = 0 + owner.drowsyness = 0 + owner.slurring = 0 + owner.confused = 0 + //Organ and disease cure moved from panacea.dm to buff proc + var/list/bad_organs = list( + owner.getorgan(/obj/item/organ/body_egg), + owner.getorgan(/obj/item/organ/zombie_infection)) + for(var/o in bad_organs) + var/obj/item/organ/O = o + if(!istype(O)) + continue + O.Remove() + if(iscarbon(owner)) + var/mob/living/carbon/C = owner + C.vomit(0, toxic = TRUE) + O.forceMove(get_turf(owner)) + if(isliving(owner)) + var/mob/living/L = owner + for(var/thing in L.diseases) + var/datum/disease/D = thing + if(D.severity == DISEASE_SEVERITY_POSITIVE) + continue + D.cure() diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 9cd47403d1..a2f534115a 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -533,6 +533,38 @@ if(100) H.adjustOrganLoss(ORGAN_SLOT_BRAIN,20) +/datum/status_effect/corrosion_curse/lesser + id = "corrosion_curse_lesser" + duration = 20 SECONDS + +/datum/status_effect/corrosion_curse/lesser/tick() + . = ..() + if(!ishuman(owner)) + return + var/mob/living/carbon/human/H = owner + var/chance = rand(0,100) + switch(chance) + if(0 to 19) + H.adjustBruteLoss(6) + if(20 to 29) + H.Dizzy(10) + if(30 to 39) + H.adjustOrganLoss(ORGAN_SLOT_LIVER,2) + if(40 to 49) + H.adjustOrganLoss(ORGAN_SLOT_HEART,2) + if(50 to 59) + H.adjustOrganLoss(ORGAN_SLOT_STOMACH,2) + if(60 to 69) + H.adjustOrganLoss(ORGAN_SLOT_EYES,5) + if(70 to 79) + H.adjustOrganLoss(ORGAN_SLOT_EARS,5) + if(80 to 89) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS,5) + if(90 to 99) + H.adjustOrganLoss(ORGAN_SLOT_TONGUE,5) + if(100) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN,10) + /datum/status_effect/amok id = "amok" status_type = STATUS_EFFECT_REPLACE diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 68b5d6f987..322fba0a33 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -211,24 +211,27 @@ GLOBAL_LIST_EMPTY(family_heirlooms) H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE) /datum/quirk/paraplegic/on_spawn() - if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs. - quirk_holder.buckled.unbuckle_mob(quirk_holder) + if(quirk_holder.client) + var/modified_limbs = quirk_holder.client.prefs.modified_limbs + if(!(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !isjellyperson(quirk_holder))) + if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs. + quirk_holder.buckled.unbuckle_mob(quirk_holder) - var/turf/T = get_turf(quirk_holder) - var/obj/structure/chair/spawn_chair = locate() in T + var/turf/T = get_turf(quirk_holder) + var/obj/structure/chair/spawn_chair = locate() in T - var/obj/vehicle/ridden/wheelchair/wheels = new(T) - if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking - wheels.setDir(spawn_chair.dir) + var/obj/vehicle/ridden/wheelchair/wheels = new(T) + if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking + wheels.setDir(spawn_chair.dir) - wheels.buckle_mob(quirk_holder) + wheels.buckle_mob(quirk_holder) - // During the spawning process, they may have dropped what they were holding, due to the paralysis - // So put the things back in their hands. + // During the spawning process, they may have dropped what they were holding, due to the paralysis + // So put the things back in their hands. - for(var/obj/item/I in T) - if(I.fingerprintslast == quirk_holder.ckey) - quirk_holder.put_in_hands(I) + for(var/obj/item/I in T) + if(I.fingerprintslast == quirk_holder.ckey) + quirk_holder.put_in_hands(I) /datum/quirk/poor_aim name = "Poor Aim" @@ -244,42 +247,6 @@ GLOBAL_LIST_EMPTY(family_heirlooms) mob_trait = TRAIT_PROSOPAGNOSIA medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces." -/datum/quirk/prosthetic_limb - name = "Prosthetic Limb" - desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!" - value = -1 - var/slot_string = "limb" - -/datum/quirk/prosthetic_limb/on_spawn() - var/mob/living/carbon/human/H = quirk_holder - var/limb_slot - if(HAS_TRAIT(H, TRAIT_PARA))//Prevent paraplegic legs being replaced - limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) - else - limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot) - var/obj/item/bodypart/prosthetic - switch(limb_slot) - if(BODY_ZONE_L_ARM) - prosthetic = new/obj/item/bodypart/l_arm/robot/surplus(quirk_holder) - slot_string = "left arm" - if(BODY_ZONE_R_ARM) - prosthetic = new/obj/item/bodypart/r_arm/robot/surplus(quirk_holder) - slot_string = "right arm" - if(BODY_ZONE_L_LEG) - prosthetic = new/obj/item/bodypart/l_leg/robot/surplus(quirk_holder) - slot_string = "left leg" - if(BODY_ZONE_R_LEG) - prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(quirk_holder) - slot_string = "right leg" - prosthetic.replace_limb(H) - qdel(old_part) - H.regenerate_icons() - -/datum/quirk/prosthetic_limb/post_add() - to_chat(quirk_holder, "Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \ - you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.") - /datum/quirk/insanity name = "Reality Dissociation Syndrome" desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. This is not a license to grief." diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 179adf46bd..9af78b0090 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -71,7 +71,7 @@ /datum/wires/airlock/on_pulse(wire) set waitfor = FALSE var/obj/machinery/door/airlock/A = holder - if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) + if(usr && !A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) return FALSE switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power. @@ -127,7 +127,7 @@ /datum/wires/airlock/on_cut(wire, mend) var/obj/machinery/door/airlock/A = holder - if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) + if(usr && !A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) return FALSE switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power. diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 6ede0415da..593579c469 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -40,7 +40,7 @@ new_ai = select_active_ai(R) R.notify_ai(DISCONNECT) if(new_ai && (new_ai != R.connected_ai)) - R.connected_ai = new_ai + R.set_connected_ai(new_ai) if(R.shell) R.undeploy() //If this borg is an AI shell, disconnect the controlling AI and assign ti to a new AI R.notify_ai(AI_SHELL) @@ -69,7 +69,7 @@ R.notify_ai(DISCONNECT) if(R.shell) R.undeploy() - R.connected_ai = null + R.set_connected_ai(null) if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync. if(mend) if(!R.emagged) diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index cbad2f7ab0..5310b24202 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -43,6 +43,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station outdoors = TRUE ambientsounds = SPACE blob_allowed = FALSE //Eating up space doesn't count for victory as a blob. + considered_hull_exterior = TRUE /area/space/nearstation icon_state = "space_near" @@ -1592,4 +1593,4 @@ NOTE: there are two lists of areas in the end of this file: centcom and station valid_territory = FALSE outdoors = TRUE ambientsounds = SPACE - blob_allowed = FALSE //While part of the station, what good will it do you? \ No newline at end of file + blob_allowed = FALSE //While part of the station, what good will it do you? diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 672d5c096f..b9415f3cf8 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -34,6 +34,9 @@ /// If megafauna can be spawned by natural random generation var/megafauna_spawn_allowed = FALSE + /// Considered space for hull shielding + var/considered_hull_exterior = FALSE + var/fire = null var/atmos = TRUE var/atmosalm = FALSE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 8a66394ecc..684d29102b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1127,3 +1127,21 @@ */ /atom/proc/rust_heretic_act() return + +///Passes Stat Browser Panel clicks to the game and calls client click on an atom +/atom/Topic(href, list/href_list) + . = ..() + if(!usr?.client) + return + var/client/usr_client = usr.client + var/list/paramslist = list() + if(href_list["statpanel_item_shiftclick"]) + paramslist["shift"] = "1" + if(href_list["statpanel_item_ctrlclick"]) + paramslist["ctrl"] = "1" + if(href_list["statpanel_item_altclick"]) + paramslist["alt"] = "1" + if(href_list["statpanel_item_click"]) + // first of all make sure we valid + var/mouseparams = list2params(paramslist) + usr_client.Click(src, loc, null, mouseparams) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 659d50c077..eac7347479 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -6,10 +6,6 @@ GLOBAL_VAR_INIT(dynamic_latejoin_delay_max, (30 MINUTES)) GLOBAL_VAR_INIT(dynamic_midround_delay_min, (10 MINUTES)) GLOBAL_VAR_INIT(dynamic_midround_delay_max, (30 MINUTES)) -GLOBAL_VAR_INIT(dynamic_event_delay_min, (10 MINUTES)) -GLOBAL_VAR_INIT(dynamic_event_delay_max, (30 MINUTES)) // this is on top of regular events, so can't be quite as often - - // -- Roundstart injection delays GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_min, (2 MINUTES)) GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_max, (30 MINUTES)) @@ -58,7 +54,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) // Threat logging vars /// Starting threat level, for things that increase it but can bring it back down. var/initial_threat_level = 0 - /// Target threat level right now. Events and antags will try to keep the round at this level. + /// Target threat level right now. Antags will try to keep the round at this level. var/threat_level = 0 /// The current antag threat. Recalculated every time a ruletype starts or ends. var/threat = 0 @@ -80,8 +76,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) var/list/latejoin_rules = list() /// List of midround rules used for selecting the rules. var/list/midround_rules = list() - /// List of events used for reducing threat without causing antag injection (necessarily). - var/list/events = list() /** # Pop range per requirement. * If the value is five the range is: * 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+ @@ -119,8 +113,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) var/latejoin_injection_cooldown = 0 /// When world.time is over this number the mode tries to inject a midround ruleset. var/midround_injection_cooldown = 0 - /// When wor.dtime is over this number the mode tries to do an event. - var/event_injection_cooldown = 0 /// When TRUE GetInjectionChance returns 100. var/forced_injection = FALSE /// Forced ruleset to be executed for the next latejoin. @@ -184,7 +176,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) dat += "
Injection Timers: ([storyteller.get_injection_chance(TRUE)]% chance)
" dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)/10] seconds"] \[Now!\]
" dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)/10] seconds"] \[Now!\]
" - dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)/10] seconds"] \[Now!\]
" usr << browse(dat.Join(), "window=gamemode_panel;size=500x500") /datum/game_mode/dynamic/Topic(href, href_list) @@ -204,10 +195,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) var/threatadd = input("Specify how much threat to add (negative to subtract). This can inflate the threat level.", "Adjust Threat", 0) as null|num if(!threatadd) return - if(threatadd > 0) - create_threat(threatadd) - else - remove_threat(threatadd) + create_threat(threatadd) else if (href_list["injectlate"]) latejoin_injection_cooldown = 0 forced_injection = TRUE @@ -216,10 +204,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) midround_injection_cooldown = 0 forced_injection = TRUE message_admins("[key_name(usr)] forced a midround injection.", 1) - else if (href_list["forceevent"]) - event_injection_cooldown = 0 - // events always happen anyway - message_admins("[key_name(usr)] forced an event.", 1) else if (href_list["threatlog"]) show_threatlog(usr) else if (href_list["stacking_limit"]) @@ -377,8 +361,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) generate_threat() storyteller.start_injection_cooldowns() - SSevents.frequency_lower = storyteller.event_frequency_lower // 6 minutes by default - SSevents.frequency_upper = storyteller.event_frequency_upper // 20 minutes by default log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!") initial_threat_level = threat_level return TRUE @@ -397,9 +379,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) if ("Midround") if (ruleset.weight) midround_rules += ruleset - if("Event") - if(ruleset.weight) - events += ruleset for(var/mob/dead/new_player/player in GLOB.player_list) if(player.ready == PLAYER_READY_TO_PLAY && player.mind) roundstart_pop_ready++ @@ -596,8 +575,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) latejoin_rules = remove_from_list(latejoin_rules, rule.type) else if(rule.ruletype == "Midround") midround_rules = remove_from_list(midround_rules, rule.type) - else if(rule.ruletype == "Event") - events = remove_from_list(events,rule.type) addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_midround_latejoin_rule, rule), rule.delay) return TRUE @@ -706,17 +683,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null) picking_midround_latejoin_rule(drafted_rules) // get_injection_chance can do things on fail - if(event_injection_cooldown < world.time) - SSblackbox.record_feedback("tally","dynamic",1,"Attempted event injections") - event_injection_cooldown = storyteller.get_event_cooldown() + world.time - message_admins("DYNAMIC: Doing event injection.") - log_game("DYNAMIC: Doing event injection.") - update_playercounts() - var/list/drafted_rules = storyteller.event_draft() - if(drafted_rules.len > 0) - SSblackbox.record_feedback("tally","dynamic",1,"Successful event injections") - picking_midround_latejoin_rule(drafted_rules) - /// Updates current_players. /datum/game_mode/dynamic/proc/update_playercounts() current_players[CURRENT_LIVING_PLAYERS] = list() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm deleted file mode 100644 index 1ee226875b..0000000000 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm +++ /dev/null @@ -1,454 +0,0 @@ -/datum/dynamic_ruleset/event - ruletype = "Event" - var/typepath // typepath of the event - var/triggering - var/earliest_start = 20 MINUTES - -/datum/dynamic_ruleset/event/get_blackbox_info() - var/list/ruleset_data = list() - ruleset_data["name"] = name - ruleset_data["rule_type"] = ruletype - ruleset_data["cost"] = total_cost - ruleset_data["weight"] = weight - ruleset_data["scaled_times"] = scaled_times - ruleset_data["event_type"] = typepath - ruleset_data["population_tier"] = indice_pop - return ruleset_data - -/datum/dynamic_ruleset/event/execute() - var/datum/round_event/E = new typepath() - E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) - // E.control = src // can't be done! we just don't use events that require these, those can be from_ghost almost always - - testing("[time2text(world.time, "hh:mm:ss")] [E.type]") - deadchat_broadcast("[name] has just been triggered by dynamic!") - log_game("Random Event triggering: [name] ([typepath])") - - return E - -/datum/dynamic_ruleset/event/ready(forced = FALSE) - if (!forced) - if(earliest_start >= world.time-SSticker.round_start_time) - return FALSE - var/job_check = 0 - if (enemy_roles.len > 0) - for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS]) - if (M.stat == DEAD) - continue // Dead players cannot count as opponents - if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles)) - job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it - - var/threat = round(mode.threat_level/10) - if (job_check < required_enemies[threat]) - SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles") - return FALSE - return TRUE - -////////////////////////////////////////////// -// // -// PIRATES // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/pirates - name = "Space Pirates" - config_tag = "pirates" - typepath = /datum/round_event/pirates - antag_flag = ROLE_TRAITOR - enemy_roles = list("AI","Security Officer","Head of Security","Captain") - required_enemies = list(2,2,1,1,0,0,0,0,0,0) - weight = 5 - cost = 10 - earliest_start = 30 MINUTES - blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear) - requirements = list(70,60,50,50,40,40,40,30,20,15) - property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1) - high_population_requirement = 15 - -/datum/dynamic_ruleset/event/pirates/ready(forced = FALSE) - if (!SSmapping.empty_space) - return FALSE - return ..() - -////////////////////////////////////////////// -// // -// SPIDERS // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/spiders - name = "Spider Infestation" - config_tag = "spiders" - typepath = /datum/round_event/spider_infestation - enemy_roles = list("AI","Security Officer","Head of Security","Captain") - required_enemies = list(2,2,1,1,0,0,0,0,0,0) - weight = 5 - cost = 10 - requirements = list(70,60,50,50,40,40,40,30,20,15) - high_population_requirement = 15 - property_weights = list("chaos" = 1, "valid" = 1) - -////////////////////////////////////////////// -// // -// CLOGGED VENTS // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/ventclog - name = "Clogged Vents" - config_tag = "ventclog" - typepath = /datum/round_event/vent_clog - enemy_roles = list("Chemist","Medical Doctor","Chief Medical Officer") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - cost = 2 - weight = 4 - repeatable_weight_decrease = 3 - requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("chaos" = 1, "extended" = 2) - -/datum/dynamic_ruleset/event/ventclog/ready() - if(mode.threat_level > 30 && mode.threat >= 5 && prob(20)) - name = "Clogged Vents: Threatening" - cost = 5 - required_enemies = list(3,3,3,2,2,2,1,1,1,1) - typepath = /datum/round_event/vent_clog/threatening - else if(mode.threat_level > 15 && mode.threat > 15 && prob(30)) - name = "Clogged Vents: Catastrophic" - cost = 15 - required_enemies = list(2,2,1,1,1,1,0,0,0,0) - typepath = /datum/round_event/vent_clog/catastrophic - else - cost = 2 - name = "Clogged Vents: Normal" - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - typepath = /datum/round_event/vent_clog - return ..() - -////////////////////////////////////////////// -// // -// ION STORM // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/ion_storm - name = "Ion Storm" - config_tag = "ion_storm" - typepath = /datum/round_event/ion_storm - enemy_roles = list("Research Director","Captain","Chief Engineer") - required_enemies = list(1,1,0,0,0,0,0,0,0,0) - weight = 4 - // no repeatable weight decrease. too variable to be unfun multiple times in one round - cost = 1 - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("story_potential" = 1, "extended" = 1) - always_max_weight = TRUE - -////////////////////////////////////////////// -// // -// METEORS // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/meteor_wave - name = "Meteor Wave" - config_tag = "meteor_wave" - typepath = /datum/round_event/meteor_wave - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Captain","Cyborg") - required_enemies = list(3,3,3,3,3,3,3,3,3,3) - cost = 15 - weight = 3 - earliest_start = 25 MINUTES - repeatable_weight_decrease = 2 - requirements = list(60,50,40,30,30,30,30,30,30,30) - high_population_requirement = 30 - property_weights = list("extended" = -2) - -/datum/dynamic_ruleset/event/meteor_wave/ready() - if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30)) - name = "Meteor Wave: Threatening" - cost = 25 - typepath = /datum/round_event/meteor_wave/threatening - else if(world.time-SSticker.round_start_time > 45 MINUTES && mode.threat_level > 50 && mode.threat >= 40 && prob(30)) - name = "Meteor Wave: Catastrophic" - cost = 40 - typepath = /datum/round_event/meteor_wave/catastrophic - else - name = "Meteor Wave: Normal" - cost = 15 - typepath = /datum/round_event/meteor_wave - return ..() - -////////////////////////////////////////////// -// // -// ANOMALIES // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/anomaly_bluespace - name = "Anomaly: Bluespace" - config_tag = "anomaly_bluespace" - typepath = /datum/round_event/anomaly/anomaly_bluespace - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - weight = 2 - repeatable_weight_decrease = 1 - cost = 3 - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/anomaly_flux - name = "Anomaly: Hyper-Energetic Flux" - config_tag = "anomaly_flux" - typepath = /datum/round_event/anomaly/anomaly_flux - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - weight = 2 - repeatable_weight_decrease = 1 - cost = 5 - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 10 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/anomaly_gravitational - name = "Anomaly: Gravitational" - config_tag = "anomaly_gravitational" - typepath = /datum/round_event/anomaly/anomaly_grav - weight = 2 - repeatable_weight_decrease = 1 - cost = 3 - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/anomaly_pyroclastic - name = "Anomaly: Pyroclastic" - config_tag = "anomaly_pyroclastic" - typepath = /datum/round_event/anomaly/anomaly_pyro - weight = 2 - repeatable_weight_decrease = 1 - cost = 5 - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg") - required_enemies = list(1,1,1,1,1,1,1,1,1,1) - requirements = list(10,10,10,10,10,10,10,10,10,10) - high_population_requirement = 10 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/anomaly_vortex - name = "Anomaly: Vortex" - config_tag = "anomaly_vortex" - typepath = /datum/round_event/anomaly/anomaly_vortex - weight = 2 - repeatable_weight_decrease = 1 - cost = 5 - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg") - required_enemies = list(1,1,1,1,1,1,1,1,1,1) - requirements = list(10,10,10,10,10,10,10,10,10,10) - high_population_requirement = 10 - repeatable = TRUE - property_weights = list("extended" = 1) - -////////////////////////////////////////////// -// // -// WOW THAT'S A LOT OF EVENTS // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/event/brand_intelligence - name = "Brand Intelligence" - config_tag = "brand_intelligence" - typepath = /datum/round_event/brand_intelligence - weight = 1 - repeatable_weight_decrease = 1 - cost = 2 - enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg") - required_enemies = list(1,1,1,1,0,0,0,0,0,0) - requirements = list(10,10,10,10,10,10,10,10,10,10) - high_population_requirement = 10 - repeatable = TRUE - property_weights = list("extended" = -1, "chaos" = 1) - -/datum/dynamic_ruleset/event/carp_migration - name = "Carp Migration" - config_tag = "carp_migration" - typepath = /datum/round_event/carp_migration - weight = 7 - repeatable_weight_decrease = 3 - cost = 4 - requirements = list(10,10,10,10,10,10,10,10,10,10) - high_population_requirement = 10 - earliest_start = 10 MINUTES - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/communications_blackout - name = "Communications Blackout" - config_tag = "communications_blackout" - typepath = /datum/round_event/communications_blackout - cost = 4 - weight = 2 - repeatable_weight_decrease = 3 - enemy_roles = list("Chief Engineer","Station Engineer") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1, "chaos" = 1) - -/datum/dynamic_ruleset/event/processor_overload - name = "Processor Overload" - config_tag = "processor_overload" - typepath = /datum/round_event/processor_overload - cost = 4 - weight = 2 - repeatable_weight_decrease = 3 - enemy_roles = list("Chief Engineer","Station Engineer") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1, "chaos" = 1) - always_max_weight = TRUE - -/datum/dynamic_ruleset/event/space_dust - name = "Minor Space Dust" - config_tag = "space_dust" - typepath = /datum/round_event/space_dust - cost = 2 - weight = 2 - repeatable_weight_decrease = 1 - enemy_roles = list("Chief Engineer","Station Engineer") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - earliest_start = 0 MINUTES - property_weights = list("extended" = 1) - always_max_weight = TRUE - -/datum/dynamic_ruleset/event/major_dust - name = "Major Space Dust" - config_tag = "major_dust" - typepath = /datum/round_event/meteor_wave/major_dust - cost = 4 - weight = 2 - repeatable_weight_decrease = 1 - enemy_roles = list("Chief Engineer","Station Engineer") - required_enemies = list(2,2,2,2,2,2,2,2,2,2) - requirements = list(10,10,10,10,10,10,10,10,10,10) - high_population_requirement = 10 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/electrical_storm - name = "Electrical Storm" - config_tag = "electrical_storm" - typepath = /datum/round_event/electrical_storm - cost = 1 - weight = 2 - repeatable_weight_decrease = 1 - enemy_roles = list("Chief Engineer","Station Engineer") - required_enemies = list(1,1,1,0,0,0,0,0,0,0) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/heart_attack - name = "Random Heart Attack" - config_tag = "heart_attack" - typepath = /datum/round_event/heart_attack - cost = 3 - weight = 2 - repeatable_weight_decrease = 1 - enemy_roles = list("Medical Doctor","Chief Medical Officer") - required_enemies = list(2,2,2,2,2,2,2,2,2,2) - requirements = list(101,101,101,5,5,5,5,5,5,5) - high_population_requirement = 5 - repeatable = TRUE - property_weights = list("extended" = 1) - always_max_weight = TRUE - -/datum/dynamic_ruleset/event/radiation_storm - name = "Radiation Storm" - config_tag = "radiation_storm" - typepath = /datum/round_event/radiation_storm - cost = 3 - weight = 1 - enemy_roles = list("Chemist","Chief Medical Officer","Geneticist","Medical Doctor","AI","Captain") - required_enemies = list(1,1,1,1,1,1,1,1,1,1) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - property_weights = list("extended" = 1,"chaos" = 1) - -/datum/dynamic_ruleset/event/portal_storm_syndicate - name = "Portal Storm" - config_tag = "portal_storm" - typepath = /datum/round_event/portal_storm/syndicate_shocktroop - cost = 10 - weight = 1 - enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner") - required_enemies = list(2,2,2,2,2,2,2,2,2,2) - requirements = list(101,101,101,30,30,30,30,30,30,30) - high_population_requirement = 30 - earliest_start = 30 MINUTES - property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1) - -/datum/dynamic_ruleset/event/wormholes - name = "Wormholes" - config_tag = "wormhole" - typepath = /datum/round_event/wormholes - cost = 3 - weight = 4 - enemy_roles = list("AI","Medical Doctor","Station Engineer","Head of Personnel","Captain") - required_enemies = list(2,2,2,2,2,2,2,2,2,2) - requirements = list(5,5,5,5,5,5,5,5,5,5) - high_population_requirement = 5 - property_weights = list("extended" = 1) - -/datum/dynamic_ruleset/event/swarmers - name = "Swarmers" - config_tag = "swarmer" - typepath = /datum/round_event/spawn_swarmer - cost = 10 - weight = 1 - earliest_start = 30 MINUTES - enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer") - required_enemies = list(4,4,4,4,3,3,2,2,1,1) - requirements = list(101,101,101,101,101,101,101,101,101,101) - high_population_requirement = 5 - property_weights = list("extended" = -2) - -/datum/dynamic_ruleset/event/sentient_disease - name = "Sentient Disease" - config_tag = "sentient_disease" - typepath = /datum/round_event/ghost_role/sentient_disease - enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist") - required_enemies = list(2,1,1,1,0,0,0,0,0,0) - required_candidates = 1 - weight = 4 - cost = 5 - requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"! - property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2) - high_population_requirement = 5 - -/datum/dynamic_ruleset/event/revenant - name = "Revenant" - config_tag = "revenant" - typepath = /datum/round_event/ghost_role/revenant - enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI") - required_enemies = list(2,1,1,1,0,0,0,0,0,0) - required_candidates = 1 - weight = 4 - cost = 5 - requirements = list(30,30,30,30,20,15,15,15,15,15) - high_population_requirement = 15 - property_weights = list("story_potential" = -2, "extended" = -1) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 63574c6475..d2fa8bcc70 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -200,13 +200,15 @@ /datum/dynamic_ruleset/latejoin/heretic_smuggler name = "Heretic Smuggler" antag_datum = /datum/antagonist/heretic - antag_flag = ROLE_HERETIC + antag_flag = "latejoin_heretic" protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") restricted_roles = list("AI","Cyborg") required_candidates = 1 weight = 4 - cost = 10 - requirements = list(40,30,20,10,10,10,10,10,10,10) + cost = 25 + requirements = list(60,60,60,55,50,50,50,50,50,50) + high_population_requirement = 50 + property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2) repeatable = TRUE ////////////////////////////////////////////// diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 6a7671cd5b..b29584aa58 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -538,7 +538,7 @@ name = "Slaughter Demon" config_tag = "slaughter_demon" antag_flag = ROLE_ALIEN - enemy_roles = list("Security Officer","Shaft Miner","Head of Security","Captain","Janitor","AI","Cyborg") + enemy_roles = list("Security Officer","Shaft Miner","Head of Security","Captain","Janitor","AI","Cyborg","Bartender") required_enemies = list(3,2,2,2,2,1,1,1,1,0) required_candidates = 1 weight = 4 diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 766ddcefc7..db4ec99558 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -151,16 +151,18 @@ /datum/dynamic_ruleset/roundstart/heretics name = "Heretics" - antag_flag = ROLE_HERETIC + antag_flag = "heretic" antag_datum = /datum/antagonist/heretic protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain") restricted_roles = list("AI", "Cyborg") required_candidates = 1 weight = 3 - cost = 20 + cost = 25 scaling_cost = 15 - requirements = list(50,45,45,40,35,20,20,15,10,10) + requirements = list(60,60,60,55,50,50,50,50,50,50) + property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2) antag_cap = list(1,1,1,1,2,2,2,2,3,3) + high_population_requirement = 50 /datum/dynamic_ruleset/roundstart/heretics/pre_execute() diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 148de9568a..ed6cb0ba88 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -22,14 +22,14 @@ var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic. /** -Property weights are: +Property weights are added to the config weight of the ruleset. They are: "story_potential" -- essentially how many different ways the antag can be played. "trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this. "chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended". "valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights. "extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on. -"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason. +"conversion" -- Basically a bool. Conversion antags, well, convert. It's in its own class 'cause people kinda hate conversion. */ /datum/dynamic_storyteller/proc/start_injection_cooldowns() @@ -39,9 +39,6 @@ Property weights are: var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max) mode.midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time - var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min) - mode.event_injection_cooldown = (round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time) - /datum/dynamic_storyteller/proc/calculate_threat() var/threat = 0 for(var/datum/antagonist/A in GLOB.antagonists) @@ -99,10 +96,6 @@ Property weights are: var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min) return round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) -/datum/dynamic_storyteller/proc/get_event_cooldown() - var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min) - return round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) - /datum/dynamic_storyteller/proc/get_latejoin_cooldown() var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min) return round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max)) @@ -126,8 +119,9 @@ Property weights are: for(var/property in property_weights) if(property in rule.property_weights) // just treat it as 0 if it's not in there property_weight += rule.property_weights[property] * property_weights[property] - if(property_weight > 0) - drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult + var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult + if(calced_weight > 0) // negatives in the list might cause problems + drafted_rules[rule] = calced_weight return drafted_rules /datum/dynamic_storyteller/proc/midround_draft() @@ -144,21 +138,24 @@ Property weights are: for(var/property in property_weights) if(property in rule.property_weights) // just treat it as 0 if it's not in there property_weight += rule.property_weights[property] * property_weights[property] - if(property_weight > 0) - var/threat_weight = 1 - if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to - pick this particular ruleset. - Let's use a toy example: there's 60 threat level and 10 threat spent. - We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. - Ruleset 1 has 30 cost, ruleset 2 has 5 cost. - When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 - is 2.26 times as likely to be picked, all other things considered. - Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. - */ - threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) - drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight + var/threat_weight = 1 + if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway + var/cost_difference = rule.cost-(mode.threat_level-mode.threat) + /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to + pick this particular ruleset. + Let's use a toy example: there's 60 threat level and 10 threat spent. + We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. + Ruleset 1 has 30 cost, ruleset 2 has 5 cost. + When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 + is 2.26 times as likely to be picked, all other things considered. + Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. + */ + threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,abs(cost_difference),0))) + if(cost_difference > 0) + threat_weight /= (1+(cost_difference*0.1)) + var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult * threat_weight + if(calced_weight > 0) + drafted_rules[rule] = calced_weight return drafted_rules /datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer) @@ -180,27 +177,17 @@ Property weights are: for(var/property in property_weights) if(property in rule.property_weights) property_weight += rule.property_weights[property] * property_weights[property] - if(property_weight > 0) - var/threat_weight = 1 - if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) - drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight + var/threat_weight = 1 + if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) + var/cost_difference = rule.cost-(mode.threat_level-mode.threat) + threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,abs(cost_difference),0))) + if(cost_difference > 0) + threat_weight /= (1+(cost_difference*0.1)) + var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult * threat_weight + if(calced_weight > 0) + drafted_rules[rule] = calced_weight return drafted_rules -/datum/dynamic_storyteller/proc/event_draft() - var/list/drafted_rules = list() - for(var/datum/dynamic_ruleset/event/rule in mode.events) - if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level + 20 - mode.threat) >= rule.cost && rule.ready()) - var/property_weight = 0 - for(var/property in property_weights) - if(property in rule.property_weights) - property_weight += rule.property_weights[property] * property_weights[property] - if(property_weight > 0) - drafted_rules[rule] = rule.get_weight() + property_weight * rule.weight_mult - return drafted_rules - - /datum/dynamic_storyteller/chaotic name = "Chaotic" config_tag = "chaotic" @@ -263,9 +250,6 @@ Property weights are: /datum/dynamic_storyteller/random/get_midround_cooldown() return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2) -/datum/dynamic_storyteller/random/get_event_cooldown() - return rand(GLOB.dynamic_event_delay_min/2, GLOB.dynamic_event_delay_max*2) - /datum/dynamic_storyteller/random/get_latejoin_cooldown() return rand(GLOB.dynamic_latejoin_delay_min/2, GLOB.dynamic_latejoin_delay_max*2) @@ -311,13 +295,6 @@ Property weights are: drafted_rules[rule] = 1 return drafted_rules -/datum/dynamic_storyteller/random/event_draft() - var/list/drafted_rules = list() - for(var/datum/dynamic_ruleset/event/rule in mode.events) - if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && rule.ready()) - drafted_rules[rule] = 1 - return drafted_rules - /datum/dynamic_storyteller/story name = "Story" config_tag = "story" @@ -327,12 +304,6 @@ Property weights are: flags = USE_PREV_ROUND_WEIGHTS property_weights = list("story_potential" = 2) - -/datum/dynamic_storyteller/story/calculate_threat() - var/current_time = (world.time / SSautotransfer.targettime)*180 - mode.threat_level = round((mode.initial_threat_level*(sin(current_time)/2)+0.75),0.1) - return ..() - /datum/dynamic_storyteller/classic name = "Classic" config_tag = "classic" @@ -363,7 +334,7 @@ Property weights are: /datum/dynamic_storyteller/no_antag name = "Extended" config_tag = "semiextended" - desc = "No standard antags. Threatening events may still spawn." + desc = "No standard antags." curve_centre = -5 curve_width = 0.5 flags = NO_ASSASSIN | FORCE_IF_WON @@ -375,15 +346,3 @@ Property weights are: /datum/dynamic_storyteller/no_antag/get_injection_chance(dry_run) return 0 - -/datum/dynamic_storyteller/extended - name = "Super Extended" - config_tag = "extended" - desc = "No antags. No dangerous events." - curve_centre = -20 - weight = 0 - curve_width = 0.5 - -/datum/dynamic_storyteller/extended/on_start() - ..() - GLOB.dynamic_forced_extended = TRUE diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index cfb4c9a120..795508320b 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -112,7 +112,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event var/turf/T = get_turf(loc) ram_turf(T) - if(prob(10) && !isspaceturf(T))//randomly takes a 'hit' from ramming + if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming get_hit() /obj/effect/meteor/Destroy() @@ -136,7 +136,8 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event if(A) ram_turf(get_turf(A)) playsound(src.loc, meteorsound, 40, 1) - get_hit() + if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid)) + get_hit() /obj/effect/meteor/proc/ram_turf(turf/T) //first bust whatever is in the turf diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm index f08d84eae2..c8f1ef4713 100644 --- a/code/game/gamemodes/objective_sabotage.dm +++ b/code/game/gamemodes/objective_sabotage.dm @@ -56,7 +56,7 @@
  • There are many other ways; be creative!
  • \ " -/datum/sabotage_objective/processing/supermatter +/*/datum/sabotage_objective/processing/supermatter name = "Sabotage the supermatter so that it goes under 50% integrity. If it is delaminated, you will fail." sabotage_type = "supermatter" special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage) @@ -77,7 +77,7 @@ /datum/sabotage_objective/processing/supermatter/can_run() return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines) -/* + /datum/sabotage_objective/station_integrity name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal." sabotage_type = "integrity" diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index e97d276296..92ae0b764f 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -8,7 +8,8 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE) sandbox.owner = src.ckey if(src.client.holder) sandbox.admin = 1 - verbs += new/mob/proc/sandbox_panel + add_verb(src, /mob/proc/sandbox_panel) + /mob/proc/sandbox_panel() set name = "Sandbox Panel" if(sandbox) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 2b7411d03f..46b4bbe574 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -381,6 +381,7 @@ Class Procs: /obj/machinery/obj_break(damage_flag) if(!(flags_1 & NODECONSTRUCT_1)) stat |= BROKEN + return TRUE /obj/machinery/contents_explosion(severity, target) if(occupant) @@ -551,4 +552,4 @@ Class Procs: AM.pixel_y = -8 + (round( . / 3)*8) /obj/machinery/rust_heretic_act() - take_damage(500, BRUTE, "melee", 1) + take_damage(500, BRUTE, "melee", 1) diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm index fc99edd3eb..a6c98c6c9c 100644 --- a/code/game/machinery/computer/arcade/battle.dm +++ b/code/game/machinery/computer/arcade/battle.dm @@ -49,7 +49,6 @@ dat += "" var/datum/browser/popup = new(user, "arcade", "Space Villain 2000") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/arcade/battle/Topic(href, href_list) diff --git a/code/game/machinery/computer/arcade/minesweeper.dm b/code/game/machinery/computer/arcade/minesweeper.dm index ad325455ad..a9c9b5dfd9 100644 --- a/code/game/machinery/computer/arcade/minesweeper.dm +++ b/code/game/machinery/computer/arcade/minesweeper.dm @@ -178,9 +178,12 @@ table[y1][x1] += 10 if(href_list["same_board"]) //Reset the board... kinda if(game_status != MINESWEEPER_GAME_PLAYING) + mine_sound = TRUE game_status = MINESWEEPER_GAME_PLAYING if(table[y1][x1] >= 10) //If revealed, become unrevealed! - playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + if(mine_sound) + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + mine_sound = FALSE table[y1][x1] -= 10 if(table[y1][x1] > 10 && !reset_board) safe_squares_revealed += 1 diff --git a/code/game/machinery/computer/arcade/orion_trail.dm b/code/game/machinery/computer/arcade/orion_trail.dm index 8b81c69ed2..441010906c 100644 --- a/code/game/machinery/computer/arcade/orion_trail.dm +++ b/code/game/machinery/computer/arcade/orion_trail.dm @@ -160,7 +160,6 @@ dat += "

    Close

    " var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() return diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 74cceacd12..46d419a8fe 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -353,7 +353,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) dat = list("", header.Join(), body, "
    ") var/datum/browser/popup = new(user, "id_com", src.name, 900, 620) popup.set_content(dat.Join()) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/card/Topic(href, href_list) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 400ce041c7..2a05b359d8 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -276,7 +276,6 @@ var/datum/browser/popup = new(user, "cloning", "Cloning System Control") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/cloning/Topic(href, href_list) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 6a99b248e3..3ef887b156 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -1,3 +1,15 @@ +#define STATE_DEFAULT 1 +#define STATE_CALLSHUTTLE 2 +#define STATE_CANCELSHUTTLE 3 +#define STATE_MESSAGELIST 4 +#define STATE_VIEWMESSAGE 5 +#define STATE_DELMESSAGE 6 +#define STATE_STATUSDISPLAY 7 +#define STATE_ALERT_LEVEL 8 +#define STATE_CONFIRM_LEVEL 9 +#define STATE_TOGGLE_EMERGENCY 10 +#define STATE_PURCHASE 11 + // The communications computer /obj/machinery/computer/communications name = "communications console" @@ -6,6 +18,7 @@ icon_keyboard = "tech_key" req_access = list(ACCESS_HEADS) circuit = /obj/item/circuitboard/computer/communications + light_color = LIGHT_COLOR_BLUE var/auth_id = "Unknown" //Who is currently logged in? var/list/datum/comm_message/messages = list() var/datum/comm_message/currmsg @@ -16,22 +29,10 @@ var/ai_message_cooldown = 0 var/tmp_alertlevel = 0 var/static/security_level_cd // used to stop mass spam. - var/const/STATE_DEFAULT = 1 - var/const/STATE_CALLSHUTTLE = 2 - var/const/STATE_CANCELSHUTTLE = 3 - var/const/STATE_MESSAGELIST = 4 - var/const/STATE_VIEWMESSAGE = 5 - var/const/STATE_DELMESSAGE = 6 - var/const/STATE_STATUSDISPLAY = 7 - var/const/STATE_ALERT_LEVEL = 8 - var/const/STATE_CONFIRM_LEVEL = 9 - var/const/STATE_TOGGLE_EMERGENCY = 10 - var/const/STATE_PURCHASE = 11 var/stat_msg1 var/stat_msg2 - light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/communications/proc/checkCCcooldown() var/obj/item/circuitboard/computer/communications/CM = circuit @@ -46,7 +47,7 @@ /obj/machinery/computer/communications/Topic(href, href_list) if(..()) return - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, !issilicon(usr))) return if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") @@ -132,15 +133,20 @@ if("crossserver") if(authenticated==2) + var/dest = href_list["cross_dest"] if(!checkCCcooldown()) to_chat(usr, "Arrays recycling. Please stand by.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return - var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "") + var/warning = dest == "all" ? "Please choose a message to transmit to allied stations." : "Please choose a message to transmit to [dest] sector station." + var/input = stripped_multiline_input(usr, "[warning] Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "") if(!input || !(usr in view(1,src)) || !checkCCcooldown()) return playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - send2otherserver("[station_name()]", input,"Comms_Console") + if(dest == "all") + send2otherserver("[station_name()]", input,"Comms_Console") + else + send2otherserver("[station_name()]", input,"Comms_Console", list(dest)) minor_announce(input, title = "Outgoing message to allied station") usr.log_talk(input, LOG_SAY, tag="message to the other server") message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.") @@ -156,12 +162,12 @@ var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles if(S && istype(S)) if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE) - to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?") + to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?") return if(SSshuttle.shuttle_purchased) - to_chat(usr, "A replacement shuttle has already been purchased.") + to_chat(usr, "A replacement shuttle has already been purchased.") else if(!S.prerequisites_met()) - to_chat(usr, "You have not met the requirements for purchasing this shuttle.") + to_chat(usr, "You have not met the requirements for purchasing this shuttle.") else var/points_to_check var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) @@ -183,7 +189,7 @@ if("callshuttle") state = STATE_DEFAULT - if(authenticated) + if(authenticated && SSshuttle.canEvac(usr)) state = STATE_CALLSHUTTLE if("callshuttle2") if(authenticated) @@ -284,12 +290,12 @@ if("MessageCentCom") if(authenticated) if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") + to_chat(usr, "Arrays recycling. Please stand by.") return var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "") if(!input || !(usr in view(1,src)) || !checkCCcooldown()) return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) CentCom_announce(input, usr) to_chat(usr, "Message transmitted to Central Command.") for(var/client/X in GLOB.admins) @@ -302,7 +308,7 @@ // OMG SYNDICATE ...LETTERHEAD if("MessageSyndicate") - if((authenticated==2) && (obj_flags & EMAGGED)) + if((authenticated) && (obj_flags & EMAGGED)) if(!checkCCcooldown()) to_chat(usr, "Arrays recycling. Please stand by.") playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) @@ -332,7 +338,7 @@ if(!checkCCcooldown()) to_chat(usr, "Arrays recycling. Please stand by.") return - var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") + var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self-Destruct Code Request.","") if(!input || !(usr in view(1,src)) || !checkCCcooldown()) return Nuke_request(input, usr) @@ -347,7 +353,9 @@ aicurrmsg = null aistate = STATE_DEFAULT if("ai-callshuttle") - aistate = STATE_CALLSHUTTLE + aistate = STATE_DEFAULT + if(SSshuttle.canEvac(usr)) + aistate = STATE_CALLSHUTTLE if("ai-callshuttle2") SSshuttle.requestEvac(usr, href_list["call"]) aistate = STATE_DEFAULT @@ -460,9 +468,8 @@ var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src))) + if(issilicon(user)) var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access if(dat2) dat += dat2 @@ -493,9 +500,15 @@ if (authenticated==2) dat += "

    Captain Functions" dat += "
    \[ Make a Captain's Announcement \]" - var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server)) - if(cross_servers_count) - dat += "
    \[ Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""] \]" + var/list/cross_servers = CONFIG_GET(keyed_list/cross_server) + var/our_id = CONFIG_GET(string/cross_comms_name) + if(cross_servers.len) + for(var/server in cross_servers) + if(server == our_id) + continue + dat += "
    \[ Send a message to station in [server] sector. \]" + if(cross_servers.len > 2) + dat += "
    \[ Send a message to all allied stations \]" if(SSmapping.config.allow_custom_shuttles) dat += "
    \[ Purchase Shuttle \]" dat += "
    \[ Change Alert Level \]" @@ -721,8 +734,13 @@ to_chat(user, "Intercomms recharging. Please stand by.") return var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?") - if(!input || !user.canUseTopic(src)) + if(!input || !user.canUseTopic(src, !issilicon(usr))) return + if(!(user.can_speak())) //No more cheating, mime/random mute guy! + input = "..." + to_chat(user, "You find yourself unable to speak.") + else + input = user.treat_message(input) //Adds slurs and so on. Someone should make this use languages too. SScommunications.make_announcement(user, is_silicon, input) deadchat_broadcast("[user.real_name] made an priority announcement from [get_area_name(usr, TRUE)].", user) @@ -771,3 +789,15 @@ content = new_content if(new_possible_answers) possible_answers = new_possible_answers + +#undef STATE_DEFAULT +#undef STATE_CALLSHUTTLE +#undef STATE_CANCELSHUTTLE +#undef STATE_MESSAGELIST +#undef STATE_VIEWMESSAGE +#undef STATE_DELMESSAGE +#undef STATE_STATUSDISPLAY +#undef STATE_ALERT_LEVEL +#undef STATE_CONFIRM_LEVEL +#undef STATE_TOGGLE_EMERGENCY +#undef STATE_PURCHASE diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 286c106788..3d212ec0cb 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -217,9 +217,6 @@ // already discovered mutations stored_research = SSresearch.science_tech -/obj/machinery/computer/scan_consolenew/examine(mob/user) - . = ..() - /obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui) // Most of ui_interact is spent setting variables for passing to the tgui // interface. @@ -266,6 +263,10 @@ if(!ui) ui = new(user, src, "DnaConsole") ui.open() + +/obj/machinery/computer/scan_consolenew/ui_assets() + . = ..() || list() + . += get_asset_datum(/datum/asset/simple/genetics) /obj/machinery/computer/scan_consolenew/ui_data(mob/user) var/list/data = list() @@ -357,7 +358,7 @@ return data -/obj/machinery/computer/scan_consolenew/ui_act(action, var/list/params) +/obj/machinery/computer/scan_consolenew/ui_act(action, list/params) if(..()) return TRUE @@ -482,6 +483,7 @@ // Resolve mutation's BYOND path from the alias var/alias = params["alias"] var/path = GET_MUTATION_TYPE_FROM_ALIAS(alias) + // Make sure the occupant still has this mutation if(!(path in scanner_occupant.dna.mutation_index)) return diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index d8a5f856f1..4e99f67157 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -178,7 +178,6 @@ dat += "{Log In}" var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/med_data/Topic(href, href_list) diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 53f7cb7e32..ca64d538b9 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -67,7 +67,6 @@ add_fingerprint(usr) var/datum/browser/popup = new(user, "computer", title, 400, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/pod/process() diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm index 4b4b39740a..43aa978558 100644 --- a/code/game/machinery/computer/prisoner/management.dm +++ b/code/game/machinery/computer/prisoner/management.dm @@ -66,7 +66,6 @@ dat += "
    {Log Out}" var/datum/browser/popup = new(user, "computer", "Prisoner Management Console", 400, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 5c280eeace..844f14465a 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -250,7 +250,6 @@ dat += "{Log In}" var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() return diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index 82e8f46ab6..87b7159125 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -103,7 +103,6 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list) @@ -185,7 +184,6 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/telecrystals/boss/Topic(href, href_list) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 9330a30555..b48742d885 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -76,7 +76,6 @@ var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/cryopod/Topic(href, href_list) @@ -308,7 +307,7 @@ var/mob/living/mob_occupant = occupant var/list/obj/item/cryo_items = list() - + investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS) //Handle Borg stuff first @@ -356,23 +355,23 @@ cryo_items -= I //Update any existing objectives involving this mob. - for(var/datum/objective/O in GLOB.objectives) + for(var/i in GLOB.objectives) + var/datum/objective/O = i // We don't want revs to get objectives that aren't for heads of staff. Letting // them win or lose based on cryo is silly so we remove the objective. if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind) qdel(O) - else if(O.target && istype(O.target, /datum/mind)) - if(O.target == mob_occupant.mind) - if(O.owner && O.owner.current) - to_chat(O.owner.current, "
    You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!") - O.target = null - spawn(10) //This should ideally fire after the occupant is deleted. - if(!O) - return - O.find_target() - O.update_explanation_text() - if(!(O.target)) - qdel(O) + else if(O.target && istype(O.target, /datum/mind) && !O.check_completion()) + if(O.target == mob_occupant.mind && O.owner?.current) + to_chat(O.owner.current, "
    You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!") + O.target = null + spawn(10) //This should ideally fire after the occupant is deleted. + if(!O) + return + O.find_target() + O.update_explanation_text() + if(!(O.target)) + qdel(O) if(mob_occupant.mind) //Handle job slot/tater cleanup. diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 228c2e1f52..d88a9c9072 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -74,12 +74,6 @@ /obj/machinery/door/firedoor/Bumped(atom/movable/AM) if(panel_open || operating || welded) return - if(ismob(AM)) - var/mob/user = AM - if(density && !welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user))) - add_fingerprint(user) - open() - return TRUE return FALSE /obj/machinery/door/firedoor/power_change() @@ -90,14 +84,6 @@ stat |= NOPOWER /obj/machinery/door/firedoor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) - if(!welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user))) - add_fingerprint(user) - if(density) - emergency_close_timer = world.time + 30 // prevent it from instaclosing again if in space - open() - else - close() - return TRUE if(operating || !density) return diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm index f74de23171..8eebd779f4 100644 --- a/code/game/machinery/embedded_controller/access_controller.dm +++ b/code/game/machinery/embedded_controller/access_controller.dm @@ -260,7 +260,6 @@ /obj/machinery/doorButtons/airlock_controller/ui_interact(mob/user) var/datum/browser/popup = new(user, "computer", name) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.set_content(returnText()) popup.open() diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 6fd351bcff..5d0165189d 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -29,7 +29,6 @@ . = ..() user.set_machine(src) var/datum/browser/popup = new(user, "computer", name) // Set up the popup browser window - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.set_content(return_text()) popup.open() diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index a8fa31d5fb..0b89b117c4 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -38,3 +38,14 @@ if(stat & (BROKEN|NOPOWER)) return drive() + +/obj/machinery/mass_driver/pressure_plate + name = "pressure plated mass driver" + var/drive_delay = 10 + +/obj/machinery/mass_driver/pressure_plate/Crossed(atom/movable/O) + . = ..() + if(isliving(O)) + var/mob/living/L = O + to_chat(L, "You feel something click beneath you!") + addtimer(CALLBACK(src, .proc/drive), drive_delay) \ No newline at end of file diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 54d320e93b..8f7aee68ce 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -300,6 +300,7 @@ else to_chat(user, "You remove the turret but did not manage to salvage anything.") qdel(src) + return else if((istype(I, /obj/item/wrench)) && (!on)) if(raised) diff --git a/code/game/machinery/porta_turret/portable_turret_construct.dm b/code/game/machinery/porta_turret/portable_turret_construct.dm index 7c2000175e..2a73ee8d89 100644 --- a/code/game/machinery/porta_turret/portable_turret_construct.dm +++ b/code/game/machinery/porta_turret/portable_turret_construct.dm @@ -151,6 +151,7 @@ turret.installation = installed_gun.type turret.setup(installed_gun) qdel(src) + return else if(istype(I, /obj/item/crowbar)) I.play_tool_sound(src, 75) diff --git a/code/game/machinery/poweredfans/fan_assembly.dm b/code/game/machinery/poweredfans/fan_assembly.dm new file mode 100644 index 0000000000..651b3342ac --- /dev/null +++ b/code/game/machinery/poweredfans/fan_assembly.dm @@ -0,0 +1,100 @@ +/obj/machinery/fan_assembly + name = "fan assembly" + desc = "A basic microfan assembly." + icon = 'icons/obj/poweredfans.dmi' + icon_state = "mfan_assembly" + max_integrity = 150 + use_power = NO_POWER_USE + power_channel = ENVIRON + idle_power_usage = 0 + active_power_usage = 0 + layer = ABOVE_NORMAL_TURF_LAYER + anchored = FALSE + density = FALSE + CanAtmosPass = ATMOS_PASS_YES + stat = 1 + var/buildstacktype = /obj/item/stack/sheet/plasteel + var/buildstackamount = 5 + /* + 1 = Wrenched in place + 2 = Welded in place + 3 = Wires attached to it, this makes it change to the full thing. + */ + +/obj/machinery/fan_assembly/attackby(obj/item/W, mob/living/user, params) + switch(stat) + if(1) + // Stat 1 + if(istype(W, /obj/item/weldingtool)) + if(weld(W, user)) + to_chat(user, "You weld the fan assembly securely into place.") + setAnchored(TRUE) + stat = 2 + update_icon_state() + return + if(2) + // Stat 2 + if(istype(W, /obj/item/stack/cable_coil)) + if(!W.tool_start_check(user, amount=2)) + to_chat(user, "You need two lengths of cable to wire the fan assembly!") + return + to_chat(user, "You start to add wires to the assembly...") + if(W.use_tool(src, user, 30, volume=50, amount=2)) + to_chat(user, "You add wires to the fan assembly.") + stat = 3 + var/obj/machinery/poweredfans/F = new(loc, src) + forceMove(F) + F.setDir(src.dir) + return + else if(istype(W, /obj/item/weldingtool)) + if(weld(W, user)) + to_chat(user, "You unweld the fan assembly from its place.") + stat = 1 + update_icon_state() + setAnchored(FALSE) + return + return ..() + +/obj/machinery/fan_assembly/wrench_act(mob/user, obj/item/I) + if(stat != 1) + return FALSE + user.visible_message("[user] disassembles [src].", + "You start to disassemble [src]...", "You hear wrenching noises.") + if(I.use_tool(src, user, 30, volume=50)) + deconstruct() + return TRUE + +/obj/machinery/fan_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user) + if(!W.tool_start_check(user, amount=0)) + return FALSE + switch(stat) + if(1) + to_chat(user, "You start to weld \the [src]...") + if(2) + to_chat(user, "You start to unweld \the [src]...") + if(W.use_tool(src, user, 30, volume=50)) + return TRUE + return FALSE + +/obj/machinery/fan_assembly/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + new buildstacktype(loc,buildstackamount) + qdel(src) + +/obj/machinery/fan_assembly/examine(mob/user) + . = ..() + switch(stat) + if(1) + to_chat(user, "The fan assembly seems to be unwelded and loose.") + if(2) + to_chat(user, "The fan assembly seems to be welded, but missing wires.") + if(3) + to_chat(user, "The outer plating is wired firmly in place.") + +/obj/machinery/fan_assembly/update_icon_state() + . = ..() + switch(stat) + if(1) + icon_state = "mfan_assembly" + if(2) + icon_state = "mfan_welded" diff --git a/code/game/machinery/poweredfans/poweredfans.dm b/code/game/machinery/poweredfans/poweredfans.dm new file mode 100644 index 0000000000..3349a6894e --- /dev/null +++ b/code/game/machinery/poweredfans/poweredfans.dm @@ -0,0 +1,56 @@ +/obj/machinery/poweredfans + icon = 'icons/obj/poweredfans.dmi' + icon_state = "mfan_powered" + name = "micro powered fan" + desc = "A handmade fan, releasing a thin gust of air." + use_power = ACTIVE_POWER_USE + power_channel = ENVIRON + idle_power_usage = 5 + active_power_usage = 10 + max_integrity = 150 + layer = ABOVE_NORMAL_TURF_LAYER + anchored = TRUE + density = FALSE + CanAtmosPass = ATMOS_PASS_NO + var/obj/machinery/fan_assembly/assembly + +/obj/machinery/poweredfans/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(!assembly) + assembly = new() + assembly.forceMove(drop_location()) + assembly.stat = 2 + assembly.setAnchored(TRUE) + assembly.setDir(dir) + assembly = null + new /obj/item/stack/cable_coil(loc, 2) + qdel(src) + +/obj/machinery/poweredfans/wirecutter_act(mob/living/user, obj/item/I) + user.visible_message("[user] removes the wires from the [src].", + "You start to remove the wires from the [src]...", "You hear clanking and banging noises.") + if(I.use_tool(src, user, 30, volume=50)) + deconstruct() + return TRUE + +/obj/machinery/poweredfans/Initialize(mapload, obj/machinery/fan_assembly/FA) + . = ..() + if(FA) + assembly = FA + else + assembly = new(src) + assembly.stat = 3 + air_update_turf(1) + +/obj/machinery/poweredfans/power_change() + ..() + if(powered()) + icon_state = "mfan_powered" + CanAtmosPass = ATMOS_PASS_NO + air_update_turf(1) + else + icon_state = "mfan_unpowered" + CanAtmosPass = ATMOS_PASS_YES + air_update_turf(1) + update_icon_state() + diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index e1f55da551..2915c2f34b 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -218,10 +218,10 @@ GLOBAL_LIST_EMPTY(allConsoles) dat += "Message Authentication

    " dat += "Message for [dpt]: [message]

    " dat += "
    You may authenticate your message now by scanning your ID or your stamp

    " - + dat += "Validated by: [msgVerified ? "[msgVerified]" : "Not Validated"]
    " dat += "Stamped by: [msgStamped ? "[msgStamped]" : "Not Stamped"]

    " - + dat += "Send Message

    " dat += "<< Discard Message
    " @@ -271,7 +271,6 @@ GLOBAL_LIST_EMPTY(allConsoles) var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/requests_console/Topic(href, href_list) @@ -279,7 +278,7 @@ GLOBAL_LIST_EMPTY(allConsoles) return usr.set_machine(src) add_fingerprint(usr) - + if(href_list["write"]) dpt = ckey(reject_bad_text(href_list["write"])) //write contains the string of the receiving department's name var/new_message = stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN) @@ -358,7 +357,7 @@ GLOBAL_LIST_EMPTY(allConsoles) workingServer = TRUE if(!workingServer) - screen = 7 + screen = 7 say("NOTICE: No server detected! Please contact your local engineering team.") updateUsrDialog() return @@ -539,7 +538,7 @@ GLOBAL_LIST_EMPTY(allConsoles) to_chat(user, "You are not authorized to send announcements!") updateUsrDialog() return - + if(istype(O, /obj/item/stamp)) if(screen == 9) var/obj/item/stamp/T = O diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index 84b205b585..4740adaffb 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -132,7 +132,6 @@ var/datum/browser/popup = new(user, "slotmachine", "Slot Machine") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/slot_machine/Topic(href, href_list) diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index a2d4b9eb7e..8bca58a7de 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -100,7 +100,7 @@ // So he can't jump out the gate right away. R.SetLockdown() if(masterAI) - R.connected_ai = masterAI + R.set_connected_ai(masterAI) R.lawsync() R.lawupdate = 1 addtimer(CALLBACK(src, .proc/unlock_new_robot, R), 50) diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 40336fb01e..e2d3af149f 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -1,12 +1,10 @@ /obj/mecha/proc/get_armour_facing(relative_dir) switch(relative_dir) - if(0) // BACKSTAB! + if(180) // BACKSTAB! return facing_modifiers[BACK_ARMOUR] - if(45, 90, 270, 315) - return facing_modifiers[SIDE_ARMOUR] - if(225, 180, 135) + if(0, 45) // direct or 45 degrees off return facing_modifiers[FRONT_ARMOUR] - return 1 //always return non-0 + return facing_modifiers[SIDE_ARMOUR] //if its not a front hit or back hit then assume its from the side /obj/mecha/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() @@ -43,7 +41,7 @@ break if(attack_dir) - var/facing_modifier = get_armour_facing(dir2angle(attack_dir) - dir2angle(src)) + var/facing_modifier = get_armour_facing(abs(dir2angle(dir) - dir2angle(attack_dir))) booster_damage_modifier /= facing_modifier booster_deflection_modifier *= facing_modifier if(prob(deflect_chance * booster_deflection_modifier)) diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 41270bb09e..7e3a5205de 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -17,11 +17,15 @@ var/countdown_colour var/obj/effect/countdown/anomaly/countdown -/obj/effect/anomaly/Initialize(mapload, new_lifespan) + /// chance we drop a core when neutralized + var/core_drop_chance = 100 + +/obj/effect/anomaly/Initialize(mapload, new_lifespan, core_drop_chance = 100) . = ..() GLOB.poi_list |= src START_PROCESSING(SSobj, src) impact_area = get_area(src) + src.core_drop_chance = core_drop_chance if (!impact_area) return INITIALIZE_HINT_QDEL @@ -54,6 +58,8 @@ GLOB.poi_list.Remove(src) STOP_PROCESSING(SSobj, src) qdel(countdown) + if(aSignal) + QDEL_NULL(aSignal) return ..() /obj/effect/anomaly/proc/anomalyEffect() @@ -70,12 +76,12 @@ /obj/effect/anomaly/proc/anomalyNeutralize() new /obj/effect/particle_effect/smoke/bad(loc) - for(var/atom/movable/O in src) - O.forceMove(drop_location()) + if(prob(core_drop_chance)) + aSignal.forceMove(drop_location()) + aSignal = null qdel(src) - /obj/effect/anomaly/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed to_chat(user, "Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].") @@ -285,7 +291,7 @@ S.rabid = TRUE S.amount_grown = SLIME_EVOLUTION_THRESHOLD S.Evolve() - offer_control(S) + offer_control(S,POLL_IGNORE_SENTIENCE_POTION) ///////////////////// diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 25b262a146..5f312f2bf3 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -46,4 +46,5 @@ var/turf/T = loc if(!istype(T)) //you know this will happen somehow CRASH("Turf decal initialized in an object/nullspace") - T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha) + var/turn_dir = 180 - dir2angle(T.dir) //Turning a dir by 0 results in a roulette of random dirs. + T.AddElement(/datum/element/decal, icon, icon_state, turn_dir ? turn(dir, turn_dir) : dir, CLEAN_GOD, color, null, null, alpha) diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index c89e318714..07ffe8896e 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -242,7 +242,6 @@ RLD var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500, src) popup.set_content(t1) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/item/construction/rcd/Topic(href, href_list) diff --git a/code/game/objects/items/broom.dm b/code/game/objects/items/broom.dm index 225644109f..4cbd75ed94 100644 --- a/code/game/objects/items/broom.dm +++ b/code/game/objects/items/broom.dm @@ -28,39 +28,37 @@ /// triggered on wield of two handed item /obj/item/broom/proc/on_wield(obj/item/source, mob/user) to_chat(user, "You brace the [src] against the ground in a firm sweeping stance.") - RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/sweep) + RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, .proc/sweep) /// triggered on unwield of two handed item /obj/item/broom/proc/on_unwield(obj/item/source, mob/user) - UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) /obj/item/broom/afterattack(atom/A, mob/user, proximity) . = ..() if(!proximity) return - sweep(user, A, FALSE) + sweep(user, A) -/obj/item/broom/proc/sweep(mob/user, atom/A, moving = TRUE) - var/turf/target - if (!moving) - if (isturf(A)) - target = A - else - target = A.loc - else - target = user.loc - if (!isturf(target)) +/obj/item/broom/proc/sweep(datum/source, atom/newLoc) + if(!ismob(source) || !isturf(newLoc) || (get_dist(source, newLoc) > 1)) return - if (locate(/obj/structure/table) in target.contents) + var/turf/target = newLoc + var/atom/movable/AM + var/sweep_dir = get_dir(source, target) + if(!sweep_dir) return + for(var/i in target.contents) + AM = i + if(AM.density) // eh good enough heuristic check + return var/i = 0 for(var/obj/item/garbage in target.contents) if(!garbage.anchored) - garbage.Move(get_step(target, user.dir), user.dir) - i++ - if(i >= 20) + step(garbage, sweep_dir) + if(++i > 20) break - if(i >= 1) + if(i) playsound(loc, 'sound/weapons/thudswoosh.ogg', 30, TRUE, -1) /obj/item/broom/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) //bless you whoever fixes this copypasta diff --git a/code/game/objects/items/charter.dm b/code/game/objects/items/charter.dm index 5ed719ff94..9b658bc5f1 100644 --- a/code/game/objects/items/charter.dm +++ b/code/game/objects/items/charter.dm @@ -13,6 +13,7 @@ var/ignores_timeout = FALSE var/response_timer_id = null var/approval_time = 600 + var/allow_unicode = FALSE var/static/regex/standard_station_regex @@ -48,6 +49,9 @@ if(!new_name) return + if(!allow_unicode && (length(new_name) != length_char(new_name))) + to_chat(user, "Unicode is not allowed. Adminhelp if you want to use it so badly.") + return log_game("[key_name(user)] has proposed to name the station as \ [new_name]") diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 37d19783b5..8e59e91e38 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -390,7 +390,7 @@ /obj/item/circuitboard/machine/thermomachine/examine() . = ..() - . += "It is set to layer [pipe_layer]." + . += "It is set to layer [pipe_layer]. Use a Multitool on the circuit to change this." /obj/item/circuitboard/machine/thermomachine/heater name = "Heater (Machine Board)" @@ -1146,3 +1146,8 @@ build_path = /obj/machinery/atmospherics/components/unary/shuttle/heater req_components = list(/obj/item/stock_parts/micro_laser = 2, /obj/item/stock_parts/matter_bin = 1) + +/obj/item/circuitboard/machine/explosive_compressor + name = "Explosive Compressor (Machine Board)" + build_path = /obj/machinery/research/explosive_compressor + req_components = list(/obj/item/stock_parts/matter_bin = 3) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 7f8b720509..2a9944f770 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -735,7 +735,11 @@ if(isobj(target)) if(actually_paints) var/list/hsl = rgb2hsl(hex2num(copytext(paint_color,2,4)),hex2num(copytext(paint_color,4,6)),hex2num(copytext(paint_color,6,8))) - if(hsl[3] < 0.25 && !istype(target, /obj/structure/window) && !istype(target, /obj/effect/decal/cleanable/crayon)) //Colors too dark are rejected + var/static/whitelisted = typecacheof(list(/obj/structure/window, + /obj/effect/decal/cleanable/crayon, + /obj/machinery/door/window) + ) + if(hsl[3] < 0.25 && !whitelisted[target]) //Colors too dark are rejected to_chat(usr, "A color that dark on an object like this? Surely not...") return FALSE diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 767f8fc395..6396a4fe3d 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -394,8 +394,6 @@ to_chat(user, "[src] are recharging!") return - user.stop_pulling() //User has hands full, and we don't care about anyone else pulling on it, their problem. CLEAR!! - if(user.a_intent == INTENT_DISARM) do_disarm(M, user) return @@ -447,8 +445,7 @@ if(do_after(user, isnull(defib?.disarm_shock_time)? disarm_shock_time : defib.disarm_shock_time, target = M)) M.visible_message("[user] zaps [M] with [src]!", \ "[user] zaps [M] with [src]!") - M.adjustStaminaLoss(50) - M.DefaultCombatKnockdown(100) + M.DefaultCombatKnockdown(140) M.updatehealth() //forces health update before next life tick playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) M.emote("gasp") diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index ec68cdb40c..10b2b68646 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -266,7 +266,7 @@ GLOBAL_LIST_EMPTY(PDAs) var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda) assets.send(user) - var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/goonchat) + var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/chat) emoji_s.send(user) //Already sent by chat but no harm doing this user.set_machine(src) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 6eae9f127a..4ca0b86bc0 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -590,7 +590,7 @@ Code: var/static/list/emoji_icon_states var/static/emoji_table if(!emoji_table) - var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat) + var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) var/list/collate = list("
    ") for(var/emoji in sortList(icon_states(icon('icons/emoji.dmi')))) var/tag = sheet.icon_tag("emoji-[emoji]") diff --git a/code/game/objects/items/devices/portable_chem_mixer.dm b/code/game/objects/items/devices/portable_chem_mixer.dm new file mode 100644 index 0000000000..3e1b20cfc2 --- /dev/null +++ b/code/game/objects/items/devices/portable_chem_mixer.dm @@ -0,0 +1,206 @@ +/obj/item/storage/portable_chem_mixer + name = "Portable Chemical Mixer" + desc = "A portable device that dispenses and mixes chemicals. All necessary reagents need to be supplied with beakers. A label indicates that a screwdriver is required to open it for refills. This device can be worn on a belt. The letters 'S&T' are imprinted on the side." + icon = 'icons/obj/chemical.dmi' + icon_state = "portablechemicalmixer_open" + w_class = WEIGHT_CLASS_HUGE + slot_flags = ITEM_SLOT_BELT + custom_price = 2000 + custom_premium_price = 2000 + + var/obj/item/reagent_containers/beaker = null ///Creating an empty slot for a beaker that can be added to dispense into + var/amount = 30 ///The amount of reagent that is to be dispensed currently + + var/list/dispensable_reagents = list() ///List in which all currently dispensable reagents go + +/obj/item/storage/portable_chem_mixer/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_combined_w_class = 200 + STR.max_items = 50 + STR.insert_preposition = "in" + STR.can_hold = typecacheof(list( + /obj/item/reagent_containers/glass/beaker, + )) + +/obj/item/storage/portable_chem_mixer/Destroy() + QDEL_NULL(beaker) + return ..() + +/obj/item/storage/portable_chem_mixer/ex_act(severity, target) + if(severity < 3) + ..() + +/obj/item/storage/portable_chem_mixer/attackby(obj/item/I, mob/user, params) + var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + if (I.tool_behaviour == TOOL_SCREWDRIVER) + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked) + if (!locked) + update_contents() + if (locked) + replace_beaker(user) + update_icon() + I.play_tool_sound(src, 50) + return + + else if (istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container() && locked) + var/obj/item/reagent_containers/B = I + . = TRUE //no afterattack + if(!user.transferItemToLoc(B, src)) + return + replace_beaker(user, B) + update_icon() + updateUsrDialog() + return + + return ..() + +/** + * Updates the contents of the portable chemical mixer + * + * A list of dispensable reagents is created by iterating through each source beaker in the portable chemical beaker and reading its contents + */ +/obj/item/storage/portable_chem_mixer/proc/update_contents() + dispensable_reagents.Cut() + + for (var/obj/item/reagent_containers/glass/beaker/B in contents) + var/key = B.reagents.get_master_reagent_id() + if (!(key in dispensable_reagents)) + dispensable_reagents[key] = list() + dispensable_reagents[key]["reagents"] = list() + dispensable_reagents[key]["reagents"] += B.reagents + + return + +/obj/item/storage/portable_chem_mixer/update_icon_state() + var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + if (!locked) + icon_state = "portablechemicalmixer_open" + else if (beaker) + icon_state = "portablechemicalmixer_full" + else + icon_state = "portablechemicalmixer_empty" + + +/obj/item/storage/portable_chem_mixer/AltClick(mob/living/user) + var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + if (!locked) + return ..() + if(!can_interact(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + replace_beaker(user) + update_icon() + +/** + * Replaces the beaker of the portable chemical mixer with another beaker, or simply adds the new beaker if none is in currently + * + * Checks if a valid user and a valid new beaker exist and attempts to replace the current beaker in the portable chemical mixer with the one in hand. Simply places the new beaker in if no beaker is currently loaded + * Arguments: + * * mob/living/user - The user who is trying to exchange beakers + * * obj/item/reagent_containers/new_beaker - The new beaker that the user wants to put into the device + */ +/obj/item/storage/portable_chem_mixer/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(!user) + return FALSE + if(beaker) + user.put_in_hands(beaker) + beaker = null + if(new_beaker) + beaker = new_beaker + return TRUE + +/obj/item/storage/portable_chem_mixer/attack_hand(mob/user) + if (loc != user) + return ..() + if(SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)) + INVOKE_ASYNC(src, /datum.proc/ui_interact, user) + +/obj/item/storage/portable_chem_mixer/attack_self(mob/user) + if(loc == user) + var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) + if (locked) + ui_interact(user) + return + else + to_chat(user, "The portable chemical mixer is currently open and its contents can be accessed.") + return + return + +/obj/item/storage/portable_chem_mixer/MouseDrop(obj/over_object) + . = ..() + if(ismob(loc)) + var/mob/M = loc + if(!M.incapacitated() && istype(over_object, /obj/screen/inventory/hand)) + var/obj/screen/inventory/hand/H = over_object + M.putItemFromInventoryInHandIfPossible(src, H.held_index) + +/obj/item/storage/portable_chem_mixer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableChemMixer", name) + if(user.hallucinating()) + // to not ruin the immersion by constantly changing the fake chemicals + ui.set_autoupdate(FALSE) + ui.open() + +/obj/item/storage/portable_chem_mixer/ui_data(mob/user) + var/list/data = list() + data["amount"] = amount + data["isBeakerLoaded"] = beaker ? 1 : 0 + data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null + data["beakerMaxVolume"] = beaker ? beaker.volume : null + data["beakerTransferAmounts"] = beaker ? beaker.possible_transfer_amounts : null + var/chemicals[0] + var/is_hallucinating = user.hallucinating() + if(user.hallucinating()) + is_hallucinating = TRUE + for(var/re in dispensable_reagents) + var/value = dispensable_reagents[re] + var/datum/reagent/temp = GLOB.chemical_reagents_list[re] + if(temp) + var/chemname = temp.name + var/total_volume = 0 + for (var/datum/reagents/rs in value["reagents"]) + total_volume += rs.total_volume + if(is_hallucinating && prob(5)) + chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" + chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "volume" = total_volume ))) + data["chemicals"] = chemicals + var/beakerContents[0] + if(beaker) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume))) // list in a list because Byond merges the first list... + data["beakerContents"] = beakerContents + return data + +/obj/item/storage/portable_chem_mixer/ui_act(action, params) + if(..()) + return + switch(action) + if("amount") + var/target = text2num(params["target"]) + amount = target + . = TRUE + if("dispense") + var/reagent_name = params["reagent"] + var/datum/reagent/reagent = GLOB.name2reagent[reagent_name] + var/entry = dispensable_reagents[reagent] + if(beaker) + var/datum/reagents/R = beaker.reagents + var/actual = min(amount, 1000, R.maximum_volume - R.total_volume) + // todo: add check if we have enough reagent left + for (var/datum/reagents/source in entry["reagents"]) + var/to_transfer = min(source.total_volume, actual) + source.trans_to(beaker, to_transfer) + actual -= to_transfer + if (actual <= 0) + break + . = TRUE + if("remove") + var/amount = text2num(params["amount"]) + beaker.reagents.remove_all(amount) + . = TRUE + if("eject") + replace_beaker(usr) + update_icon() + . = TRUE diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index e65325587c..c51edc8106 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -16,9 +16,6 @@ var/on = TRUE var/shock_cooldown = FALSE - var/ui_x = 260 - var/ui_y = 137 - /obj/item/electropack/suicide_act(mob/living/carbon/user) user.visible_message("[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!") return (FIRELOSS) @@ -201,17 +198,7 @@ else return ..() -/obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey - var/dat = {" - -Frequency/Code for shock collar:
    -Frequency: -[format_frequency(src.frequency)] -Set
    -Code: -[src.code] -Set
    -
    "} - user << browse(dat, "window=radio") - onclose(user, "radio") - return +/obj/item/electropack/ui_act(action, params) + if(action == "power") // DO. NOT. + return FALSE + return ..() diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index fae2833c8a..db29614f20 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -718,8 +718,9 @@ GENETICS SCANNER to_chat(user, "Pressure: [round(pressure,0.01)] kPa") for(var/id in air_contents.get_gases()) - var/gas_concentration = air_contents.get_moles(id)/total_moles - to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") + if(air_contents.get_moles(id) >= 0.005) + var/gas_concentration = air_contents.get_moles(id)/total_moles + to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") to_chat(user, "Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") else @@ -729,10 +730,10 @@ GENETICS SCANNER to_chat(user, "[target] is empty!") if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected - var/fusion_power = round(cached_scan_results["fusion"], 0.01) - var/tier = fusionpower2text(fusion_power) + var/instability = round(cached_scan_results["fusion"], 0.01) + var/tier = instability2text(instability) to_chat(user, "Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.") - to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") + to_chat(user, "Instability of the last fusion reaction: [instability]\n This indicates it was [tier].") return /obj/item/analyzer/proc/scan_turf(mob/user, turf/location) @@ -783,10 +784,10 @@ GENETICS SCANNER to_chat(user, "Temperature: [round(environment.return_temperature()-T0C, 0.01)] °C ([round(environment.return_temperature(), 0.01)] K)") if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected - var/fusion_power = round(cached_scan_results["fusion"], 0.01) - var/tier = fusionpower2text(fusion_power) + var/instability = round(cached_scan_results["fusion"], 0.01) + var/tier = instability2text(instability) to_chat(user, "Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.") - to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") + to_chat(user, "Instability of the last fusion reaction: [instability]\n This indicates it was [tier].") /obj/item/analyzer/ranged desc = "A hand-held scanner which uses advanced spectroscopy and infrared readings to analyze gases as a distance. Alt-Click to use the built in barometer function." @@ -992,4 +993,4 @@ GENETICS SCANNER #undef SCANMODE_CHEMICAL #undef SCANMODE_WOUND #undef SCANNER_CONDENSED -#undef SCANNER_VERBOSE \ No newline at end of file +#undef SCANNER_VERBOSE diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 32d9c02a27..8b0d46be44 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -289,3 +289,9 @@ . = TRUE update_icon() + +/** + * Returns if this is ready to be detonated. Checks if both tanks are in place. + */ +/obj/item/transfer_valve/proc/ready() + return tank_one && tank_two diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index cf5c3d4fc5..6cf6a524de 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -26,6 +26,7 @@ wound_bonus = -110 bare_wound_bonus = 20 block_parry_data = /datum/block_parry_data/dual_esword + block_chance = 60 var/hacked = FALSE /// Can this reflect all energy projectiles? var/can_reflect = TRUE @@ -38,7 +39,8 @@ var/wielded = FALSE // track wielded status on item var/slowdown_wielded = 0 -/datum/block_parry_data/dual_esword +/datum/block_parry_data/dual_esword // please run at the man going apeshit with his funny doublesword + can_block_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST | BLOCK_DIR_WEST | BLOCK_DIR_EAST block_damage_absorption = 2 block_damage_multiplier = 0.15 block_damage_multiplier_override = list( @@ -50,10 +52,10 @@ block_lock_sprinting = TRUE // no attacking while blocking block_lock_attacking = TRUE - block_projectile_mitigation = 75 + block_projectile_mitigation = 85 // more efficient vs projectiles block_stamina_efficiency_override = list( - TEXT_ATTACK_TYPE_PROJECTILE = 4 + TEXT_ATTACK_TYPE_PROJECTILE = 6 ) parry_time_windup = 0 diff --git a/code/game/objects/items/implants/implant_hijack.dm b/code/game/objects/items/implants/implant_hijack.dm index 5dd610059c..36e58d8887 100644 --- a/code/game/objects/items/implants/implant_hijack.dm +++ b/code/game/objects/items/implants/implant_hijack.dm @@ -7,7 +7,8 @@ activated = 1 var/toggled = FALSE icon_state = "hijack" - var/eye_color + var/left_eye_color + var/right_eye_color var/stealthmode = FALSE var/stealthcooldown = 0 var/hijacking = FALSE @@ -25,8 +26,10 @@ return var/on = toggled && !stealthmode var/mob/living/carbon/human/H = imp_in - H.eye_color = on ? "ff0" : eye_color - H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK) + H.left_eye_color = on ? "ff0" : left_eye_color + H.right_eye_color = on ? "ff0" : right_eye_color + H.dna.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK) + H.dna.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK) H.update_body() /obj/item/implant/hijack/implant(mob/living/target, mob/user, silent = FALSE) @@ -34,7 +37,8 @@ ADD_TRAIT(target, TRAIT_HIJACKER, "implant") if (ishuman(target)) var/mob/living/carbon/human/H = target - eye_color = H.eye_color + left_eye_color = H.left_eye_color + right_eye_color = H.right_eye_color return TRUE /obj/item/implant/hijack/removed(mob/living/source, silent = FALSE, special = 0) @@ -49,7 +53,8 @@ apc.update_icon() if (ishuman(source)) var/mob/living/carbon/human/H = source - H.eye_color = eye_color + H.left_eye_color = left_eye_color + H.right_eye_color = left_eye_color return TRUE /obj/item/implant/hijack/proc/InterceptClickOn(mob/living/user,params,atom/object) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 01d2924a90..52ff0f740e 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -234,6 +234,9 @@ /obj/item/melee/rapier/attack(mob/living/target, mob/living/user) . = ..() if(iscarbon(target)) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + visible_message("[user] gently taps [target] with [src].",null,null,COMBAT_MESSAGE_RANGE) + log_combat(user, target, "slept", src) var/mob/living/carbon/H = target H.Dizzy(10) H.adjustStaminaLoss(30) diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm index 6f1aec287b..7e14fb9d35 100644 --- a/code/game/objects/items/miscellaneous.dm +++ b/code/game/objects/items/miscellaneous.dm @@ -255,7 +255,7 @@ /obj/item/choice_beacon/box/plushie/generate_display_names() var/list/plushie_list = list() //plushie set 1: just subtypes of /obj/item/toy/plush - var/list/plushies_set_one = subtypesof(/obj/item/toy/plush) - list(/obj/item/toy/plush/narplush, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random_snowflake, /obj/item/toy/plush/random) //don't allow these special ones (you can still get narplush/hugbox) + var/list/plushies_set_one = subtypesof(/obj/item/toy/plush) - list(/obj/item/toy/plush/narplush, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random_snowflake, /obj/item/toy/plush/plushling, /obj/item/toy/plush/random) //don't allow these special ones (you can still get narplush/hugbox) for(var/V in plushies_set_one) var/atom/A = V plushie_list[initial(A.name)] = A @@ -272,4 +272,3 @@ icon_state = "skub" w_class = WEIGHT_CLASS_BULKY attack_verb = list("skubbed") - diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index a3da49ed89..9a8f1214f0 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -167,7 +167,7 @@ return log_game("[key_name(user)] activated a hidden grenade in [src].") grenade.preprime(user, msg = FALSE, volume = 10) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushpet", /datum/mood_event/plushpet) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushpet", /datum/mood_event/plushpet) else to_chat(user, "You try to pet [src], but it has no stuffing. Aww...") SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plush_nostuffing", /datum/mood_event/plush_nostuffing) @@ -688,18 +688,6 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) icon_state = "scrubpuppy" item_state = "scrubpuppy" -/obj/item/toy/plush/borgplushie/meddrake - name = "MediDrake Plushie" - desc = "An adorable stuffed toy of a Medidrake." - icon_state = "meddrake" - item_state = "meddrake" - -/obj/item/toy/plush/borgplushie/secdrake - name = "SecDrake Plushie" - desc = "An adorable stuffed toy of a Secdrake." - icon_state = "secdrake" - item_state = "secdrake" - /obj/item/toy/plush/aiplush name = "AI plushie" desc = "A little stuffed toy AI core... it appears to be malfunctioning." @@ -766,8 +754,8 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) attack_verb = list("headbutt", "scritched", "bit") squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1) can_random_spawn = FALSE - - + + /obj/item/toy/plush/hairball name = "Hairball" desc = "A bundle of undigested fibers and scales. Yuck." @@ -777,3 +765,78 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) squeak_override = list('sound/misc/splort.ogg'=1) attack_verb = list("sploshed", "splorted", "slushed") can_random_spawn = FALSE + +/obj/item/toy/plush/plushling + name = "peculiar plushie" + desc = "An adorable stuffed toy- wait, did it just move?" + can_random_spawn = FALSE + var/absorb_cooldown = 100 //ticks cooldown between absorbs + var/next_absorb = 0 //When can it absorb another plushie + var/check_interval = 20 + var/next_check = 0 + +//Overrides parent proc +/obj/item/toy/plush/plushling/attack_self(mob/user) + if(!user) //hmmmmm + return + to_chat(user, "You try to pet the plushie, but recoil as it bites your hand instead! OW!") + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plush_bite", /datum/mood_event/plush_bite) + var/mob/living/carbon/human/H = user + if(!H) + return //Type safety. + H.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + addtimer(CALLBACK(H, /mob/living/carbon/human.proc/dropItemToGround, src, TRUE), 1) + +/obj/item/toy/plush/plushling/New() + var/initial_state = pick("plushie_lizard", "plushie_snake", "plushie_slime", "fox") + icon_state = initial_state + item_state = initial_state + START_PROCESSING(SSobj, src) + . = ..() + +/obj/item/toy/plush/plushling/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/toy/plush/plushling/process() + if(world.time < next_absorb || world.time < next_check) + return + next_check = world.time + check_interval + var/obj/item/toy/plush/target + for(var/obj/item/toy/plush/possible_target in loc) //First, it tries to get anything in its same location, be it a tile or a backpack + if(possible_target == src || istype(possible_target, /obj/item/toy/plush/plushling)) + continue + target = possible_target + break + if(!target) + if(!isturf(loc)) + return + for(var/obj/item/toy/plush/P in oview(1, src)) //If that doesn't work, it hunts for plushies adjacent to its own tile + if(istype(P, /obj/item/toy/plush/plushling)) //These do not hunt their own kind + continue + src.throw_at(P, 1, 2) + visible_message("[src] leaps at [P]!") + break + return + if(istype(target, /obj/item/toy/plush/plushling)) //These do not consume their own. + return + next_absorb = world.time + absorb_cooldown + plushie_absorb(target) + +/obj/item/toy/plush/plushling/proc/plushie_absorb(obj/item/toy/plush/victim) + if(!victim) + return + visible_message("[src] gruesomely mutilliates [victim], leaving nothing more than dust!") + name = victim.name + desc = victim.desc + " Wait, did it just move..?" + icon_state = victim.icon_state + item_state = victim.item_state + squeak_override = victim.squeak_override + attack_verb = victim.attack_verb + new /obj/effect/decal/cleanable/ash(get_turf(victim)) + qdel(victim) + +/obj/item/toy/plush/plushling/love(obj/item/toy/plush/Kisser, mob/living/user) //You shouldn't have come here, poor plush. + if(!Kisser) + return + plushie_absorb(Kisser) diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 6621095b72..a9cd4c33a7 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -281,12 +281,12 @@ O.custom_name = created_name O.locked = panel_locked if(!aisync) - lawsync = 0 - O.connected_ai = null + lawsync = FALSE + O.set_connected_ai(null) else O.notify_ai(NEW_BORG) if(forced_ai) - O.connected_ai = forced_ai + O.set_connected_ai(forced_ai) if(!lawsync) O.lawupdate = 0 if(M.laws.id == DEFAULT_AI_LAWID) @@ -337,10 +337,10 @@ if(!aisync) lawsync = FALSE - O.connected_ai = null + O.set_connected_ai(null) else if(forced_ai) - O.connected_ai = forced_ai + O.set_connected_ai(forced_ai) O.notify_ai(AI_SHELL) if(!lawsync) O.lawupdate = FALSE diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 7ba2196184..a96b0104f1 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -269,8 +269,8 @@ to_chat(user, "[M] is at full health.") return FALSE user.visible_message("[user] applies \the [src] on [M].", "You apply \the [src] on [M].") - return heal_carbon(M, user, heal_brute, heal_burn) - + M.heal_bodypart_damage(heal_brute) + return TRUE to_chat(user, "You can't heal [M] with \the [src]!") /obj/item/stack/medical/ointment diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 7692278ba3..426958b99a 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -117,6 +117,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \ new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \ +// new/datum/stack_recipe("diamond brick", /obj/item/ingot/diamond, 6, time = 100), \ not yet )) /obj/item/stack/sheet/mineral/diamond/get_main_recipes() @@ -145,6 +146,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \ new/datum/stack_recipe("uranium tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \ new/datum/stack_recipe("Nuke Statue", /obj/structure/statue/uranium/nuke, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Engineer Statue", /obj/structure/statue/uranium/eng, 5, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("uranium ingot", /obj/item/ingot/uranium, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/uranium/get_main_recipes() @@ -177,6 +179,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \ new/datum/stack_recipe("plasma door", /obj/structure/mineral_door/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("plasma tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \ new/datum/stack_recipe("Scientist Statue", /obj/structure/statue/plasma/scientist, 5, one_per_turf = 1, on_floor = 1), \ +// new/datum/stack_recipe("plasma ingot", /obj/item/ingot/plasma, 6, time = 100), \ no )) /obj/item/stack/sheet/mineral/plasma/get_main_recipes() @@ -221,6 +224,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \ new/datum/stack_recipe("RD Statue", /obj/structure/statue/gold/rd, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Simple Crown", /obj/item/clothing/head/crown, 5), \ new/datum/stack_recipe("CMO Statue", /obj/structure/statue/gold/cmo, 5, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("gold ingot", /obj/item/ingot/gold, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/gold/get_main_recipes() @@ -252,6 +256,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \ new/datum/stack_recipe("Sec Officer Statue", /obj/structure/statue/silver/sec, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Sec Borg Statue", /obj/structure/statue/silver/secborg, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Med Borg Statue", /obj/structure/statue/silver/medborg, 5, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("silver ingot", /obj/item/ingot/silver, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/silver/get_main_recipes() @@ -278,6 +283,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \ GLOBAL_LIST_INIT(bananium_recipes, list ( \ new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \ new/datum/stack_recipe("Clown Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("hilarious ingot", /obj/item/ingot/bananium, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/bananium/get_main_recipes() @@ -306,6 +312,7 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \ GLOBAL_LIST_INIT(titanium_recipes, list ( \ new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20), \ + new/datum/stack_recipe("titanic ingot", /obj/item/ingot/titanium, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/titanium/get_main_recipes() @@ -353,6 +360,7 @@ GLOBAL_LIST_INIT(plastitanium_recipes, list ( \ */ GLOBAL_LIST_INIT(adamantine_recipes, list( new /datum/stack_recipe("incomplete servant golem shell", /obj/item/golem_shell/servant, req_amount=1, res_amount=1), + new/datum/stack_recipe("adamant ingot", /obj/item/ingot/adamantine, 6, time = 100), \ )) /obj/item/stack/sheet/mineral/adamantine diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 645051b7c2..fa52ec4520 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -121,6 +121,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("pestle", /obj/item/pestle, 1, time = 50), \ new/datum/stack_recipe("floodlight frame", /obj/structure/floodlight_frame, 5, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("iron ingot", /obj/item/ingot/iron, 6, time = 100), \ )) /obj/item/stack/sheet/metal @@ -178,6 +179,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \ new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \ + new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \ new /datum/stack_recipe_list("crates", list( \ new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("internals crate", /obj/structure/closet/crate/internals, 5, time = 50, one_per_turf = 1, on_floor = 1), \ @@ -556,6 +558,9 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \ new/datum/stack_recipe("forge", /obj/structure/destructible/cult/forge, 3, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("archives", /obj/structure/destructible/cult/tome, 3, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("altar", /obj/structure/destructible/cult/talisman, 3, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("anvil", /obj/structure/anvil/obtainable/narsie, 4, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("runic ingot", /obj/item/ingot/cult, 2, time = 100), \ + new/datum/stack_recipe("rune smith's hammer", /obj/item/melee/smith/hammer/narsie, 6), \ )) /obj/item/stack/sheet/runed_metal @@ -618,6 +623,8 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \ new/datum/stack_recipe("brass bar stool", /obj/structure/chair/stool/bar/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("brass stool", /obj/structure/chair/stool/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("brass anvil", /obj/structure/anvil/obtainable/ratvar, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("brass furnace", /obj/structure/furnace/infinite/ratvar, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ null, \ new/datum/stack_recipe("sender - pressure sensor", /obj/structure/destructible/clockwork/trap/trigger/pressure_sensor, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("sender - mech sensor", /obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/mech, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \ @@ -629,6 +636,8 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \ new/datum/stack_recipe("receiver - power nullifier", /obj/structure/destructible/clockwork/trap/power_nullifier, 5, time = 20, one_per_turf = TRUE, on_floor = TRUE, placement_checks = STACK_CHECK_CARDINALS), \ null, \ new/datum/stack_recipe("brass flask", /obj/item/reagent_containers/food/drinks/bottle/holyoil/empty), \ + new/datum/stack_recipe("brass smith's hammer", /obj/item/melee/smith/hammer/ratvar, 6), \ + new/datum/stack_recipe("brass ingot", /obj/item/ingot/ratvar, 6, time = 100), \ )) /obj/item/stack/tile/brass @@ -684,7 +693,10 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ new/datum/stack_recipe("bronze chair", /obj/structure/chair/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bronze bar stool", /obj/structure/chair/stool/bar/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bronze stool", /obj/structure/chair/stool/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ - new /datum/stack_recipe("bronze floor tiles", /obj/item/stack/tile/bronze, 1, 4, 20), \ + new/datum/stack_recipe("bronze anvil",/obj/structure/anvil/obtainable/bronze, 20, time = 110, one_per_turf = TRUE, on_floor = TRUE), \ + null, + new/datum/stack_recipe("bronze ingot", /obj/item/ingot/bronze, 6, time = 100), \ + new/datum/stack_recipe("bronze floor tiles", /obj/item/stack/tile/bronze, 1, 4, 20), \ )) /obj/item/stack/sheet/bronze diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 0001494fdd..590df34cde 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -815,3 +815,18 @@ attack_verb = list("bashed", "slashes", "prods", "pokes") fitting_swords = list(/obj/item/melee/rapier) starting_sword = /obj/item/melee/rapier + +/obj/item/storage/belt/sabre/twin + name = "twin sheath" + desc = "Two sheaths. One is capable of holding a katana (or bokken) and the other a wakizashi. You could put two wakizashis in if you really wanted to. Now you can really roleplay as a samurai." + icon_state = "twinsheath" + item_state = "quiver" //this'll do. + w_class = WEIGHT_CLASS_BULKY + fitting_swords = list(/obj/item/melee/smith/wakizashi, /obj/item/melee/smith/twohand/katana, /obj/item/melee/bokken) + starting_sword = null + +/obj/item/storage/belt/sabre/twin/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 2 + STR.max_w_class = WEIGHT_CLASS_BULKY + WEIGHT_CLASS_NORMAL //katana and waki. diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 653e95c21e..3f2dc2506a 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -237,6 +237,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 resistance_flags = FIRE_PROOF total_mass = TOTAL_MASS_MEDIEVAL_WEAPON +/obj/item/katana/lavaland + desc = "Woefully underpowered in Lavaland." + block_chance = 30 + force = 25 //Like a fireaxe but one handed and can block! + /obj/item/katana/cursed slot_flags = null diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index f5003e035b..3de28b38e8 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -143,10 +143,18 @@ var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10) take_damage(amt, BRUTE) +#define BLACKLISTED_OBJECTS list(/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/machinery/power/smes, /obj/structure/cable) + /obj/attack_slime(mob/living/simple_animal/slime/user) if(!user.is_adult) return - attack_generic(user, rand(10, 15), "melee", 1) + if(src.type in BLACKLISTED_OBJECTS) + return + if(istype(src, /obj/machinery/atmospherics)) + return + attack_generic(user, rand(10, 15), BRUTE, "melee", 1) + +#undef BLACKLISTED_OBJECTS /obj/mech_melee_attack(obj/mecha/M) M.do_attack_animation(src) @@ -196,9 +204,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e /obj/proc/acid_processing() . = 1 if(!(resistance_flags & ACID_PROOF)) - for(var/armour_value in armor) - if(armour_value != "acid" && armour_value != "fire") - armor = armor.modifyAllRatings(0 - round(sqrt(acid_level)*0.1)) if(prob(33)) playsound(loc, 'sound/items/welder.ogg', 150, 1) take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, "acid", 0) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 99b302e9ce..3abee4db33 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -304,18 +304,20 @@ /obj/proc/reskin_obj(mob/M) if(!LAZYLEN(unique_reskin)) return - var/dat = "Reskin options for [name]:\n" - for(var/V in unique_reskin) - var/output = icon2html(src, M, unique_reskin[V]) - dat += "[V]: [output]\n" - to_chat(M, dat) - - var/choice = input(M, always_reskinnable ? "Choose the a reskin for [src]" : "Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin - if(QDELETED(src) || !choice || (current_skin && !always_reskinnable) || M.incapacitated() || !in_range(M,src) || !unique_reskin[choice] || unique_reskin[choice] == current_skin) - return - current_skin = choice + var/list/skins = list() + for(var/S in unique_reskin) + skins[S] = image(icon = icon, icon_state = unique_reskin[S]) + var/choice = show_radial_menu(M, src, skins, custom_check = CALLBACK(src, .proc/check_skinnable, M), radius = 40, require_near = TRUE) + if(!choice) + return FALSE icon_state = unique_reskin[choice] - to_chat(M, "[src] is now skinned as '[choice]'.") + current_skin = choice + return + +/obj/proc/check_skinnable(/mob/M) + if(current_skin || !always_reskinnable) + return FALSE + return TRUE /obj/update_overlays() . = ..() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index beb14ff48c..d127a87b20 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -4,25 +4,6 @@ req_access = list(ACCESS_ALL_PERSONAL_LOCKERS) var/registered_name = null -/obj/structure/closet/secure_closet/personal/examine(mob/user) - . = ..() - if(registered_name) - . += "The display reads, \"Owned by [registered_name]\"." - -/obj/structure/closet/secure_closet/personal/check_access(obj/item/I) - . = ..() - if(!I || !istype(I)) - return - if(istype(I,/obj/item/modular_computer/tablet)) - var/obj/item/modular_computer/tablet/ourTablet = I - var/obj/item/computer_hardware/card_slot/card_slot = ourTablet.all_components[MC_CARD] - if(card_slot) - return registered_name == card_slot.stored_card.registered_name || registered_name == card_slot.stored_card2.registered_name - var/obj/item/card/id/ID = I.GetID() - if(ID && registered_name == ID.registered_name) - return TRUE - return FALSE - /obj/structure/closet/secure_closet/personal/PopulateContents() ..() if(prob(50)) @@ -54,15 +35,24 @@ /obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params) var/obj/item/card/id/I = W.GetID() - if(!I || !istype(I)) - return ..() - if(!can_lock(user, FALSE)) //Can't do anything if there isn't a lock! - return - if(I.registered_name && !registered_name) - to_chat(user, "You claim [src].") - registered_name = I.registered_name + if(istype(I)) + if(broken) + to_chat(user, "It appears to be broken.") + return + if(!I || !I.registered_name) + return + if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name))) + //they can open all lockers, or nobody owns this, or they own this locker + locked = !locked + update_icon() + + if(!registered_name) + registered_name = I.registered_name + desc = "Owned by [I.registered_name]." + else + to_chat(user, "Access Denied.") else - ..() + return ..() /obj/structure/closet/secure_closet/personal/handle_lock_addition() //If lock construction is successful we don't care what access the electronics had, so we override it if(..()) diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index dc5355e9d8..1e278a9f88 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -9,6 +9,7 @@ armor = list("melee" = 0, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 20) var/obj/item/holosign_creator/projector var/init_vis_overlay = TRUE + rad_flags = RAD_NO_CONTAMINATE /obj/structure/holosign/Initialize(mapload, source_projector) . = ..() diff --git a/code/game/objects/structures/lavaland/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm index 2911babd83..edc4f0c91f 100644 --- a/code/game/objects/structures/lavaland/necropolis_tendril.dm +++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm @@ -10,6 +10,7 @@ max_mobs = 3 max_integrity = 250 mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril) + var/loot_type = /obj/structure/closet/crate/necropolis/tendril/all move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it anchored = TRUE @@ -41,7 +42,7 @@ GLOBAL_LIST_INIT(tendrils, list()) /obj/structure/spawner/lavaland/deconstruct(disassembled) new /obj/effect/collapse(loc) - new /obj/structure/closet/crate/necropolis/tendril(loc) + new loot_type(loc) return ..() diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 237cfdbf0b..758685ede7 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -229,17 +229,32 @@ H.update_hair() if(BODY_ZONE_PRECISE_EYES) - var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+H.eye_color) as color|null - if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return - if(new_eye_color) - var/n_color = sanitize_hexcolor(new_eye_color) - var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) - if(eyes) - eyes.eye_color = n_color - H.eye_color = n_color - H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK) - H.dna.species.handle_body() + var/eye_type = input(H, "Choose the eye you want to color", "Eye Color") as null|anything in list("Both Eyes", "Left Eye", "Right Eye") + if(eye_type) + var/input_color = H.left_eye_color + if(eye_type == "Right Eye") + input_color = H.right_eye_color + var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+input_color) as color|null + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + if(new_eye_color) + var/n_color = sanitize_hexcolor(new_eye_color) + var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) + var/left_color = n_color + var/right_color = n_color + if(eye_type == "Left Eye") + right_color = H.right_eye_color + else + if(eye_type == "Right Eye") + left_color = H.left_eye_color + if(eyes) + eyes.left_eye_color = left_color + eyes.right_eye_color = right_color + H.left_eye_color = left_color + H.right_eye_color = right_color + H.dna.update_ui_block(DNA_LEFT_EYE_COLOR_BLOCK) + H.dna.update_ui_block(DNA_RIGHT_EYE_COLOR_BLOCK) + H.dna.species.handle_body() if(choice) curse(user) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 6552e29246..1ff056c572 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -210,7 +210,7 @@ if(!get_excited() && air.compare(enemy_air)) //testing("Active turf found. Return value of compare(): [is_active]") set_excited(TRUE) - SSair.active_turfs |= src + SSair.add_to_active_extools(src) /turf/open/proc/GetHeatCapacity() . = air.heat_capacity() diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 758f824727..877d236e84 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -13,7 +13,7 @@ var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default var/icon_plating = "plating" - thermal_conductivity = 0.040 + thermal_conductivity = 0.004 heat_capacity = 10000 intact = 1 var/broken = 0 diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index 03045674e4..42b4707b50 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -3,7 +3,7 @@ name = "reinforced floor" desc = "Extremely sturdy." icon_state = "engine" - thermal_conductivity = 0.025 + thermal_conductivity = 0.0025 heat_capacity = INFINITY floor_tile = /obj/item/stack/rods footstep = FOOTSTEP_PLATING diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index ed48c24462..5d928f377e 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -90,7 +90,7 @@ icon = 'icons/turf/walls/plasma_wall.dmi' icon_state = "plasma" sheet_type = /obj/item/stack/sheet/mineral/plasma - thermal_conductivity = 0.04 + thermal_conductivity = 0.004 canSmoothWith = list(/turf/closed/wall/mineral/plasma, /obj/structure/falsewall/plasma) /turf/closed/wall/mineral/plasma/attackby(obj/item/W, mob/user, params) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 9ff4f668a4..402ab36947 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -138,7 +138,7 @@ if(prob(hardness)) playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") - hulk_recoil(arm, user) + //hulk_recoil(arm, user) // citadel edit - no, hulks are already subject to stamina combat dismantle_wall(1) else diff --git a/code/game/world.dm b/code/game/world.dm index a342200b3d..42c90d8be1 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -11,6 +11,11 @@ GLOBAL_LIST(topic_status_cache) /world/New() if (fexists(EXTOOLS)) call(EXTOOLS, "maptick_initialize")() + #ifdef EXTOOLS_LOGGING + call(EXTOOLS, "init_logging")() + else + CRASH("[EXTOOLS] does not exist!") + #endif enable_debugger() #ifdef REFERENCE_TRACKING enable_reference_tracking() @@ -20,8 +25,6 @@ GLOBAL_LIST(topic_status_cache) log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!") - SetupExternalRSC() - GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) @@ -87,17 +90,6 @@ GLOBAL_LIST(topic_status_cache) #endif SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS)) -/world/proc/SetupExternalRSC() -#if (PRELOAD_RSC == 0) - GLOB.external_rsc_urls = world.file2list("[global.config.directory]/external_rsc_urls.txt","\n") - var/i=1 - while(i<=GLOB.external_rsc_urls.len) - if(GLOB.external_rsc_urls[i]) - i++ - else - GLOB.external_rsc_urls.Cut(i,i+1) -#endif - /world/proc/SetupLogs() var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER] if(!override_dir) @@ -281,12 +273,7 @@ GLOBAL_LIST(topic_status_cache) ..() /world/Del() - // memory leaks bad - var/num_deleted = 0 - for(var/datum/gas_mixture/GM) - GM.__gasmixture_unregister() - num_deleted++ - log_world("Deallocated [num_deleted] gas mixtures") + shutdown_logging() // makes sure the thread is closed before end, else we terminate ..() /world/proc/update_status() diff --git a/code/modules/NTNet/network.dm b/code/modules/NTNet/network.dm index d86ad792fe..2a2820d289 100644 --- a/code/modules/NTNet/network.dm +++ b/code/modules/NTNet/network.dm @@ -206,7 +206,7 @@ for(var/datum/ntnet_conversation/chan in chat_channels) if(chan.id == id) return chan - + // Resets the IDS alarm /datum/ntnet/proc/resetIDS() intrusion_detection_alarm = FALSE diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 8cfae3820a..8421d9955d 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1,12 +1,12 @@ //////////////////////////////// /proc/message_admins(msg) - msg = "ADMIN LOG: [msg]" - to_chat(GLOB.admins, msg) + msg = "ADMIN LOG: [msg]" + to_chat(GLOB.admins, msg, confidential = TRUE) /proc/relay_msg_admins(msg) - msg = "RELAY: [msg]" - to_chat(GLOB.admins, msg) + msg = "RELAY: [msg]" + to_chat(GLOB.admins, msg, confidential = TRUE) ///////////////////////////////////////////////////////////////////////////////////////////////Panels @@ -22,7 +22,7 @@ log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].") if(!M) - to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.") + to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.", confidential = TRUE) return var/body = "Options for [M.key]" @@ -65,6 +65,7 @@ body += "VV - " if(M.mind) body += "TP - " + // body += "SKILLS - " else body += "Init Mind - " if (iscyborg(M)) @@ -122,6 +123,7 @@ body += "Traitor panel | " body += "Narrate to | " body += "Subtle message | " + // body += "Play sound to | " body += "Language Menu" if (M.client) @@ -216,7 +218,7 @@ if (!istype(src, /datum/admins)) src = usr.client.holder if (!istype(src, /datum/admins)) - to_chat(usr, "Error: you are not an admin!") + to_chat(usr, "Error: you are not an admin!", confidential = TRUE) return var/dat dat = text("Admin Newscaster

    Admin Newscaster Unit

    ") @@ -242,7 +244,7 @@ dat+="

    The newscaster recognises you as:
    [src.admin_signature]
    " if(1) dat+= "Station Feed Channels
    " - if( isemptylist(GLOB.news_network.network_channels) ) + if( !length(GLOB.news_network.network_channels) ) dat+="No active channels found..." else for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) @@ -295,7 +297,7 @@ dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    " dat+="No further feed story additions are allowed while the D-Notice is in effect.

    " else - if( isemptylist(src.admincaster_feed_channel.messages) ) + if( !length(src.admincaster_feed_channel.messages) ) dat+="No feed messages found in channel...
    " else var/i = 0 @@ -317,7 +319,7 @@ dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
    " dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
    " dat+="
    Select Feed channel to get Stories from:
    " - if(isemptylist(GLOB.news_network.network_channels)) + if(!length(GLOB.news_network.network_channels)) dat+="No feed channels found active...
    " else for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) @@ -328,7 +330,7 @@ dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's" dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed" dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
    " - if(isemptylist(GLOB.news_network.network_channels)) + if(!length(GLOB.news_network.network_channels)) dat+="No feed channels found active...
    " else for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) @@ -339,7 +341,7 @@ dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
    " dat+="[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]
    " - if( isemptylist(src.admincaster_feed_channel.messages) ) + if( !length(src.admincaster_feed_channel.messages) ) dat+="No feed messages found in channel...
    " else for(var/datum/news/feed_message/MESSAGE in src.admincaster_feed_channel.messages) @@ -356,7 +358,7 @@ dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    " dat+="No further feed story additions are allowed while the D-Notice is in effect.

    " else - if( isemptylist(src.admincaster_feed_channel.messages) ) + if( !length(src.admincaster_feed_channel.messages) ) dat+="No feed messages found in channel...
    " else for(var/datum/news/feed_message/MESSAGE in src.admincaster_feed_channel.messages) @@ -426,7 +428,6 @@ "} if(GLOB.master_mode == "secret") dat += "(Force Secret Mode)
    " - if(GLOB.master_mode == "dynamic") if(SSticker.current_state <= GAME_STATE_PREGAME) dat += "(Force Roundstart Rulesets)
    " @@ -449,7 +450,6 @@ dat += "
    " if(SSticker.IsRoundInProgress()) dat += "(Game Mode Panel)
    " - dat += {"
    Create Object
    @@ -461,7 +461,7 @@ if(marked_datum && istype(marked_datum, /atom)) dat += "Duplicate Marked Datum
    " - usr << browse(dat, "window=admin2;size=210x200") + usr << browse(dat, "window=admin2;size=240x280") return /////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge @@ -475,33 +475,42 @@ if (!usr.client.holder) return - var/list/options = list("Regular Restart", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)") + var/localhost_addresses = list("127.0.0.1", "::1") + var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)") if(world.TgsAvailable()) options += "Server Restart (Kill and restart DD)"; - var/rebootconfirm if(SSticker.admin_delay_notice) - if(alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") == "Yes") - rebootconfirm = TRUE - else - rebootconfirm = TRUE - if(rebootconfirm) - var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options - if(result) - SSblackbox.record_feedback("tally", "admin_verb", 1, "Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]." - switch(result) - if("Regular Restart") - SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10) - if("Hard Restart (No Delay, No Feeback Reason)") - to_chat(world, "World reboot - [init_by]") - world.Reboot() - if("Hardest Restart (No actions, just reboot)") - to_chat(world, "Hard world reboot - [init_by]") - world.Reboot(fast_track = TRUE) - if("Server Restart (Kill and restart DD)") - to_chat(world, "Server restart - [init_by]") - world.TgsEndProcess() + if(alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes") + return FALSE + + var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options + if(result) + SSblackbox.record_feedback("tally", "admin_verb", 1, "Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]." + switch(result) + if("Regular Restart") + if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) + if(alert("Are you sure you want to restart the server?","This server is live","Restart","Cancel") != "Restart") + return FALSE + SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10) + if("Regular Restart (with delay)") + var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null + if(!delay) + return FALSE + if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) + if(alert("Are you sure you want to restart the server?","This server is live","Restart","Cancel") != "Restart") + return FALSE + SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay * 10) + if("Hard Restart (No Delay, No Feeback Reason)") + to_chat(world, "World reboot - [init_by]") + world.Reboot() + if("Hardest Restart (No actions, just reboot)") + to_chat(world, "Hard world reboot - [init_by]") + world.Reboot(fast_track = TRUE) + if("Server Restart (Kill and restart DD)") + to_chat(world, "Server restart - [init_by]") + world.TgsEndProcess() /datum/admins/proc/end_round() set category = "Server" @@ -529,7 +538,7 @@ if(message) if(!check_rights(R_SERVER,0)) message = adminscrub(message,500) - to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]") + to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]", confidential = TRUE) log_admin("Announce: [key_name(usr)] : [message]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -551,7 +560,7 @@ else message_admins("[key_name(usr)] set the admin notice.") log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]") - to_chat(world, "Admin Notice:\n \t [new_admin_notice]") + to_chat(world, "Admin Notice:\n \t [new_admin_notice]", confidential = TRUE) SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! GLOB.admin_notice = new_admin_notice return @@ -598,20 +607,29 @@ set desc="Start the round RIGHT NOW" set name="Start Now" if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP) - SSticker.start_immediately = TRUE - log_admin("[usr.key] has started the game.") - var/msg = "" - if(SSticker.current_state == GAME_STATE_STARTUP) - msg = " (The server is still setting up, but the round will be \ - started as soon as possible.)" - message_admins("\ - [usr.key] has started the game.[msg]") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return 1 + if(!SSticker.start_immediately) + var/localhost_addresses = list("127.0.0.1", "::1") + if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) + if(alert("Are you sure you want to start the round?","Start Now","Start Now","Cancel") != "Start Now") + return FALSE + SSticker.start_immediately = TRUE + log_admin("[usr.key] has started the game.") + var/msg = "" + if(SSticker.current_state == GAME_STATE_STARTUP) + msg = " (The server is still setting up, but the round will be \ + started as soon as possible.)" + message_admins("[usr.key] has started the game.[msg]") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return TRUE + SSticker.start_immediately = FALSE + SSticker.SetTimeLeft(1800) + to_chat(world, "The game will start in 180 seconds.") + SEND_SOUND(world, sound(get_announcer_sound("attention"))) + message_admins("[usr.key] has cancelled immediate game start. Game will start in 180 seconds.") + log_admin("[usr.key] has cancelled immediate game start.") else to_chat(usr, "Error: Start Now: Game has already started.") - - return 0 + return FALSE /datum/admins/proc/toggleenter() set category = "Server" @@ -619,9 +637,9 @@ set name="Toggle Entering" GLOB.enter_allowed = !( GLOB.enter_allowed ) if (!( GLOB.enter_allowed )) - to_chat(world, "New players may no longer enter the game.") + to_chat(world, "New players may no longer enter the game.", confidential = TRUE) else - to_chat(world, "New players may now enter the game.") + to_chat(world, "New players may now enter the game.", confidential = TRUE) log_admin("[key_name(usr)] toggled new player game entering.") message_admins("[key_name_admin(usr)] toggled new player game entering.") world.update_status() @@ -634,9 +652,9 @@ var/alai = CONFIG_GET(flag/allow_ai) CONFIG_SET(flag/allow_ai, !alai) if (alai) - to_chat(world, "The AI job is no longer chooseable.") + to_chat(world, "The AI job is no longer chooseable.", confidential = TRUE) else - to_chat(world, "The AI job is chooseable now.") + to_chat(world, "The AI job is chooseable now.", confidential = TRUE) log_admin("[key_name(usr)] toggled AI allowed.") world.update_status() SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -654,7 +672,7 @@ aiPlayer.end_multicam() log_admin("[key_name(usr)] toggled AI multicam.") world.update_status() - to_chat(GLOB.ai_list | GLOB.admins, "The AI [almcam ? "no longer" : "now"] has multicam.") + to_chat(GLOB.ai_list | GLOB.admins, "The AI [almcam ? "no longer" : "now"] has multicam.", confidential = TRUE) SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Multicam", "[!almcam ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /datum/admins/proc/toggleaban() @@ -664,9 +682,9 @@ var/new_nores = !CONFIG_GET(flag/norespawn) CONFIG_SET(flag/norespawn, new_nores) if (!new_nores) - to_chat(world, "You may now respawn.") + to_chat(world, "You may now respawn.", confidential = TRUE) else - to_chat(world, "You may no longer respawn :(") + to_chat(world, "You may no longer respawn :(", confidential = TRUE) message_admins("[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"].") log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].") world.update_status() @@ -675,7 +693,7 @@ /datum/admins/proc/delay() set category = "Server" set desc="Delay the game start" - set name="Delay pre-game" + set name="Delay Pre-Game" var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null if(SSticker.current_state > GAME_STATE_PREGAME) @@ -683,11 +701,12 @@ if(newtime) newtime = newtime*10 SSticker.SetTimeLeft(newtime) + SSticker.start_immediately = FALSE if(newtime < 0) - to_chat(world, "The game start has been delayed.") + to_chat(world, "The game start has been delayed.", confidential = TRUE) log_admin("[key_name(usr)] delayed the round start.") else - to_chat(world, "The game will start in [DisplayTimeText(newtime)].") + to_chat(world, "The game will start in [DisplayTimeText(newtime)].", confidential = TRUE) SEND_SOUND(world, sound(get_announcer_sound("attention"))) log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].") SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -724,20 +743,28 @@ set desc = "(atom path) Spawn an atom" set name = "Spawn" - if(!check_rights(R_SPAWN)) + if(!check_rights(R_SPAWN) || !object) + return + + var/list/preparsed = splittext(object,":") + var/path = preparsed[1] + var/amount = 1 + if(preparsed.len > 1) + amount = clamp(text2num(preparsed[2]),1, 50) //50 at a time! + + var/chosen = pick_closest_path(path) + if(!chosen) return var/turf/T = get_turf(usr) - var/chosen = pick_closest_path(object) - if(!chosen) - return if(ispath(chosen, /turf)) T.ChangeTurf(chosen) else - var/atom/A = new chosen(T) - A.flags_1 |= ADMIN_SPAWNED_1 + for(var/i in 1 to amount) + var/atom/A = new chosen(T) + A.flags_1 |= ADMIN_SPAWNED_1 - log_admin("[key_name(usr)] spawned [chosen] at [AREACOORD(usr)]") + log_admin("[key_name(usr)] spawned [amount] x [chosen] at [AREACOORD(usr)]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /datum/admins/proc/podspawn_atom(object as text) @@ -782,20 +809,18 @@ log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Cargo") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/show_traitor_panel(mob/M in GLOB.mob_list) +/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list) set category = "Admin" set desc = "Edit mobs's memory and role" set name = "Show Traitor Panel" - - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") + var/datum/mind/target_mind = target_mob.mind + if(!target_mind) + to_chat(usr, "This mob has no mind!", confidential = TRUE) return - if(!M.mind) - to_chat(usr, "This mob has no mind!") + if(!istype(target_mob) && !istype(target_mind)) + to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE) return - - M.mind.traitor_panel() + target_mind.traitor_panel() SSblackbox.record_feedback("tally", "admin_verb", 1, "Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -805,9 +830,9 @@ set name="Toggle tinted welding helmes" GLOB.tinted_weldhelh = !( GLOB.tinted_weldhelh ) if (GLOB.tinted_weldhelh) - to_chat(world, "The tinted_weldhelh has been enabled!") + to_chat(world, "The tinted_weldhelh has been enabled!", confidential = TRUE) else - to_chat(world, "The tinted_weldhelh has been disabled!") + to_chat(world, "The tinted_weldhelh has been disabled!", confidential = TRUE) log_admin("[key_name(usr)] toggled tinted_weldhelh.") message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Tinted Welding Helmets", "[GLOB.tinted_weldhelh ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -819,9 +844,9 @@ var/new_guest_ban = !CONFIG_GET(flag/guest_ban) CONFIG_SET(flag/guest_ban, new_guest_ban) if (new_guest_ban) - to_chat(world, "Guests may no longer enter the game.") + to_chat(world, "Guests may no longer enter the game.", confidential = TRUE) else - to_chat(world, "Guests may now enter the game.") + to_chat(world, "Guests may now enter the game.", confidential = TRUE) log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.") message_admins("[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -832,37 +857,37 @@ var/mob/living/silicon/S = i ai_number++ if(isAI(S)) - to_chat(usr, "AI [key_name(S, usr)]'s laws:") + to_chat(usr, "AI [key_name(S, usr)]'s laws:", confidential = TRUE) else if(iscyborg(S)) var/mob/living/silicon/robot/R = S - to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:") + to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:", confidential = TRUE) else if (ispAI(S)) - to_chat(usr, "pAI [key_name(S, usr)]'s laws:") + to_chat(usr, "pAI [key_name(S, usr)]'s laws:", confidential = TRUE) else - to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") + to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:", confidential = TRUE) if (S.laws == null) - to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.") + to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.", confidential = TRUE) else S.laws.show_laws(usr) if(!ai_number) - to_chat(usr, "No AIs located" ) + to_chat(usr, "No AIs located" , confidential = TRUE) /datum/admins/proc/output_all_devil_info() var/devil_number = 0 for(var/datum/mind/D in SSticker.mode.devils) devil_number++ var/datum/antagonist/devil/devil = D.has_antag_datum(/datum/antagonist/devil) - to_chat(usr, "Devil #[devil_number]:

    " + devil.printdevilinfo()) + to_chat(usr, "Devil #[devil_number]:

    " + devil.printdevilinfo(), confidential = TRUE) if(!devil_number) - to_chat(usr, "No Devils located" ) + to_chat(usr, "No Devils located" , confidential = TRUE) /datum/admins/proc/output_devil_info(mob/living/M) if(is_devil(M)) var/datum/antagonist/devil/devil = M.mind.has_antag_datum(/datum/antagonist/devil) - to_chat(usr, devil.printdevilinfo()) + to_chat(usr, devil.printdevilinfo(), confidential = TRUE) else - to_chat(usr, "[M] is not a devil.") + to_chat(usr, "[M] is not a devil.", confidential = TRUE) /datum/admins/proc/manage_free_slots() if(!check_rights()) @@ -965,21 +990,21 @@ if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk continue if(message) - to_chat(C, message) + to_chat(C, message, confidential = TRUE) kicked_client_names.Add("[C.key]") qdel(C) return kicked_client_names -//returns 1 to let the dragdrop code know we are trapping this event -//returns 0 if we don't plan to trap the event +//returns TRUE to let the dragdrop code know we are trapping this event +//returns FALSE if we don't plan to trap the event /datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, mob/tomob) //this is the exact two check rights checks required to edit a ckey with vv. if (!check_rights(R_VAREDIT,0) || !check_rights(R_SPAWN|R_DEBUG,0)) - return 0 + return FALSE if (!frommob.ckey) - return 0 + return FALSE var/question = "" if (tomob.ckey) @@ -988,12 +1013,18 @@ var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No") if (ask != "Yes") - return 1 + return TRUE if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response - return 1 + return TRUE - tomob.ghostize(0) + // Disassociates observer mind from the body mind + if(tomob.client) + tomob.ghostize(FALSE) + else + for(var/mob/dead/observer/ghost in GLOB.dead_mob_list) + if(tomob.mind == ghost.mind) + ghost.mind = null message_admins("[key_name_admin(usr)] has put [frommob.key] in control of [tomob.name].") log_admin("[key_name(usr)] stuffed [frommob.key] into [tomob.name].") @@ -1002,7 +1033,7 @@ tomob.ckey = frommob.ckey qdel(frommob) - return 1 + return TRUE /client/proc/adminGreet(logout) if(SSticker.HasRoundStarted()) diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 99bb988be6..7e5c104d90 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -4,19 +4,39 @@ var/F = file("[GLOB.log_directory]/[subject].html") WRITE_FILE(F, "[TIME_STAMP("hh:mm:ss", FALSE)] [REF(src)] ([x],[y],[z]) || [src] [message]
    ") -/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RCD, INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES, INVESTIGATE_CRYOGENICS) ) +/client/proc/investigate_show() set name = "Investigate" set category = "Admin" if(!holder) return - switch(subject) - if("notes, memos, watchlist") - if(!check_rights(R_ADMIN)) - return - browse_messages() + + var/list/investigates = list(INVESTIGATE_RCD, INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES, INVESTIGATE_CRYOGENICS) + + var/list/logs_present = list("notes, memos, watchlist") + var/list/logs_missing = list("---") + + for(var/subject in investigates) + var/temp_file = file("[GLOB.log_directory]/[subject].html") + if(fexists(temp_file)) + logs_present += subject else - var/F = file("[GLOB.log_directory]/[subject].html") - if(!fexists(F)) - to_chat(src, "No [subject] logfile was found.") - return - src << browse(F,"window=investigate[subject];size=800x300") + logs_missing += "[subject] (empty)" + + var/list/combined = sortList(logs_present) + sortList(logs_missing) + + var/selected = input("Investigate what?", "Investigate") as null|anything in combined + + if(!(selected in combined) || selected == "---") + return + + selected = replacetext(selected, " (empty)", "") + + if(selected == "notes, memos, watchlist" && check_rights(R_ADMIN)) + browse_messages() + return + + var/F = file("[GLOB.log_directory]/[selected].html") + if(!fexists(F)) + to_chat(src, "No [selected] logfile was found.", confidential = TRUE) + return + src << browse(F,"window=investigate[selected];size=800x300") diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e9abb7db87..2c4e7b4f6e 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -11,7 +11,8 @@ GLOBAL_PROTECT(admin_verbs_default) /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ /client/proc/toggleprayers, - /client/proc/toggleadminhelpsound + /client/proc/toggleadminhelpsound, + /client/proc/debugstatpanel, ) GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) GLOBAL_PROTECT(admin_verbs_admin) @@ -260,36 +261,36 @@ GLOBAL_PROTECT(admin_verbs_hideable) control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS var/rights = holder.rank.rights - verbs += GLOB.admin_verbs_default + add_verb(src, GLOB.admin_verbs_default) if(rights & R_BUILDMODE) - verbs += /client/proc/togglebuildmodeself + add_verb(src, /client/proc/togglebuildmodeself) if(rights & R_ADMIN) - verbs += GLOB.admin_verbs_admin + add_verb(src, GLOB.admin_verbs_admin) if(rights & R_BAN) - verbs += GLOB.admin_verbs_ban + add_verb(src, GLOB.admin_verbs_ban) if(rights & R_FUN) - verbs += GLOB.admin_verbs_fun + add_verb(src, GLOB.admin_verbs_fun) if(rights & R_SERVER) - verbs += GLOB.admin_verbs_server + add_verb(src, GLOB.admin_verbs_server) if(rights & R_DEBUG) - verbs += GLOB.admin_verbs_debug + add_verb(src, GLOB.admin_verbs_debug) if(rights & R_POSSESS) - verbs += GLOB.admin_verbs_possess + add_verb(src, GLOB.admin_verbs_possess) if(rights & R_PERMISSIONS) - verbs += GLOB.admin_verbs_permissions + add_verb(src, GLOB.admin_verbs_permissions) if(rights & R_STEALTH) - verbs += /client/proc/stealth + add_verb(src, /client/proc/stealth) if(rights & R_ADMIN) - verbs += GLOB.admin_verbs_poll + add_verb(src, GLOB.admin_verbs_poll) if(rights & R_SOUNDS) - verbs += GLOB.admin_verbs_sounds + add_verb(src, GLOB.admin_verbs_sounds) if(CONFIG_GET(string/invoke_youtubedl)) - verbs += /client/proc/play_web_sound + add_verb(src, /client/proc/play_web_sound) if(rights & R_SPAWN) - verbs += GLOB.admin_verbs_spawn + add_verb(src, GLOB.admin_verbs_spawn) /client/proc/remove_admin_verbs() - verbs.Remove( + remove_verb(src, list( GLOB.admin_verbs_default, /client/proc/togglebuildmodeself, GLOB.admin_verbs_admin, @@ -308,14 +309,15 @@ GLOBAL_PROTECT(admin_verbs_hideable) GLOB.admin_verbs_debug_mapping, /client/proc/disable_debug_verbs, /client/proc/readmin - ) + )) /client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs set name = "Adminverbs - Hide Most" set category = "Admin" - verbs.Remove(/client/proc/hide_most_verbs, GLOB.admin_verbs_hideable) - verbs += /client/proc/show_verbs + remove_verb(src, GLOB.admin_verbs_hideable) + remove_verb(src, /client/proc/hide_most_verbs) + add_verb(src, /client/proc/show_verbs) to_chat(src, "Most of your adminverbs have been hidden.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Hide Most Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -326,7 +328,7 @@ GLOBAL_PROTECT(admin_verbs_hideable) set category = "Admin" remove_admin_verbs() - verbs += /client/proc/show_verbs + add_verb(src, /client/proc/show_verbs) to_chat(src, "Almost all of your adminverbs have been hidden.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Hide All Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -336,7 +338,7 @@ GLOBAL_PROTECT(admin_verbs_hideable) set name = "Adminverbs - Show" set category = "Admin" - verbs -= /client/proc/show_verbs + remove_verb(src, /client/proc/show_verbs) add_admin_verbs() to_chat(src, "All of your adminverbs are now visible.") @@ -724,3 +726,9 @@ GLOBAL_PROTECT(admin_verbs_hideable) log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact") message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction") + +/client/proc/debugstatpanel() + set name = "Debug Stat Panel" + set category = "Debug" + + src << output("", "statbrowser:create_debug") diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 59651b17d5..e287d9b1b3 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -24,7 +24,9 @@ H.facial_hair_style = random_facial_hair_style(H.gender) H.hair_color = random_short_color() H.facial_hair_color = H.hair_color - H.eye_color = random_eye_color() + var/random_eye_color = random_eye_color() + H.left_eye_color = random_eye_color + H.right_eye_color = random_eye_color H.dna.blood_type = random_blood_type() H.saved_underwear = H.underwear H.saved_undershirt = H.undershirt diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 1d0b6b2a79..09f9664295 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -91,7 +91,7 @@ GLOBAL_PROTECT(href_token) var/client/C if ((C = owner) || (C = GLOB.directory[target])) disassociate() - C.verbs += /client/proc/readmin + add_verb(C, /client/proc/readmin) /datum/admins/proc/associate(client/C) if(IsAdminAdvancedProcCall()) @@ -111,7 +111,8 @@ GLOBAL_PROTECT(href_token) owner = C owner.holder = src owner.add_admin_verbs() //TODO <--- todo what? the proc clearly exists and works since its the backbone to our entire admin system - owner.verbs -= /client/proc/readmin + remove_verb(owner, /client/proc/readmin) + owner.init_verbs() //re-initialize the verb list GLOB.admins |= C /datum/admins/proc/disassociate() @@ -123,6 +124,7 @@ GLOBAL_PROTECT(href_token) if(owner) GLOB.admins -= owner owner.remove_admin_verbs() + owner.init_verbs() owner.holder = null owner = null diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index b757028ea2..97d912cb9e 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -397,11 +397,13 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null delete_click = new(null, "INITIALIZING", src) if(!action_click) action_click = new(null, "INITIALIZNG", src) - stat("[id] ", delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \ + var/list/L = list() + L[++L.len] = list("[id] ", "[delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \ [islist(obj_count_all)? length(obj_count_all) : (isnull(obj_count_all)? "0" : obj_count_all)]/\ [islist(obj_count_eligible)? length(obj_count_eligible) : (isnull(obj_count_eligible)? "0" : obj_count_eligible)]/\ - [islist(obj_count_finished)? length(obj_count_finished) : (isnull(obj_count_finished)? "0" : obj_count_finished)] - [get_query_text()]")) - stat(" ", action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]")) + [islist(obj_count_finished)? length(obj_count_finished) : (isnull(obj_count_finished)? "0" : obj_count_finished)] - [get_query_text()]")]", REF(delete_click)) + L[++L.len] = list(" ", "[action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]")]", REF(action_click)) + return L /datum/SDQL2_query/proc/delete_click() admin_del(usr) @@ -1189,15 +1191,27 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null return query_list /obj/effect/statclick/SDQL2_delete/Click() + if(!usr.client?.holder) + message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])") + log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])") + return var/datum/SDQL2_query/Q = target Q.delete_click() /obj/effect/statclick/SDQL2_action/Click() + if(!usr.client?.holder) + message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])") + log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])") + return var/datum/SDQL2_query/Q = target Q.action_click() /obj/effect/statclick/SDQL2_VV_all name = "VIEW VARIABLES" -/obj/effect/statclick/SDQL2_VV_all/Click() +/obj/effect/statclick/sdql2_vv_all/Click() + if(!usr.client?.holder) + message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])") + log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])") + return usr.client.debug_variables(GLOB.sdql2_queries) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index edf95dc47e..4348ae7661 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -89,18 +89,23 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) //Tickets statpanel /datum/admin_help_tickets/proc/stat_entry() + SHOULD_CALL_PARENT(TRUE) + SHOULD_NOT_SLEEP(TRUE) + var/list/L = list() var/num_disconnected = 0 - stat("Active Tickets:", astatclick.update("[active_tickets.len]")) + L[++L.len] = list("Active Tickets:", "[astatclick.update("[active_tickets.len]")]", null, REF(astatclick)) + astatclick.update("[active_tickets.len]") for(var/I in active_tickets) var/datum/admin_help/AH = I if(AH.initiator) - stat("#[AH.id]. [AH.initiator_key_name]:", AH.statclick.update()) + L[++L.len] = list("#[AH.id]. [AH.initiator_key_name]:", "[AH.statclick.update()]", REF(AH)) else ++num_disconnected if(num_disconnected) - stat("Disconnected:", astatclick.update("[num_disconnected]")) - stat("Closed Tickets:", cstatclick.update("[closed_tickets.len]")) - stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]")) + L[++L.len] = list("Disconnected:", "[astatclick.update("[num_disconnected]")]", null, REF(astatclick)) + L[++L.len] = list("Closed Tickets:", "[cstatclick.update("[closed_tickets.len]")]", null, REF(cstatclick)) + L[++L.len] = list("Resolved Tickets:", "[rstatclick.update("[resolved_tickets.len]")]", null, REF(rstatclick)) + return L //Reassociate still open ticket if one exists /datum/admin_help_tickets/proc/ClientLogin(client/C) @@ -137,6 +142,10 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) /obj/effect/statclick/ticket_list/Click() GLOB.ahelp_tickets.BrowseTickets(current_state) +//called by admin topic +/obj/effect/statclick/ticket_list/proc/Action() + Click() + // //TICKET DATUM // @@ -218,7 +227,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) //Removes the ahelp verb and returns it after 2 minutes /datum/admin_help/proc/TimeoutVerb() - initiator.verbs -= /client/verb/adminhelp + remove_verb(initiator, /client/verb/adminhelp) initiator.adminhelptimerid = addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 1200, TIMER_STOPPABLE) //2 minute cooldown of admin helps //private @@ -490,7 +499,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) // /client/proc/giveadminhelpverb() - src.verbs |= /client/verb/adminhelp + add_verb(src, /client/verb/adminhelp) deltimer(adminhelptimerid) adminhelptimerid = 0 diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 525e4e82c0..257c1d275a 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -3,7 +3,7 @@ set desc = "Area to jump to" set category = "Admin" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return if(!A) @@ -15,20 +15,22 @@ continue turfs.Add(T) - var/turf/T = safepick(turfs) - if(!T) - to_chat(src, "Nowhere to jump to!") + if(length(turfs)) + var/turf/T = pick(turfs) + usr.forceMove(T) + log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Area") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + to_chat(src, "Nowhere to jump to!", confidential = TRUE) return - usr.forceMove(T) - log_admin("[key_name(usr)] jumped to [AREACOORD(A)]") - message_admins("[key_name_admin(usr)] jumped to [AREACOORD(A)]") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Area") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/proc/jumptoturf(turf/T in world) set name = "Jump to Turf" set category = "Admin" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") @@ -42,7 +44,7 @@ set name = "Jump to Mob" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return log_admin("[key_name(usr)] jumped to [key_name(M)]") @@ -54,14 +56,14 @@ SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! A.forceMove(M.loc) else - to_chat(A, "This mob is not located in the game world.") + to_chat(A, "This mob is not located in the game world.", confidential = TRUE) /client/proc/jumptocoord(tx as num, ty as num, tz as num) set category = "Admin" set name = "Jump to Coordinate" if (!holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return if(src.mob) @@ -76,7 +78,7 @@ set name = "Jump to Key" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return var/list/keys = list() @@ -84,7 +86,7 @@ keys += M.client var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) if(!selection) - to_chat(src, "No keys found.") + to_chat(src, "No keys found.", confidential = TRUE) return var/mob/M = selection.mob log_admin("[key_name(usr)] jumped to [key_name(M)]") @@ -99,7 +101,7 @@ set name = "Get Mob" set desc = "Mob to teleport" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return var/atom/loc = get_turf(usr) @@ -116,7 +118,7 @@ set desc = "Key to teleport" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return var/list/keys = list() @@ -142,16 +144,17 @@ set category = "Admin" set name = "Send Mob" if(!src.holder) - to_chat(src, "Only administrators may use this command.") + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return var/area/A = input(usr, "Pick an area.", "Pick an area") in GLOB.sortedAreas|null if(A && istype(A)) - if(M.forceMove(safepick(get_area_turfs(A)))) + var/list/turfs = get_area_turfs(A) + if(length(turfs) && M.forceMove(pick(turfs))) - log_admin("[key_name(usr)] teleported [key_name(M)] to [AREACOORD(A)]") - var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)] to [AREACOORD(A)]" + log_admin("[key_name(usr)] teleported [key_name(M)] to [AREACOORD(M)]") + var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)] to [AREACOORD(M)]" message_admins(msg) admin_ticket_log(M, msg) else - to_chat(src, "Failed to move mob to a valid location.") + to_chat(src, "Failed to move mob to a valid location.", confidential = TRUE) SSblackbox.record_feedback("tally", "admin_verb", 1, "Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index b7f05740a3..2931c52a5c 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -1,12 +1,11 @@ -#define IRCREPLYCOUNT 2 - +#define EXTERNALREPLYCOUNT 2 //allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm /client/proc/cmd_admin_pm_context(mob/M in GLOB.mob_list) set category = null set name = "Admin PM Mob" if(!holder) - to_chat(src, "Error: Admin-PM-Context: Only administrators may use this command.") + to_chat(src, "Error: Admin-PM-Context: Only administrators may use this command.", confidential = TRUE) return if( !ismob(M) || !M.client ) return @@ -18,7 +17,7 @@ set category = "Admin" set name = "Admin PM" if(!holder) - to_chat(src, "Error: Admin-PM-Panel: Only administrators may use this command.") + to_chat(src, "Error: Admin-PM-Panel: Only administrators may use this command.", confidential = TRUE) return var/list/client/targets[0] for(var/client/T) @@ -37,7 +36,7 @@ /client/proc/cmd_ahelp_reply(whom) if(prefs.muted & MUTE_ADMINHELP) - to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).") + to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).", confidential = TRUE) return var/client/C if(istext(whom)) @@ -48,45 +47,61 @@ C = whom if(!C) if(holder) - to_chat(src, "Error: Admin-PM: Client not found.") + to_chat(src, "Error: Admin-PM: Client not found.", confidential = TRUE) return var/datum/admin_help/AH = C.current_ticket if(AH) - message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.") + message_admins("[key_name_admin(src)] has started replying to [key_name_admin(C, 0, 0)]'s admin help.") var/msg = input(src,"Message:", "Private message to [C.holder?.fakekey ? "an Administrator" : key_name(C, 0, 0)].") as message|null if (!msg) - message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.") + message_admins("[key_name_admin(src)] has cancelled their reply to [key_name_admin(C, 0, 0)]'s admin help.") return + if(!C) //We lost the client during input, disconnected or relogged. + if(GLOB.directory[AH.initiator_ckey]) // Client has reconnected, lets try to recover + whom = GLOB.directory[AH.initiator_ckey] + else + to_chat(src, "Error: Admin-PM: Client not found.", confidential = TRUE) + to_chat(src, "Message not sent:
    [msg]", confidential = TRUE) + AH.AddInteraction("No client found, message not sent:
    [msg]") + return cmd_admin_pm(whom, msg) //takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM. //Fetching a message if needed. src is the sender and C is the target client /client/proc/cmd_admin_pm(whom, msg) if(prefs.muted & MUTE_ADMINHELP) - to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).") + to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).", confidential = TRUE) return if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo - to_chat(src, "You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.") - to_chat(src, "Message: [msg]") + to_chat(src, "You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.", confidential = TRUE) + to_chat(src, "Message: [msg]", confidential = TRUE) return var/client/recipient - var/irc = 0 + var/recipient_ckey // Stored in case client is deleted between this and after the message is input + var/datum/admin_help/recipient_ticket // Stored in case client is deleted between this and after the message is input + var/external = 0 if(istext(whom)) if(whom[1] == "@") whom = findStealthKey(whom) if(whom == "IRCKEY") - irc = 1 + external = 1 else recipient = GLOB.directory[whom] else if(istype(whom, /client)) recipient = whom + if(!recipient) + to_chat(src, "Error: Admin-PM: Client not found.", confidential = TRUE) + return - if(irc) + recipient_ckey = recipient.ckey + recipient_ticket = recipient.current_ticket + + if(external) if(!ircreplyamount) //to prevent people from spamming irc/discord return if(!msg) @@ -95,21 +110,11 @@ if(!msg) return if(holder) - to_chat(src, "Error: Use the admin IRC channel, nerd.") + to_chat(src, "Error: Use the admin IRC/Discord channel, nerd.", confidential = TRUE) return else - if(!recipient) - if(holder) - to_chat(src, "Error: Admin-PM: Client not found.") - if(msg) - to_chat(src, msg) - return - else if(msg) // you want to continue if there's no message instead of returning now - current_ticket.MessageNoRecipient(msg) - return - //get message text, limit it's length.and clean/escape html if(!msg) msg = input(src,"Message:", "Private message to [recipient.holder?.fakekey ? "an Administrator" : key_name(recipient, 0, 0)].") as message|null @@ -117,22 +122,30 @@ if(!msg) return - if(prefs.muted & MUTE_ADMINHELP) - to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).") - return - - if(!recipient) + if(!recipient) + if(GLOB.directory[recipient_ckey]) // Client has reconnected, lets try to recover + recipient = GLOB.directory[recipient_ckey] + else if(holder) - to_chat(src, "Error: Admin-PM: Client not found.") + to_chat(src, "Error: Admin-PM: Client not found.", confidential = TRUE) + to_chat(src, "Message not sent:
    [msg]", confidential = TRUE) + if(recipient_ticket) + recipient_ticket.AddInteraction("No client found, message not sent:
    [msg]") + return else current_ticket.MessageNoRecipient(msg) - return + return + + + if(prefs.muted & MUTE_ADMINHELP) + to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).", confidential = TRUE) + return if (src.handle_spam_prevention(msg,MUTE_ADMINHELP)) return //clean the message if it's not sent by a high-rank admin - if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots + if(!check_rights(R_SERVER|R_DEBUG,0)||external)//no sending html to the poor bots msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return @@ -144,28 +157,33 @@ var/keywordparsedmsg = keywords_lookup(msg) - if(irc) - to_chat(src, "PM to-Admins: [rawmsg]") - var/datum/admin_help/AH = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to IRC: [keywordparsedmsg]") + if(external) + to_chat(src, "PM to-Admins: [rawmsg]", confidential = TRUE) + var/datum/admin_help/AH = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]") ircreplyamount-- send2irc("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg) + else - if(recipient.holder) - if(holder) //both are admins - to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]") - to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]") + var/badmin = FALSE //Lets figure out if an admin is getting bwoinked. + if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket. + badmin = TRUE + if(recipient.holder && !badmin) + if(holder) + to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]", confidential = TRUE) + to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]", confidential = TRUE) //omg this is dumb, just fill in both their tickets var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]" admin_ticket_log(src, interaction_message) if(recipient != src) //reeee admin_ticket_log(recipient, interaction_message) - + // SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) else //recipient is an admin but sender is not var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]" admin_ticket_log(src, "[replymsg]") - to_chat(recipient, "[replymsg]") - to_chat(src, "PM to-Admins: [msg]") + to_chat(recipient, "[replymsg]", confidential = TRUE) + to_chat(src, "PM to-Admins: [msg]", confidential = TRUE) + // SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) //play the receiving admin the adminhelp sound (if they have them enabled) if(recipient.prefs.toggles & SOUND_ADMINHELP) @@ -173,78 +191,88 @@ else if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT + //var/already_logged = FALSE if(!recipient.current_ticket) new /datum/admin_help(msg, recipient, TRUE) + //already_logged = TRUE + // SSblackbox.LogAhelp(recipient.current_ticket.id, "Ticket Opened", msg, recipient.ckey, src.ckey) - to_chat(recipient, "-- Administrator private message --") - to_chat(recipient, "Admin PM from-[key_name(src, recipient, 0)]: [msg]") - to_chat(recipient, "Click on the administrator's name to reply.") - to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [msg]") + to_chat(recipient, "-- Administrator private message --", confidential = TRUE) + to_chat(recipient, "Admin PM from-[key_name(src, recipient, 0)]: [msg]", confidential = TRUE) + to_chat(recipient, "Click on the administrator's name to reply.", confidential = TRUE) + to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [msg]", confidential = TRUE) admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]") + // if(!already_logged) //Reply to an existing ticket + // SSblackbox.LogAhelp(recipient.current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) + + //always play non-admin recipients the adminhelp sound SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg')) //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn if(CONFIG_GET(flag/popup_admin_pm)) - spawn() //so we don't hold the caller proc up. Please functionalize this - var/sender = src - var/sendername = key - var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply - if(recipient && reply) - if(sender) - recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them - else - adminhelp(reply) //sender has left, adminhelp instead - return + INVOKE_ASYNC(src, .proc/popup_admin_pm, recipient, msg) else //neither are admins - to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.") + to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.", confidential = TRUE) return - if(irc) - log_admin_private("PM: [key_name(src)]->IRC: [rawmsg]") + if(external) + log_admin_private("PM: [key_name(src)]->External: [rawmsg]") for(var/client/X in GLOB.admins) - to_chat(X, "PM: [key_name(src, X, 0)]->IRC: [keywordparsedmsg]") + to_chat(X, "PM: [key_name(src, X, 0)]->External: [keywordparsedmsg]", confidential = TRUE) else window_flash(recipient, ignorepref = TRUE) log_admin_private("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]") //we don't use message_admins here because the sender/receiver might get it too for(var/client/X in GLOB.admins) if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient - to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" ) + to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" , confidential = TRUE) + +/client/proc/popup_admin_pm(client/recipient, msg) + var/sender = src + var/sendername = key + var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply + if(recipient && reply) + if(sender) + recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them + else + adminhelp(reply) //sender has left, adminhelp instead - -#define IRC_AHELP_USAGE "Usage: ticket " /proc/IrcPm(target,msg,sender) + return TgsPm(target,msg,sender) //compatability moment. + +#define TGS_AHELP_USAGE "Usage: ticket " +/proc/TgsPm(target,msg,sender) target = ckey(target) var/client/C = GLOB.directory[target] var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target) var/compliant_msg = trim(lowertext(msg)) - var/irc_tagged = "[sender](IRC)" + var/tgs_tagged = "[sender](TGS/External)" var/list/splits = splittext(compliant_msg, " ") if(splits.len && splits[1] == "ticket") if(splits.len < 2) - return IRC_AHELP_USAGE + return TGS_AHELP_USAGE switch(splits[2]) if("close") if(ticket) - ticket.Close(irc_tagged) + ticket.Close(tgs_tagged) return "Ticket #[ticket.id] successfully closed" if("resolve") if(ticket) - ticket.Resolve(irc_tagged) + ticket.Resolve(tgs_tagged) return "Ticket #[ticket.id] successfully resolved" if("icissue") if(ticket) - ticket.ICIssue(irc_tagged) + ticket.ICIssue(tgs_tagged) return "Ticket #[ticket.id] successfully marked as IC issue" if("reject") if(ticket) - ticket.Reject(irc_tagged) + ticket.Reject(tgs_tagged) return "Ticket #[ticket.id] successfully rejected" if("reopen") if(ticket) @@ -253,7 +281,7 @@ if(!isnull(fail)) fail = text2num(splits[3]) if(isnull(fail)) - return "Error: No/Invalid ticket id specified. [IRC_AHELP_USAGE]" + return "Error: No/Invalid ticket id specified. [TGS_AHELP_USAGE]" var/datum/admin_help/AH = GLOB.ahelp_tickets.TicketByID(fail) if(!AH) return "Error: Ticket #[fail] not found" @@ -275,41 +303,42 @@ . += "#[AH.id]" return else - return IRC_AHELP_USAGE + return TGS_AHELP_USAGE return "Error: Ticket could not be found" var/static/stealthkey - var/adminname = CONFIG_GET(flag/show_irc_name) ? irc_tagged : "Administrator" + var/adminname = CONFIG_GET(flag/show_irc_name) ? tgs_tagged : "Administrator" if(!C) return "Error: No client" if(!stealthkey) - stealthkey = GenIrcStealthKey() + stealthkey = GenTgsStealthKey() msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return "Error: No message" - message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]") - log_admin_private("IRC PM: [sender] -> [key_name(C)] : [msg]") + message_admins("External message from [sender] to [key_name_admin(C)] : [msg]") + log_admin_private("External PM: [sender] -> [key_name(C)] : [msg]") msg = emoji_parse(msg) - to_chat(C, "-- Administrator private message --") - to_chat(C, "Admin PM from-[adminname]: [msg]") - to_chat(C, "Click on the administrator's name to reply.") + to_chat(C, "-- Administrator private message --", confidential = TRUE) + to_chat(C, "Admin PM from-[adminname]: [msg]", confidential = TRUE) + to_chat(C, "Click on the administrator's name to reply.", confidential = TRUE) - admin_ticket_log(C, "PM From [irc_tagged]: [msg]") + admin_ticket_log(C, "PM From [tgs_tagged]: [msg]") window_flash(C, ignorepref = TRUE) //always play non-admin recipients the adminhelp sound SEND_SOUND(C, 'sound/effects/adminhelp.ogg') - C.ircreplyamount = IRCREPLYCOUNT + // C.externalreplyamount = EXTERNALREPLYCOUNT + C.ircreplyamount = EXTERNALREPLYCOUNT return "Message Successful" -/proc/GenIrcStealthKey() +/proc/GenTgsStealthKey() var/num = (rand(0,1000)) var/i = 0 while(i == 0) @@ -322,4 +351,4 @@ GLOB.stealthminID["IRCKEY"] = stealth return stealth -#undef IRCREPLYCOUNT +#undef EXTERNALREPLYCOUNT diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 9081357ef6..66653020d4 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -13,7 +13,7 @@ msg = keywords_lookup(msg) msg = "ADMIN: [key_name(usr, 1)] [ADMIN_FLW(mob)]: [msg]" - to_chat(GLOB.admins, msg) + to_chat(GLOB.admins, msg, confidential = TRUE) SSblackbox.record_feedback("tally", "admin_verb", 1, "Asay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/bluespacearty.dm b/code/modules/admin/verbs/bluespacearty.dm index 2910d6dd85..23fff5ece9 100644 --- a/code/modules/admin/verbs/bluespacearty.dm +++ b/code/modules/admin/verbs/bluespacearty.dm @@ -5,7 +5,7 @@ var/mob/living/target = M if(!isliving(target)) - to_chat(usr, "This can only be used on instances of type /mob/living") + to_chat(usr, "This can only be used on instances of type /mob/living", confidential = TRUE) return explosion(target.loc, 0, 0, 0, 0) diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm index 35f4ddb3e5..be22c889f0 100644 --- a/code/modules/admin/verbs/borgpanel.dm +++ b/code/modules/admin/verbs/borgpanel.dm @@ -7,9 +7,9 @@ return if (!istype(borgo, /mob/living/silicon/robot)) - borgo = input("Select a borg", "Select a borg", null, null) as null|anything in GLOB.silicon_mobs + borgo = input("Select a borg", "Select a borg", null, null) as null|anything in sortNames(GLOB.silicon_mobs) if (!istype(borgo, /mob/living/silicon/robot)) - to_chat(usr, "Borg is required for borgpanel") + to_chat(usr, "Borg is required for borgpanel", confidential = TRUE) var/datum/borgpanel/borgpanel = new(usr, borgo) @@ -25,18 +25,18 @@ if(!istype(to_borg)) qdel(src) CRASH("Borg panel is only available for borgs") - user = CLIENT_FROM_VAR(to_user) - if (!user) CRASH("Borg panel attempted to open to a mob without a client") - borg = to_borg -/datum/borgpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/borgpanel/ui_state(mob/user) + return GLOB.admin_state + +/datum/borgpanel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "BorgPanel", "Borg Panel", 700, 700, master_ui, state) + ui = new(user, src, "BorgPanel") ui.open() /datum/borgpanel/ui_data(mob/user) @@ -53,13 +53,13 @@ .["upgrades"] = list() for (var/upgradetype in subtypesof(/obj/item/borg/upgrade)-/obj/item/borg/upgrade/hypospray) //hypospray is a dummy parent for hypospray upgrades var/obj/item/borg/upgrade/upgrade = upgradetype - if (initial(upgrade.module_type) && !istype(borg.module, initial(upgrade.module_type))) // Upgrade requires a different module + if (initial(upgrade.module_type) && !is_type_in_list(borg.module, initial(upgrade.module_type))) // Upgrade requires a different module continue var/installed = FALSE if (locate(upgradetype) in borg) installed = TRUE .["upgrades"] += list(list("name" = initial(upgrade.name), "installed" = installed, "type" = upgradetype)) - .["laws"] = borg.laws ? borg.laws.get_law_list(include_zeroth = TRUE) : list() + .["laws"] = borg.laws ? borg.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE) : list() .["channels"] = list() for (var/k in GLOB.radiochannels) if (k == RADIO_CHANNEL_COMMON) @@ -199,7 +199,7 @@ borg.notify_ai(DISCONNECT) if(borg.shell) borg.undeploy() - borg.connected_ai = newai + borg.set_connected_ai(newai) borg.notify_ai(TRUE) message_admins("[key_name_admin(user)] slaved [ADMIN_LOOKUPFLW(borg)] to the AI [ADMIN_LOOKUPFLW(newai)].") log_admin("[key_name(user)] slaved [key_name(borg)] to the AI [key_name(newai)].") @@ -207,7 +207,7 @@ borg.notify_ai(DISCONNECT) if(borg.shell) borg.undeploy() - borg.connected_ai = null + borg.set_connected_ai(null) message_admins("[key_name_admin(user)] freed [ADMIN_LOOKUPFLW(borg)] from being slaved to an AI.") log_admin("[key_name(user)] freed [key_name(borg)] from being slaved to an AI.") if (borg.lawupdate) diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index 4df6f22686..66acc0f667 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -2,16 +2,16 @@ set category = "Special Verbs" set name = "Dsay" set hidden = 1 - if(!src.holder) - to_chat(src, "Only administrators may use this command.") + if(!holder) + to_chat(src, "Only administrators may use this command.", confidential = TRUE) return - if(!src.mob) + if(!mob) return if(prefs.muted & MUTE_DEADCHAT) - to_chat(src, "You cannot send DSAY messages (muted).") + to_chat(src, "You cannot send DSAY messages (muted).", confidential = TRUE) return - if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) + if (handle_spam_prevention(msg,MUTE_DEADCHAT)) return msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN) @@ -23,14 +23,25 @@ var/rendered = "DEAD: [uppertext(holder.rank)]([src.holder.fakekey ? pick(nicknames) : src.key]) says, \"[emoji_parse(msg)]\"" + // var/rank_name = holder.rank + // var/admin_name = key + // if(holder.fakekey) + // rank_name = pick(strings("admin_nicknames.json", "ranks", "config")) please use this soon. + // admin_name = pick(strings("admin_nicknames.json", "names", "config")) + // var/rendered = "DEAD: [rank_name]([admin_name]) says, \"[emoji_parse(msg)]\"" + for (var/mob/M in GLOB.player_list) if(isnewplayer(M)) continue - if (M.stat == DEAD || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above - to_chat(M, rendered) + if (M.stat == DEAD || (M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above + to_chat(M, rendered, confidential = TRUE) SSblackbox.record_feedback("tally", "admin_verb", 1, "Dsay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/get_dead_say() - var/msg = input(src, null, "dsay \"text\"") as text + var/msg = input(src, null, "dsay \"text\"") as text|null + + if (isnull(msg)) + return + dsay(msg) diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm index 21a722d32f..4cbb0214f7 100644 --- a/code/modules/admin/verbs/getlogs.dm +++ b/code/modules/admin/verbs/getlogs.dm @@ -31,5 +31,5 @@ src << ftp(file(path)) else return - to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.") - return \ No newline at end of file + to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.", confidential = TRUE) + return diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 35ab3927d4..0dfee4c38c 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -205,15 +205,15 @@ GLOBAL_LIST_EMPTY(dirty_vars) set name = "Debug verbs - Enable" if(!check_rights(R_DEBUG)) return - verbs -= /client/proc/enable_debug_verbs - verbs.Add(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping) + remove_verb(src, /client/proc/enable_debug_verbs) + add_verb(src, list(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)) SSblackbox.record_feedback("tally", "admin_verb", 1, "Enable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/disable_debug_verbs() set category = "Debug" set name = "Debug verbs - Disable" - verbs.Remove(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping) - verbs += /client/proc/enable_debug_verbs + remove_verb(src, list(/client/proc/disable_debug_verbs, GLOB.admin_verbs_debug_mapping)) + add_verb(src, /client/proc/enable_debug_verbs) SSblackbox.record_feedback("tally", "admin_verb", 1, "Disable Debug Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/count_objects_on_z_level() diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index e7b9342645..fc2ba55f54 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -34,9 +34,7 @@ for(var/mob/M in GLOB.player_list) if(M.client.prefs.toggles & SOUND_MIDI) - var/user_vol = M.client.chatOutput.adminMusicVolume - if(user_vol) - admin_sound.volume = vol * (user_vol / 100) + admin_sound.volume = vol * M.client.admin_music_volume SEND_SOUND(M, admin_sound) admin_sound.volume = vol @@ -69,7 +67,7 @@ if(istext(web_sound_input)) var/web_sound_url = "" var/stop_web_sounds = FALSE - var/pitch + var/list/music_extra_data = list() if(length(web_sound_input)) web_sound_input = trim(web_sound_input) @@ -97,11 +95,10 @@ var/webpage_url = title if (data["webpage_url"]) webpage_url = "[title]" - - var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num - if(!freq) - freq = 1 - pitch = freq + music_extra_data["start"] = data["start_time"] + music_extra_data["end"] = data["end_time"] + music_extra_data["link"] = data["webpage_url"] + music_extra_data["title"] = data["title"] var/res = alert(usr, "Show the title of and link to this song to the players?\n[title]",, "No", "Yes", "Cancel") switch(res) @@ -130,11 +127,11 @@ for(var/m in GLOB.player_list) var/mob/M = m var/client/C = M.client - if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) + if(C.prefs.toggles & SOUND_MIDI) if(!stop_web_sounds) - C.chatOutput.sendMusic(web_sound_url, pitch) + C.tgui_panel?.play_music(web_sound_url, music_extra_data) else - C.chatOutput.stopMusic() + C.tgui_panel?.stop_music() SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Internet Sound") @@ -144,7 +141,7 @@ if(!check_rights(R_SOUNDS)) return - var/web_sound_input = input("Enter content stream URL (fetch this from local youtube-dl!)", "Play Internet Sound via direct URL") as text|null + var/web_sound_input = input("Enter content stream URL (must be a direct link)", "Play Internet Sound via direct URL") as text|null if(istext(web_sound_input)) if(!length(web_sound_input)) log_admin("[key_name(src)] stopped web sound") @@ -152,34 +149,37 @@ var/mob/M for(var/i in GLOB.player_list) M = i - M?.client?.chatOutput?.stopMusic() + M?.client?.tgui_panel?.stop_music() return - else - if(web_sound_input && !findtext(web_sound_input, GLOB.is_http_protocol)) - to_chat(src, "BLOCKED: Content URL not using http(s) protocol") - return - var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num - if(isnull(freq)) - return - if(!freq) - freq = 1 - SSblackbox.record_feedback("nested tally", "played_url", 1, list("[ckey]", "[web_sound_input]")) - var/logstr = "[key_name(src)] played web sound at freq [freq]: [web_sound_input]" - log_admin(logstr) - message_admins(logstr) - var/mob/M - var/client/C - var/datum/chatOutput/O - for(var/i in GLOB.player_list) - M = i - C = M.client - if(!(C?.prefs?.toggles & SOUND_MIDI)) - continue - O = C.chatOutput - if(!O || O.broken || !O.loaded) - continue - O.sendMusic(web_sound_input, freq) - SSblackbox.record_feedback("tally", "admin_verb", 1, "Manual Play Internet Sound") + + var/list/music_extra_data = list() + web_sound_input = trim(web_sound_input) + if(web_sound_input && (findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol))) + to_chat(src, "Non-http(s) URIs are not allowed.", confidential = TRUE) + return + + var/list/explode = splittext(web_sound_input, "/") //if url=="https://fixthisshit.com/pogchamp.ogg"then title="pogchamp.ogg" + var/title = "[explode[explode.len]]" + + if(!findtext(title, ".mp3") && !findtext(title, ".mp4")) // IE sucks. + to_chat(src, "The format is not .mp3/.mp4, IE 8 and above can only support the .mp3/.mp4 format, the music might not play.", confidential = TRUE) + + if(length(title) > 50) //kev no. + title = "Unknown.mp3" + + music_extra_data["title"] = title + + SSblackbox.record_feedback("nested tally", "played_url", 1, list("[ckey]", "[web_sound_input]")) + log_admin("[key_name(src)] played web sound: [web_sound_input]") + message_admins("[key_name(src)] played web sound: [web_sound_input]") + + for(var/m in GLOB.player_list) + var/mob/M = m + var/client/C = M.client + if(C.prefs.toggles & SOUND_MIDI) + C.tgui_panel?.play_music(web_sound_input, music_extra_data) + + SSblackbox.record_feedback("tally", "admin_verb", 1, "Manual Play Internet Sound") /client/proc/set_round_end_sound(S as sound) set category = "Fun" @@ -193,42 +193,6 @@ message_admins("[key_name_admin(src)] set the round end sound to [S]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Round End Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/play_web_sound_manual() - set category = "Fun" - set name = "Manual Play Internet Sound" - if(!check_rights(R_SOUNDS)) - return - - var/web_sound_input = input("Enter youtube-dl fetched content URL (supported sites only, leave blank to stop playing)", "Send youtube-dl media link") as text|null - if(!istext(web_sound_input)) - return - web_sound_input = trim(web_sound_input) - if(!length(web_sound_input)) - log_admin("[key_name(src)] stopped web sound") - message_admins("[key_name(src)] stopped web sound") - for(var/m in GLOB.player_list) - var/mob/M = m - var/client/C = M.client - if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) - C.chatOutput.stopMusic() - return - var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num - if(!freq) - return - if(web_sound_input && !findtext(web_sound_input, GLOB.is_http_protocol)) - to_chat(src, "BLOCKED: Content URL not using http(s) protocol") - to_chat(src, "The media provider returned a content URL that isn't using the HTTP or HTTPS protocol") - return - - SSblackbox.record_feedback("nested tally", "played_url_manual", 1, list("[ckey]", "[web_sound_input]")) - log_admin("[key_name(src)] manually played web sound: [web_sound_input]") - message_admins("[key_name(src)] manually played web sound: HREF") - for(var/m in GLOB.player_list) - var/mob/M = m - var/client/C = M.client - if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) - C.chatOutput.sendMusic(web_sound_input, freq) - /client/proc/stop_sounds() set category = "Debug" set name = "Stop All Playing Sounds" @@ -238,9 +202,7 @@ log_admin("[key_name(src)] stopped all currently playing sounds.") message_admins("[key_name_admin(src)] stopped all currently playing sounds.") for(var/mob/M in GLOB.player_list) - if(M.client) - SEND_SOUND(M, sound(null)) - var/client/C = M.client - if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) - C.chatOutput.stopMusic() + SEND_SOUND(M, sound(null)) + var/client/C = M.client + C?.tgui_panel?.stop_music() SSblackbox.record_feedback("tally", "admin_verb", 1, "Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm index 445de4c40f..ee4d12656a 100644 --- a/code/modules/admin/verbs/possess.dm +++ b/code/modules/admin/verbs/possess.dm @@ -48,6 +48,6 @@ set desc = "Give this guy possess/release verbs" set category = "Debug" set name = "Give Possessing Verbs" - M.verbs += /proc/possess - M.verbs += /proc/release + add_verb(M, /proc/possess) + add_verb(M, /proc/release) SSblackbox.record_feedback("tally", "admin_verb", 1, "Give Possessing Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/view_variables/mass_edit_variables.dm b/code/modules/admin/view_variables/mass_edit_variables.dm index 4e78e1aed7..a498868436 100644 --- a/code/modules/admin/view_variables/mass_edit_variables.dm +++ b/code/modules/admin/view_variables/mass_edit_variables.dm @@ -38,7 +38,7 @@ var/var_value = O.vars[variable] if(variable in GLOB.VVckey_edit) - to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.") + to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.", confidential = TRUE) return if(variable in GLOB.VVlocked) if(!check_rights(R_DEBUG)) @@ -56,11 +56,11 @@ default = vv_get_class(variable, var_value) if(isnull(default)) - to_chat(src, "Unable to determine variable type.") + to_chat(src, "Unable to determine variable type.", confidential = TRUE) else - to_chat(src, "Variable appears to be [uppertext(default)].") + to_chat(src, "Variable appears to be [uppertext(default)].", confidential = TRUE) - to_chat(src, "Variable contains: [var_value]") + to_chat(src, "Variable contains: [var_value]", confidential = TRUE) if(default == VV_NUM) var/dir_text = "" @@ -75,7 +75,7 @@ dir_text += "WEST" if(dir_text) - to_chat(src, "If a direction, direction is: [dir_text]") + to_chat(src, "If a direction, direction is: [dir_text]", confidential = TRUE) var/value = vv_get_value(default_class = default) var/new_value = value["value"] @@ -97,9 +97,9 @@ switch(class) if(VV_RESTORE_DEFAULT) - to_chat(src, "Finding items...") + to_chat(src, "Finding items...", confidential = TRUE) var/list/items = get_all_of_type(O.type, method) - to_chat(src, "Changing [items.len] items...") + to_chat(src, "Changing [items.len] items...", confidential = TRUE) for(var/thing in items) if (!thing) continue @@ -123,9 +123,9 @@ for(var/V in varsvars) new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]") - to_chat(src, "Finding items...") + to_chat(src, "Finding items...", confidential = TRUE) var/list/items = get_all_of_type(O.type, method) - to_chat(src, "Changing [items.len] items...") + to_chat(src, "Changing [items.len] items...", confidential = TRUE) for(var/thing in items) if (!thing) continue @@ -151,9 +151,9 @@ many = FALSE var/type = value["type"] - to_chat(src, "Finding items...") + to_chat(src, "Finding items...", confidential = TRUE) var/list/items = get_all_of_type(O.type, method) - to_chat(src, "Changing [items.len] items...") + to_chat(src, "Changing [items.len] items...", confidential = TRUE) for(var/thing in items) if (!thing) continue @@ -169,9 +169,9 @@ CHECK_TICK else - to_chat(src, "Finding items...") + to_chat(src, "Finding items...", confidential = TRUE) var/list/items = get_all_of_type(O.type, method) - to_chat(src, "Changing [items.len] items...") + to_chat(src, "Changing [items.len] items...", confidential = TRUE) for(var/thing in items) if (!thing) continue @@ -185,20 +185,20 @@ var/count = rejected+accepted if (!count) - to_chat(src, "No objects found") + to_chat(src, "No objects found", confidential = TRUE) return if (!accepted) - to_chat(src, "Every object rejected your edit") + to_chat(src, "Every object rejected your edit", confidential = TRUE) return if (rejected) - to_chat(src, "[rejected] out of [count] objects rejected your edit") + to_chat(src, "[rejected] out of [count] objects rejected your edit", confidential = TRUE) log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])") log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)") message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)") //not using global lists as vv is a debug function and debug functions should rely on as less things as possible. -/proc/get_all_of_type(var/T, subtypes = TRUE) +/proc/get_all_of_type(T, subtypes = TRUE) var/list/typecache = list() typecache[T] = 1 if (subtypes) @@ -253,7 +253,7 @@ CHECK_TICK else if (ispath(T, /client)) - for(var/client/thing in world) + for(var/client/thing in GLOB.clients) if (typecache[thing.type]) . += thing CHECK_TICK diff --git a/code/modules/admin/view_variables/modify_variables.dm b/code/modules/admin/view_variables/modify_variables.dm index 5f80b3a5e4..a8871a6467 100644 --- a/code/modules/admin/view_variables/modify_variables.dm +++ b/code/modules/admin/view_variables/modify_variables.dm @@ -17,7 +17,7 @@ GLOBAL_PROTECT(VVpixelmovement) //FALSE = no subtypes, strict exact type pathing (or the type doesn't have subtypes) //TRUE = Yes subtypes //NULL = User cancelled at the prompt or invalid type given -/client/proc/vv_subtype_prompt(var/type) +/client/proc/vv_subtype_prompt(type) if (!ispath(type)) return var/list/subtypes = subtypesof(type) @@ -102,7 +102,7 @@ GLOBAL_PROTECT(VVpixelmovement) L[var_value] = mod_list_add_ass(O) //hehe if (O) if (O.vv_edit_var(objectvar, L) == FALSE) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: ADDED=[var_value]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]") @@ -112,7 +112,7 @@ GLOBAL_PROTECT(VVpixelmovement) if(!check_rights(R_VAREDIT)) return if(!istype(L, /list)) - to_chat(src, "Not a List.") + to_chat(src, "Not a List.", confidential = TRUE) return if(L.len > 1000) @@ -121,7 +121,6 @@ GLOBAL_PROTECT(VVpixelmovement) return var/is_normal_list = IS_NORMAL_LIST(L) - var/list/names = list() for (var/i in 1 to L.len) var/key = L[i] @@ -145,7 +144,7 @@ GLOBAL_PROTECT(VVpixelmovement) L = L.Copy() listclearnulls(L) if (!O.vv_edit_var(objectvar, L)) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR NULLS") @@ -155,7 +154,7 @@ GLOBAL_PROTECT(VVpixelmovement) if(variable == "(CLEAR DUPES)") L = uniqueList(L) if (!O.vv_edit_var(objectvar, L)) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR DUPES") @@ -165,7 +164,7 @@ GLOBAL_PROTECT(VVpixelmovement) if(variable == "(SHUFFLE)") L = shuffle(L) if (!O.vv_edit_var(objectvar, L)) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: SHUFFLE") @@ -202,9 +201,9 @@ GLOBAL_PROTECT(VVpixelmovement) default = vv_get_class(objectvar, variable) - to_chat(src, "Variable appears to be [uppertext(default)].") + to_chat(src, "Variable appears to be [uppertext(default)].", confidential = TRUE) - to_chat(src, "Variable contains: [variable]") + to_chat(src, "Variable contains: [variable]", confidential = TRUE) if(default == VV_NUM) var/dir_text = "" @@ -220,7 +219,7 @@ GLOBAL_PROTECT(VVpixelmovement) dir_text += "WEST" if(dir_text) - to_chat(usr, "If a direction, direction is: [dir_text]") + to_chat(usr, "If a direction, direction is: [dir_text]", confidential = TRUE) var/original_var = variable @@ -248,7 +247,7 @@ GLOBAL_PROTECT(VVpixelmovement) L.Cut(index, index+1) if (O) if (O.vv_edit_var(objectvar, L)) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]") @@ -260,6 +259,7 @@ GLOBAL_PROTECT(VVpixelmovement) for(var/V in varsvars) new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]") + if(is_normal_list) if(assoc) L[assoc_key] = new_var @@ -269,7 +269,7 @@ GLOBAL_PROTECT(VVpixelmovement) L[new_var] = old_assoc_value if (O) if (O.vv_edit_var(objectvar, L) == FALSE) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]") log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") @@ -297,7 +297,7 @@ GLOBAL_PROTECT(VVpixelmovement) if(param_var_name) if(!(param_var_name in O.vars)) - to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])") + to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])", confidential = TRUE) return variable = param_var_name @@ -322,11 +322,11 @@ GLOBAL_PROTECT(VVpixelmovement) var/default = vv_get_class(variable, var_value) if(isnull(default)) - to_chat(src, "Unable to determine variable type.") + to_chat(src, "Unable to determine variable type.", confidential = TRUE) else - to_chat(src, "Variable appears to be [uppertext(default)].") + to_chat(src, "Variable appears to be [uppertext(default)].", confidential = TRUE) - to_chat(src, "Variable contains: [var_value]") + to_chat(src, "Variable contains: [var_value]", confidential = TRUE) if(default == VV_NUM) var/dir_text = "" @@ -341,7 +341,7 @@ GLOBAL_PROTECT(VVpixelmovement) dir_text += "WEST" if(dir_text) - to_chat(src, "If a direction, direction is: [dir_text]") + to_chat(src, "If a direction, direction is: [dir_text]", confidential = TRUE) if(autodetect_class && default != VV_NULL) if (default == VV_TEXT) @@ -378,7 +378,7 @@ GLOBAL_PROTECT(VVpixelmovement) if (O.vv_edit_var(variable, var_new) == FALSE) - to_chat(src, "Your edit was rejected by the object.") + to_chat(src, "Your edit was rejected by the object.", confidential = TRUE) return vv_update_display(O, "varedited", VV_MSG_EDITED) log_world("### VarEdit by [key_name(src)]: [O.type] [variable]=[var_value] => [var_new]") diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index 626e75fa10..9f61781f01 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -25,7 +25,7 @@ var/mob/M = locate(href_list["rename"]) in GLOB.mob_list if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") + to_chat(usr, "This can only be used on instances of type /mob", confidential = TRUE) return var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN) @@ -43,7 +43,7 @@ var/atom/A = locate(href_list["rotatedatum"]) if(!istype(A)) - to_chat(usr, "This can only be done to instances of type /atom") + to_chat(usr, "This can only be done to instances of type /atom", confidential = TRUE) return switch(href_list["rotatedir"]) @@ -60,13 +60,13 @@ var/mob/living/carbon/monkey/Mo = locate(href_list["makehuman"]) in GLOB.mob_list if(!istype(Mo)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey") + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey", confidential = TRUE) return if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return if(!Mo) - to_chat(usr, "Mob doesn't exist anymore") + to_chat(usr, "Mob doesn't exist anymore", confidential = TRUE) return holder.Topic(href, list("humanone"=href_list["makehuman"])) @@ -80,10 +80,13 @@ var/Text = href_list["adjustDamage"] - var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num + var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num|null + + if (isnull(amount)) + return if(!L) - to_chat(usr, "Mob doesn't exist anymore") + to_chat(usr, "Mob doesn't exist anymore", confidential = TRUE) return var/newamt @@ -110,7 +113,7 @@ L.adjustStaminaLoss(amount) newamt = L.getStaminaLoss() else - to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") + to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]", confidential = TRUE) return if(amount != 0) @@ -124,5 +127,5 @@ //Finally, refresh if something modified the list. if(href_list["datumrefresh"]) var/datum/DAT = locate(href_list["datumrefresh"]) - if(istype(DAT, /datum) || istype(DAT, /client)) + if(istype(DAT, /datum) || istype(DAT, /client) || islist(DAT)) debug_variables(DAT) diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm index 9ee7103562..b5d7632515 100644 --- a/code/modules/admin/view_variables/topic_basic.dm +++ b/code/modules/admin/view_variables/topic_basic.dm @@ -34,11 +34,11 @@ if (!C) return if(!target) - to_chat(usr, "The object you tried to expose to [C] no longer exists (nulled or hard-deled)") + to_chat(usr, "The object you tried to expose to [C] no longer exists (nulled or hard-deled)", confidential = TRUE) return message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a VV window") log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [target]") - to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window") + to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window", confidential = TRUE) C.debug_variables(target) if(check_rights(R_DEBUG)) if(href_list[VV_HK_DELETE]) @@ -46,31 +46,33 @@ if (isturf(src)) // show the turf that took its place usr.client.debug_variables(src) return - #ifdef REFERENCE_TRACKING - if(href_list[VV_HK_VIEW_REFERENCES]) - var/datum/D = locate(href_list[VV_HK_TARGET]) - if(!D) - to_chat(usr, "Unable to locate item.") + + #ifdef REFERENCE_TRACKING //people with debug can only access this putnam! + if(href_list[VV_HK_VIEW_REFERENCES]) + var/datum/D = locate(href_list[VV_HK_TARGET]) + if(!D) + to_chat(usr, "Unable to locate item.") + return + usr.client.holder.view_refs(target) return - usr.client.holder.view_refs(target) - return - #endif + #endif + if(href_list[VV_HK_MARK]) usr.client.mark_datum(target) if(href_list[VV_HK_ADDCOMPONENT]) if(!check_rights(NONE)) return var/list/names = list() - var/list/componentsubtypes = subtypesof(/datum/component) + var/list/componentsubtypes = sortList(subtypesof(/datum/component), /proc/cmp_typepaths_asc) names += "---Components---" names += componentsubtypes names += "---Elements---" - names += subtypesof(/datum/element) + names += sortList(subtypesof(/datum/element), /proc/cmp_typepaths_asc) var/result = input(usr, "Choose a component/element to add","better know what ur fuckin doin pal") as null|anything in names if(!usr || !result || result == "---Components---" || result == "---Elements---") return if(QDELETED(src)) - to_chat(usr, "That thing doesn't exist anymore!") + to_chat(usr, "That thing doesn't exist anymore!", confidential = TRUE) return var/list/lst = get_callproc_args() if(!lst) @@ -83,7 +85,7 @@ else datumname = "element" target._AddElement(lst) - log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(src)].") - message_admins("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(src)].") + log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(target)].") + message_admins("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(target)].") if(href_list[VV_HK_CALLPROC]) usr.client.callproc_datum(target) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index a4dff725f7..3851008d86 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -1,4 +1,3 @@ - /client/proc/debug_variables(datum/D in world) set category = "Debug" set name = "View Variables" @@ -6,7 +5,7 @@ var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. if(!usr.client || !usr.client.holder) //This is usr because admins can call the proc on other clients, even if they're not admins, to show them VVs. - to_chat(usr, "You need to be an administrator to access this.") + to_chat(usr, "You need to be an administrator to access this.", confidential = TRUE) return if(!D) @@ -26,7 +25,6 @@ if(istype(D, /atom)) sprite = getFlatIcon(D) - hash = md5(sprite) if(sprite) hash = md5(sprite) src << browse_rsc(sprite, "vv[hash].png") @@ -97,7 +95,7 @@ [title] - + - \ No newline at end of file + diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 2b43319904..0c6ca13e86 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -1,6 +1,6 @@ /turf //used for temperature calculations - var/thermal_conductivity = 0.05 + var/thermal_conductivity = 0.005 var/heat_capacity = 1 var/temperature_archived @@ -270,7 +270,7 @@ /turf/proc/super_conduct() var/conductivity_directions = conductivity_directions() - + archive() if(conductivity_directions) //Conduct with tiles around me for(var/direction in GLOB.cardinals) @@ -331,6 +331,7 @@ var/heat = thermal_conductivity*delta_temperature* \ (heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM)) temperature -= heat/heat_capacity + temperature = max(temperature,T0C) //otherwise we just sorta get stuck at super cold temps forever /turf/open/proc/temperature_share_open_to_solid(turf/sharer) sharer.temperature = air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity) @@ -344,3 +345,5 @@ temperature -= heat/heat_capacity sharer.temperature += heat/sharer.heat_capacity + temperature = max(temperature,T0C) + sharer.temperature = max(sharer.temperature,T0C) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index e86b249be6..3cc597ec31 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length //Returns: amount of gas exchanged (+ if sharer received) -/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) +/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient,temperature=null,heat_capacity=null) //Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length //Returns: new temperature of the sharer @@ -196,7 +196,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //Compares sample to self to see if within acceptable ranges that group processing may be enabled //Returns: a string indicating what check failed, or "" if check passes -/datum/gas_mixture/proc/react(turf/open/dump_location) +/datum/gas_mixture/proc/react(datum/holder) //Performs various reactions such as combustion or fusion (LOL) //Returns: 1 if any reaction took place; 0 otherwise @@ -243,7 +243,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) set_moles(path, text2num(gas[id])) archive() return 1 - +/* /datum/gas_mixture/react(datum/holder) . = NO_REACTION if(!total_moles()) @@ -291,7 +291,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) . |= reaction.react(src, holder) if (. & STOP_REACTIONS) break - +*/ //Takes the amount of the gas you want to PP as an argument //So I don't have to do some hacky switches/defines/magic strings //eg: diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index c0f66be7de..7f073567c5 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -40,6 +40,9 @@ /datum/gas_reaction/proc/react(datum/gas_mixture/air, atom/location) return NO_REACTION +/datum/gas_reaction/proc/test() + return list("success" = TRUE) + /datum/gas_reaction/nobliumsupression priority = INFINITY name = "Hyper-Noblium Reaction Suppression" @@ -70,6 +73,8 @@ air.adjust_moles(/datum/gas/water_vapor,-MOLES_GAS_VISIBLE) . = REACTING +// no test cause it's entirely based on location + //tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic /datum/gas_reaction/tritfire priority = -1 //fire should ALWAYS be last, but tritium fires happen before plasma fires @@ -126,6 +131,18 @@ return cached_results["fire"] ? REACTING : NO_REACTION +/datum/gas_reaction/tritfire/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/tritium,50) + G.set_moles(/datum/gas/oxygen,50) + G.set_temperature(500) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(!G.reaction_results["fire"]) + return list("success" = FALSE, "message" = "Trit fires aren't setting fire results correctly!") + return ..() + //plasma combustion: combustion of oxygen and plasma (treated as hydrocarbons). creates hotspots. exothermic /datum/gas_reaction/plasmafire priority = -2 //fire should ALWAYS be last, but plasma fires happen after tritium fires @@ -198,6 +215,28 @@ return cached_results["fire"] ? REACTING : NO_REACTION +/datum/gas_reaction/plasmafire/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/plasma,50) + G.set_moles(/datum/gas/oxygen,50) + G.set_volume(1000) + G.set_temperature(500) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(!G.reaction_results["fire"]) + return list("success" = FALSE, "message" = "Plasma fires aren't setting fire results correctly!") + if(!G.get_moles(/datum/gas/carbon_dioxide)) + return list("success" = FALSE, "message" = "Plasma fires aren't making CO2!") + G.clear() + G.set_moles(/datum/gas/plasma,10) + G.set_moles(/datum/gas/oxygen,1000) + G.set_temperature(500) + result = G.react() + if(!G.get_moles(/datum/gas/tritium)) + return list("success" = FALSE, "message" = "Plasma fires aren't making trit!") + return ..() + //fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again! //Fusion Rework Counter: Please increment this if you make a major overhaul to this system again. //6 reworks @@ -236,7 +275,7 @@ for (var/gas_id in air.get_gases()) gas_power += (gas_fusion_powers[gas_id]*air.get_moles(gas_id)) var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is - cached_scan_results[id] = instability//used for analyzer feedback + cached_scan_results["fusion"] = instability//used for analyzer feedback var/plasma = (initial_plasma-FUSION_MOLE_THRESHOLD)/(scale_factor) //We have to scale the amounts of carbon and plasma down a significant amount in order to show the chaotic dynamics we want var/carbon = (initial_carbon-FUSION_MOLE_THRESHOLD)/(scale_factor) //We also subtract out the threshold amount to make it harder for fusion to burn itself out. @@ -282,6 +321,31 @@ air.set_temperature(clamp(((air.return_temperature()*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)) return REACTING +/datum/gas_reaction/fusion/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/carbon_dioxide,300) + G.set_moles(/datum/gas/plasma,1000) + G.set_moles(/datum/gas/tritium,100.61) + G.set_moles(/datum/gas/nitryl,1) + G.set_temperature(15000) + G.set_volume(1000) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(abs(G.analyzer_results["fusion"] - 3) > 0.0000001) + var/instability = G.analyzer_results["fusion"] + return list("success" = FALSE, "message" = "Fusion is not calculating analyzer results correctly, should be 3.000000045, is instead [instability]") + if(abs(G.get_moles(/datum/gas/plasma) - 850.616) > 0.5) + var/plas = G.get_moles(/datum/gas/plasma) + return list("success" = FALSE, "message" = "Fusion is not calculating plasma correctly, should be 850.616, is instead [plas]") + if(abs(G.get_moles(/datum/gas/carbon_dioxide) - 1699.384) > 0.5) + var/co2 = G.get_moles(/datum/gas/carbon_dioxide) + return list("success" = FALSE, "message" = "Fusion is not calculating co2 correctly, should be 1699.384, is instead [co2]") + if(abs(G.return_temperature() - 27600) > 200) // calculating this manually sucks dude + var/temp = G.return_temperature() + return list("success" = FALSE, "message" = "Fusion is not calculating temperature correctly, should be around 27600, is instead [temp]") + return ..() + /datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst. priority = 3 name = "Nitryl formation" @@ -313,6 +377,20 @@ air.set_temperature(max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB)) return REACTING +/datum/gas_reaction/nitrylformation/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/oxygen,30) + G.set_moles(/datum/gas/nitrogen,30) + G.set_moles(/datum/gas/nitrous_oxide,10) + G.set_volume(1000) + G.set_temperature(150000) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(!G.get_moles(/datum/gas/nitryl) < 0.8) + return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!") + return ..() + /datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic. priority = 4 name = "BZ Gas formation" @@ -348,6 +426,19 @@ air.set_temperature(max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB)) return REACTING +/datum/gas_reaction/bzformation/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/plasma,15) + G.set_moles(/datum/gas/nitrous_oxide,15) + G.set_volume(1000) + G.set_temperature(10) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(!G.get_moles(/datum/gas/bz) < 4) // efficiency is 4.0643 and bz generation == efficiency + return list("success" = FALSE, "message" = "Nitryl isn't being generated correctly!") + return ..() + /datum/gas_reaction/stimformation //Stimulum formation follows a strange pattern of how effective it will be at a given temperature, having some multiple peaks and some large dropoffs. Exo and endo thermic. priority = 5 name = "Stimulum formation" @@ -380,6 +471,23 @@ air.set_temperature(max(((air.return_temperature()*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB)) return REACTING +/datum/gas_reaction/stimformation/test() + //above mentioned "strange pattern" is a basic quintic polynomial, it's fine, can calculate it manually + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/bz,30) + G.set_moles(/datum/gas/plasma,1000) + G.set_moles(/datum/gas/tritium,1000) + G.set_moles(/datum/gas/nitryl,1000) + G.set_volume(1000) + G.set_temperature(12998000) // yeah, really + + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(!G.get_moles(/datum/gas/stimulum) < 900) + return list("success" = FALSE, "message" = "Stimulum isn't being generated correctly!") + return ..() + /datum/gas_reaction/nobliumformation //Hyper-Noblium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic. priority = 6 name = "Hyper-Noblium condensation" @@ -408,6 +516,19 @@ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.set_temperature(max(((air.return_temperature()*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB)) +/datum/gas_reaction/nobliumformation/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/nitrogen,100) + G.set_moles(/datum/gas/tritium,500) + G.set_volume(1000) + G.set_temperature(5000000) // yeah, really + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + if(abs(G.thermal_energy() - 23000000000) > 1000000) // god i hate floating points + return list("success" = FALSE, "message" = "Hyper-nob formation isn't removing the right amount of heat! Should be 23,000,000,000, is instead [G.thermal_energy()]") + return ..() + /datum/gas_reaction/miaster //dry heat sterilization: clears out pathogens in the air priority = -10 //after all the heating from fires etc. is done @@ -433,3 +554,20 @@ //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable air.set_temperature(air.return_temperature() + cleaned_air * 0.002) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists + +/datum/gas_reaction/miaster/test() + var/datum/gas_mixture/G = new + G.set_moles(/datum/gas/miasma,1) + G.set_volume(1000) + G.set_temperature(450) + var/result = G.react() + if(result != REACTING) + return list("success" = FALSE, "message" = "Reaction didn't go at all!") + G.clear() + G.set_moles(/datum/gas/miasma,1) + G.set_temperature(450) + G.set_moles(/datum/gas/water_vapor,0.5) + result = G.react() + if(result != NO_REACTION) + return list("success" = FALSE, "message" = "Miasma sterilization not stopping due to water vapor correctly!") + return ..() diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 098df67321..6c732e3ee1 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -206,7 +206,7 @@ . = other_airs + air if(null in .) stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") - return removeNullsFromList(.) + return listclearnulls(.) /datum/pipeline/proc/reconcile_air() var/list/datum/gas_mixture/GL = list() diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 8476090f75..5540cd7529 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -11,15 +11,15 @@ GLOBAL_LIST_EMPTY(gateway_destinations) /datum/gateway_destination var/name = "Unknown Destination" var/wait = 0 /// How long after roundstart this destination becomes active - var/enabled = TRUE /// If disabled, the destination won't be availible + var/enabled = TRUE /// If disabled, the destination won't be available var/hidden = FALSE /// Will not show on gateway controls at all. /* Can a gateway link to this destination right now. */ -/datum/gateway_destination/proc/is_availible() +/datum/gateway_destination/proc/is_available() return enabled && (world.time - SSticker.round_start_time >= wait) /* Returns user-friendly description why you can't connect to this destination, displayed in UI */ -/datum/gateway_destination/proc/get_availible_reason() +/datum/gateway_destination/proc/get_available_reason() . = "Unreachable" if(world.time - SSticker.round_start_time < wait) . = "Connection desynchronized. Recalibration in progress." @@ -52,8 +52,8 @@ GLOBAL_LIST_EMPTY(gateway_destinations) . = list() .["ref"] = REF(src) .["name"] = name - .["availible"] = is_availible() - .["reason"] = get_availible_reason() + .["available"] = is_available() + .["reason"] = get_available_reason() if(wait) .["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0) @@ -72,10 +72,10 @@ GLOBAL_LIST_EMPTY(gateway_destinations) if(target_gateway.target == deactivated.destination) target_gateway.deactivate() -/datum/gateway_destination/gateway/is_availible() +/datum/gateway_destination/gateway/is_available() return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered() -/datum/gateway_destination/gateway/get_availible_reason() +/datum/gateway_destination/gateway/get_available_reason() . = ..() if(!target_gateway.calibrated) . = "Exit gateway malfunction. Manual recalibration required." @@ -217,8 +217,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations) target = D target.activate(destination) generate_bumper() - if(use_power == IDLE_POWER_USE) - use_power = ACTIVE_POWER_USE + use_power = ACTIVE_POWER_USE update_icon() /obj/machinery/gateway/proc/Transfer(atom/movable/AM) @@ -261,8 +260,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations) if(!GLOB.the_gateway) to_chat(user,"Home gateway is not responding!") if(GLOB.the_gateway.target) - to_chat(user,"Home gateway already in use!") - return + GLOB.the_gateway.deactivate() //this will turn the home gateway off so that it's free for us to connect to activate(GLOB.the_gateway.destination) else deactivate() @@ -319,7 +317,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations) /obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D) if(!D || !G) return - if(!D.is_availible() || G.target) + if(!D.is_available() || G.target) return G.activate(D) diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 505b9a1edc..f13341faf3 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -105,7 +105,7 @@ if("Immortality") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - user.verbs += /mob/living/carbon/proc/immortality + add_verb(user, /mob/living/carbon/proc/immortality) user.set_species(/datum/species/shadow) if("To Kill") to_chat(user, "Your wish is granted, but at a terrible cost...") diff --git a/code/modules/cargo/packs/goodies.dm b/code/modules/cargo/packs/goodies.dm index 5d07e85bac..423d2fc743 100644 --- a/code/modules/cargo/packs/goodies.dm +++ b/code/modules/cargo/packs/goodies.dm @@ -52,8 +52,8 @@ cost = 300 contains = list(/obj/item/storage/toolbox/mechanical) -/datum/supply_pack/goody/electrical_toolbox // mostly just to water down coupon probability - name = "Mechanical Toolbox" +/datum/supply_pack/goody/electrical_toolbox + name = "Electrical Toolbox" desc = "A fully stocked electrical toolbox, for when you're too lazy to just print them out." cost = 300 contains = list(/obj/item/storage/toolbox/electrical) diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm index c6728831eb..394b86bb81 100644 --- a/code/modules/cargo/packs/misc.dm +++ b/code/modules/cargo/packs/misc.dm @@ -13,6 +13,13 @@ //////////////////// Paperwork and Writing Supplies ////////////////////////// ////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/misc/anvil + name = "Anvil Crate" + desc = "An anvil in a crate, we had to dig this out of the old warehouse. It's got wheels on it so you can move it." + cost = 7500 + contains = list(/obj/structure/anvil/obtainable/basic) + /datum/supply_pack/misc/artsupply name = "Art Supplies" desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!" diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index fd6fee362d..125bfe2034 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -192,3 +192,49 @@ crate_type = /obj/structure/closet/crate/secure/science dangerous = TRUE +//////// RAW ANOMALY CORES + +/datum/supply_pack/science/raw_flux_anomaly + name = "Raw Flux Anomaly" + desc = "The raw core of a flux anomaly, ready to be implosion-compressed into a powerful artifact." + cost = 5000 + access = ACCESS_TOX + contains = list(/obj/item/raw_anomaly_core/flux) + crate_name = "raw flux anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_grav_anomaly + name = "Raw Gravitational Anomaly" + desc = "The raw core of a gravitational anomaly, ready to be implosion-compressed into a powerful artifact." + cost = 5000 + access = ACCESS_TOX + contains = list(/obj/item/raw_anomaly_core/grav) + crate_name = "raw pyro anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_vortex_anomaly + name = "Raw Vortex Anomaly" + desc = "The raw core of a vortex anomaly, ready to be implosion-compressed into a powerful artifact." + cost = 5000 + access = ACCESS_TOX + contains = list(/obj/item/raw_anomaly_core/vortex) + crate_name = "raw vortex anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_bluespace_anomaly + name = "Raw Bluespace Anomaly" + desc = "The raw core of a bluespace anomaly, ready to be implosion-compressed into a powerful artifact." + cost = 5000 + access = ACCESS_TOX + contains = list(/obj/item/raw_anomaly_core/bluespace) + crate_name = "raw bluespace anomaly" + crate_type = /obj/structure/closet/crate/secure/science + +/datum/supply_pack/science/raw_pyro_anomaly + name = "Raw Pyro Anomaly" + desc = "The raw core of a pyro anomaly, ready to be implosion-compressed into a powerful artifact." + cost = 5000 + access = ACCESS_TOX + contains = list(/obj/item/raw_anomaly_core/pyro) + crate_name = "raw pyro anomaly" + crate_type = /obj/structure/closet/crate/secure/science diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index ae48fddfb4..755665583a 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -7,6 +7,9 @@ //////////////// //ADMIN THINGS// //////////////// + /// hides the byond verb panel as we use our own custom version + show_verb_panel = FALSE + ///Contains admin info. Null if client is not an admin. var/datum/admins/holder = null var/datum/click_intercept = null // Needs to implement InterceptClickOn(user,params,atom) proc var/AI_Interact = 0 @@ -75,11 +78,12 @@ var/inprefs = FALSE var/list/topiclimiter + + ///Used for limiting the rate of clicks sends by the client to avoid abuse var/list/clicklimiter - var/datum/chatOutput/chatOutput - - var/list/credits //lazy list of all credit object bound to this client + ///lazy list of all credit object bound to this client + var/list/credits var/datum/player_details/player_details //these persist between logins/logouts during the same round. @@ -122,6 +126,23 @@ /// Messages currently seen by this client var/list/seen_messages + + /// datum wrapper for client view + var/datum/view_data/view_size + + /// our current tab + var/stat_tab + + /// whether our browser is ready or not yet + var/statbrowser_ready = FALSE + + /// list of all tabs + var/list/panel_tabs = list() + + /// list of tabs containing spells and abilities + var/list/spell_tabs = list() + /// list of tabs containing verbs + var/list/verb_tabs = list() ///A lazy list of atoms we've examined in the last EXAMINE_MORE_TIME (default 1.5) seconds, so that we will call [atom/proc/examine_more()] instead of [atom/proc/examine()] on them when examining var/list/recent_examines ///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns @@ -151,3 +172,4 @@ //world.time of when the crew manifest can be accessed var/crew_manifest_delay + diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index e7aa447840..45990cd21f 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -20,7 +20,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( When somebody clicks a link in game, this Topic is called first. It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever] (if specified in the link). ie locate(hsrc).Topic() + Such links can be spoofed. + Because of this certain things MUST be considered whenever adding a Topic() for something: - Can it be fed harmful values which could cause runtimes? - Is the Topic call an admin-only thing? @@ -38,7 +40,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( var/asset_cache_job if(href_list["asset_cache_confirm_arrival"]) asset_cache_job = asset_cache_confirm_arrival(href_list["asset_cache_confirm_arrival"]) - if(!asset_cache_job) + if (!asset_cache_job) return // Rate limiting @@ -100,7 +102,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return // Tgui Topic middleware - if(!tgui_Topic(href_list)) + if(tgui_Topic(href_list)) return // Admin PM @@ -108,10 +110,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( cmd_admin_pm(href_list["priv_msg"],null) return - // CITADEL Start - Mentor PM + // Mentor PM (cit.) if (citadel_client_procs(href_list)) return - // CITADEL End switch(href_list["_src_"]) if("holder") @@ -119,7 +120,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if("usr") hsrc = mob if("mentor") // CITADEL - hsrc = mentor_datum // CITADEL END + hsrc = mentor_datum if("prefs") if (inprefs) return @@ -129,8 +130,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return if("vars") return view_var_Topic(href,href_list,hsrc) - if("chat") - return chatOutput.Topic(href, href_list) switch(href_list["action"]) if("openLink") @@ -147,7 +146,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! Click Here to find out more.") return 0 return 1 - /* * Call back proc that should be checked in all paths where a client can send messages * @@ -210,14 +208,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( /////////// //CONNECT// /////////// -#if (PRELOAD_RSC == 0) -GLOBAL_LIST_EMPTY(external_rsc_urls) -#endif /client/New(TopicData) - world.SetConfig("APP/admin", ckey, "role=admin") //CITADEL EDIT - Allows admins to reboot in OOM situations + world.SetConfig("APP/admin", ckey, "role=admin") var/tdata = TopicData //save this for later use - chatOutput = new /datum/chatOutput(src) TopicData = null //Prevent calls to client.Topic from connect if(connection != "seeker" && connection != "web")//Invalid connection type. @@ -226,6 +220,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) GLOB.clients += src GLOB.directory[ckey] = src + // Instantiate tgui panel + tgui_panel = new(src) + GLOB.ahelp_tickets.ClientLogin(src) var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins. //Admin Authorisation @@ -240,7 +237,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) debug_tools_allowed = TRUE //END CITADEL EDIT else if(GLOB.deadmins[ckey]) - verbs += /client/proc/readmin + add_verb(src, /client/proc/readmin) connecting_admin = TRUE if(CONFIG_GET(flag/autoadmin)) if(!GLOB.admin_datums[ckey]) @@ -266,7 +263,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) new /datum/admins(localhost_rank, ckey, 1, 1) //preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum) prefs = GLOB.preferences_datums[ckey] - if(prefs) prefs.parent = src else @@ -276,10 +272,10 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) prefs.last_ip = address //these are gonna be used for banning prefs.last_id = computer_id //these are gonna be used for banning - fps = prefs.clientfps + fps = prefs.clientfps //(prefs.clientfps < 0) ? RECOMMENDED_FPS : prefs.clientfps if(fexists(roundend_report_file())) - verbs += /client/proc/show_previous_roundend_report + add_verb(src, /client/proc/show_previous_roundend_report) var/full_version = "[byond_version].[byond_build ? byond_build : "xxx"]" log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[full_version]") @@ -301,22 +297,26 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) alert_mob_dupe_login = TRUE if(matches) if(C) - message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)].") - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(C)].") + message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)].") + log_admin_private("Notice: [key_name(src)] has the same [matches] as [key_name(C)].") else - message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)] (no longer logged in). ") - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).") + message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)] (no longer logged in). ") + log_admin_private("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).") if(GLOB.player_details[ckey]) player_details = GLOB.player_details[ckey] player_details.byond_version = full_version else - player_details = new + player_details = new(ckey) player_details.byond_version = full_version GLOB.player_details[ckey] = player_details . = ..() //calls mob.Login() + // if (length(GLOB.stickybanadminexemptions)) + // GLOB.stickybanadminexemptions -= ckey + // if (!length(GLOB.stickybanadminexemptions)) + // restore_stickybans() if (byond_version >= 512) if (!byond_build || byond_build < 1386) @@ -336,7 +336,14 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) qdel(src) return - chatOutput.start() // Starts the chat + // if(SSinput.initialized) placed here on tg. + // set_macros() + // update_movement_keys() + + // Initialize tgui panel + tgui_panel.initialize() + src << browse(file('html/statbrowser.html'), "window=statbrowser") + if(alert_mob_dupe_login) spawn() @@ -347,12 +354,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) connection_timeofday = world.timeofday winset(src, null, "command=\".configure graphics-hwmode on\"") var/cev = CONFIG_GET(number/client_error_version) + var/ceb = CONFIG_GET(number/client_error_build) var/cwv = CONFIG_GET(number/client_warn_version) - if (byond_version < cev) //Out of date client. + if (byond_version < cev || (byond_version == cev && byond_build < ceb)) //Out of date client. to_chat(src, "Your version of BYOND is too old:") to_chat(src, CONFIG_GET(string/client_error_message)) - to_chat(src, "Your version: [byond_version]") - to_chat(src, "Required version: [cev] or later") + to_chat(src, "Your version: [byond_version].[byond_build]") + to_chat(src, "Required version: [cev].[ceb] or later") to_chat(src, "Visit BYOND's website to get the latest version of BYOND.") if (connecting_admin) to_chat(src, "Because you are an admin, you are being allowed to walk past this limitation, But it is still STRONGLY suggested you upgrade") @@ -464,6 +472,10 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) if (menuitem) menuitem.Load_checked(src) + // view_size = new(src, getScreenSize(prefs.widescreenpref)) + // view_size.resetFormat() + // view_size.setZoomMode() + // fit_viewport() Master.UpdateTickRate() /client/proc/ensure_keys_set() @@ -477,13 +489,17 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) /client/Del() if(!gc_destroyed) - Destroy() + Destroy() //Clean up signals and timers. return ..() /client/Destroy() + GLOB.clients -= src + GLOB.directory -= ckey + log_access("Logout: [key_name(src)]") + GLOB.ahelp_tickets.ClientLogout(src) + // SSserver_maint.UpdateHubStatus() if(credits) QDEL_LIST(credits) - log_access("Logout: [key_name(src)]") if(holder) adminGreet(1) holder.owner = null @@ -505,16 +521,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) ) send2irc("Server", "[cheesy_message] (No admins online)") - - GLOB.ahelp_tickets.ClientLogout(src) - GLOB.directory -= ckey - GLOB.clients -= src QDEL_LIST_ASSOC_VAL(char_render_holders) if(movingmob != null) movingmob.client_mobs_in_contents -= mob UNSETEMPTY(movingmob.client_mobs_in_contents) + // seen_messages = null Master.UpdateTickRate() - . = ..() + . = ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening return QDEL_HINT_HARDDEL_NOW /client/proc/set_client_age_from_db(connectiontopic) @@ -616,6 +629,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) var/datum/DBQuery/query_log_connection = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`round_id`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')),'[world.port]','[GLOB.round_id]','[sql_ckey]',INET_ATON('[sql_ip]'),'[sql_computerid]')") query_log_connection.Execute() qdel(query_log_connection) + + // SSserver_maint.UpdateHubStatus() + if(new_player) player_age = -1 . = player_age @@ -843,9 +859,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) /client/proc/add_verbs_from_config() if(CONFIG_GET(flag/see_own_notes)) - verbs += /client/proc/self_notes + add_verb(src, /client/proc/self_notes) if(CONFIG_GET(flag/use_exp_tracking)) - verbs += /client/proc/self_playtime + add_verb(src, /client/proc/self_playtime) #undef UPLOAD_LIMIT @@ -857,40 +873,31 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) return inactivity return FALSE -//send resources to the client. It's here in its own proc so we can move it around easiliy if need be +/// Send resources to the client. +/// Sends both game resources and browser assets. /client/proc/send_resources() #if (PRELOAD_RSC == 0) var/static/next_external_rsc = 0 - if(GLOB.external_rsc_urls && GLOB.external_rsc_urls.len) - next_external_rsc = WRAP(next_external_rsc+1, 1, GLOB.external_rsc_urls.len+1) - preload_rsc = GLOB.external_rsc_urls[next_external_rsc] + var/list/external_rsc_urls = CONFIG_GET(keyed_list/external_rsc_urls) + if(length(external_rsc_urls)) + next_external_rsc = WRAP(next_external_rsc+1, 1, external_rsc_urls.len+1) + preload_rsc = external_rsc_urls[next_external_rsc] #endif - //get the common files - getFiles( - 'html/search.js', - 'html/panels.css', - 'html/browser/common.css', - 'html/browser/scannernew.css', - 'html/browser/playeroptions.css', - ) + spawn (10) //removing this spawn causes all clients to not get verbs. //load info on what assets the client has src << browse('code/modules/asset_cache/validate_assets.html', "window=asset_cache_browser") //Precache the client with all other assets slowly, so as to not block other browse() calls - getFilesSlow(src, SSassets.preload, register_asset = FALSE) - addtimer(CALLBACK(GLOBAL_PROC, /proc/getFilesSlow, src, SSassets.preload, FALSE), 5 SECONDS) + if (CONFIG_GET(flag/asset_simple_preload)) + addtimer(CALLBACK(SSassets.transport, /datum/asset_transport.proc/send_assets_slow, src, SSassets.transport.preload), 5 SECONDS) #if (PRELOAD_RSC == 0) for (var/name in GLOB.vox_sounds) var/file = GLOB.vox_sounds[name] Export("##action=load_rsc", file) stoplag() - for (var/name in GLOB.vox_sounds_male) - var/file = GLOB.vox_sounds_male[name] - Export("##action=load_rsc", file) - stoplag() #endif @@ -996,3 +1003,21 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) /client/proc/can_have_part(part_name) return prefs.pref_species.mutant_bodyparts[part_name] || (part_name in GLOB.unlocked_mutant_parts) + +/// compiles a full list of verbs and sends it to the browser +/client/proc/init_verbs() + if(IsAdminAdvancedProcCall()) + return + var/list/verblist = list() + verb_tabs.Cut() + for(var/thing in (verbs + mob?.verbs)) + var/procpath/verb_to_init = thing + if(!verb_to_init) + continue + if(verb_to_init.hidden) + continue + if(!istext(verb_to_init.category)) + continue + verb_tabs |= verb_to_init.category + verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name) + src << output("[url_encode(json_encode(verb_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs") diff --git a/code/modules/client/darkmode.dm b/code/modules/client/darkmode.dm deleted file mode 100644 index f806e5c964..0000000000 --- a/code/modules/client/darkmode.dm +++ /dev/null @@ -1,65 +0,0 @@ -//Darkmode preference by Kmc2000// - -/* -This lets you switch chat themes by using winset and CSS loading, you must relog to see this change (or rebuild your browseroutput datum) -Things to note: -If you change ANYTHING in interface/skin.dmf you need to change it here: -Format: -winset(src, "window as appears in skin.dmf after elem", "var to change = desired value") -How this works: -I've added a function to browseroutput.js which registers a cookie for darkmode and swaps the chat accordingly. You can find the button to do this under the "cog" icon next to the ping button (top right of chat) -This then swaps the window theme automatically -Thanks to spacemaniac and mcdonald for help with the JS side of this. -*/ - -/client/proc/force_white_theme() //There's no way round it. We're essentially changing the skin by hand. It's painful but it works, and is the way Lummox suggested. - //Main windows - winset(src, "infowindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "info", "background-color = [COLOR_WHITEMODE_BACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "browseroutput", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "outputwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "mainwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND]") - winset(src, "split", "background-color = [COLOR_WHITEMODE_BACKGROUND]") - //Buttons - winset(src, "changelog", "background-color = [COLOR_WHITEMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "rules", "background-color = [COLOR_WHITEMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "wiki", "background-color = [COLOR_WHITEMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "forum", "background-color = [COLOR_WHITEMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "github", "background-color = [COLOR_WHITEMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "report-issue", "background-color = [COLOR_WHITEMODE_ISSUE_BUTTON_BG];text-color = [COLOR_WHITEMODE_TEXT]") - //Status and verb tabs - winset(src, "output", "background-color = [COLOR_WHITEMODE_BACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "statwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "stat", "background-color = [COLOR_WHITEMODE_BACKGROUND];tab-background-color = [COLOR_WHITEMODE_DARKBACKGROUND];\ - text-color = [COLOR_WHITEMODE_TEXT];tab-text-color = [COLOR_WHITEMODE_TEXT];\ - prefix-color = [COLOR_WHITEMODE_TEXT];suffix-color = [COLOR_WHITEMODE_TEXT]") - //Etc. - winset(src, "say", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "asset_cache_browser", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - winset(src, "tooltip", "background-color = [COLOR_WHITEMODE_BACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]") - -/client/proc/force_dark_theme() //Inversely, if theyre using white theme and want to swap to the superior dark theme, let's get WINSET() ing - //Main windows - winset(src, "infowindow", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "info", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "browseroutput", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "outputwindow", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "mainwindow", "background-color = [COLOR_DARKMODE_DARKBACKGROUND]") - winset(src, "split", "background-color = [COLOR_DARKMODE_BACKGROUND]") - //Buttons - winset(src, "changelog", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "rules", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "wiki", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "forum", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "github", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "report-issue", "background-color = [COLOR_DARKMODE_ISSUE_BUTTON_BG];text-color = [COLOR_DARKMODE_TEXT]") - //Status and verb tabs - winset(src, "output", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "statwindow", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "stat", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];tab-background-color = [COLOR_DARKMODE_BACKGROUND];\ - text-color = [COLOR_DARKMODE_TEXT];tab-text-color = [COLOR_DARKMODE_TEXT];\ - prefix-color = [COLOR_DARKMODE_TEXT];suffix-color = [COLOR_DARKMODE_TEXT]") - //Etc. - winset(src, "say", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "asset_cache_browser", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") - winset(src, "tooltip", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]") \ No newline at end of file diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 2fe674e59e..a673012118 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -95,7 +95,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/facial_hair_color = "000000" //Facial hair color var/skin_tone = "caucasian1" //Skin color var/use_custom_skin_tone = FALSE - var/eye_color = "000000" //Eye color + var/left_eye_color = "000000" //Eye color + var/right_eye_color = "000000" + var/split_eye_colors = FALSE var/datum/species/pref_species = new /datum/species/human() //Mutant race var/list/features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", @@ -163,6 +165,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) ) var/custom_speech_verb = "default" //if your say_mod is to be something other than your races var/custom_tongue = "default" //if your tongue is to be something other than your races + var/modified_limbs = list() //prosthetic/amputated limbs + var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded /// Security record note section var/security_records @@ -246,7 +250,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) /// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)] var/scars_index = 1 - var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded + var/hide_ckey = FALSE //pref for hiding if your ckey shows round-end or not /datum/preferences/New(client/C) parent = C @@ -372,6 +376,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "[medical_records]" else dat += "[TextPreview(medical_records)]...
    " + dat += "
    Hide ckey: [hide_ckey ? "Enabled" : "Disabled"]
    " dat += "
    " //Character Appearance @@ -427,12 +432,19 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
    " if(gender != NEUTER && pref_species.sexes) dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
    " + dat += "Limb Modification:
    " + dat += "Modify Limbs
    " + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + dat += "[modification]: [modified_limbs[modification][2]]
    " + else + dat += "[modification]: [modified_limbs[modification][1]]
    " + dat += "
    " dat += "Species:[pref_species.name]
    " dat += "Custom Species Name:[custom_species ? custom_species : "None"]
    " dat += "Random Body:Randomize!
    " dat += "Always Random Body:[be_random_body ? "Yes" : "No"]
    " dat += "
    Cycle background:[bgstate]
    " - var/use_skintones = pref_species.use_skintones if(use_skintones) dat += APPEARANCE_CATEGORY_COLUMN @@ -462,15 +474,22 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Sprite Size: [features["body_size"]*100]%
    " if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits)) - if(!use_skintones && !mutant_colors) dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Eye Color

    " - - dat += "    Change
    " - - dat += "" + if(left_eye_color != right_eye_color) + split_eye_colors = TRUE + dat += "

    Heterochromia

    " + dat += "
    [split_eye_colors ? "Enabled" : "Disabled"]" + if(!split_eye_colors) + dat += "

    Eye Color

    " + dat += "    Change" + dat += "" + else + dat += "

    Left Eye Color

    " + dat += "    Change" + dat += "

    Right Eye Color

    " + dat += "    Change
    " + dat += "" else if(use_skintones || mutant_colors) dat += "" @@ -857,6 +876,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
    " dat += "

    Fetish content prefs

    " dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
    " + dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"]
    " + dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"]
    " dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
    " dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
    " dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
    " @@ -1231,6 +1252,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) for(var/V in all_quirks) var/datum/quirk/T = SSquirks.quirks[V] bal -= initial(T.value) + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + return bal + 1 //max 1 point regardless of how many prosthetics return bal /datum/preferences/proc/GetPositiveQuirkCount() @@ -1358,7 +1382,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) socks = random_socks() socks_color = random_short_color() if(BODY_ZONE_PRECISE_EYES) - eye_color = random_eye_color() + var/random_eye_color = random_eye_color() + left_eye_color = random_eye_color + right_eye_color = random_eye_color if("s_tone") skin_tone = random_skin_tone() use_custom_skin_tone = null @@ -1446,6 +1472,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(!isnull(msg)) features["ooc_notes"] = msg + if("hide_ckey") + hide_ckey = !hide_ckey + if(user) + user.mind?.hide_ckey = hide_ckey + if("hair") var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null if(new_hair) @@ -1483,6 +1514,29 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("cycle_bg") bgstate = next_list_item(bgstate, bgstate_options) + if("modify_limbs") + var/limb_type = input(user, "Choose the limb to modify:", "Character Preference") as null|anything in LOADOUT_ALLOWED_LIMB_TARGETS + if(limb_type) + var/modification_type = input(user, "Choose the modification to the limb:", "Character Preference") as null|anything in LOADOUT_LIMBS + if(modification_type) + if(modification_type == LOADOUT_LIMB_PROSTHETIC) + var/prosthetic_type = input(user, "Choose the type of prosthetic", "Character Preference") as null|anything in (list("prosthetic") + GLOB.prosthetic_limb_types) + if(prosthetic_type) + var/number_of_prosthetics = 0 + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + number_of_prosthetics += 1 + if(number_of_prosthetics >= MAXIMUM_LOADOUT_PROSTHETICS && !(limb_type in modified_limbs && modified_limbs[limb_type][1] == LOADOUT_LIMB_PROSTHETIC)) + to_chat(user, "You can only have up to two prosthetic limbs!") + else + //save the actual prosthetic data + modified_limbs[limb_type] = list(modification_type, prosthetic_type) + else + if(modification_type == LOADOUT_LIMB_NORMAL) + modified_limbs -= limb_type + else + modified_limbs[limb_type] = list(modification_type) + if("underwear") var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_list if(new_underwear) @@ -1514,9 +1568,24 @@ GLOBAL_LIST_EMPTY(preferences_datums) socks_color = sanitize_hexcolor(n_socks_color, 6) if("eyes") - var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null + var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+left_eye_color) as color|null if(new_eyes) - eye_color = sanitize_hexcolor(new_eyes, 6) + left_eye_color = sanitize_hexcolor(new_eyes, 6) + right_eye_color = sanitize_hexcolor(new_eyes, 6) + + if("eye_left") + var/new_eyes = input(user, "Choose your character's left eye colour:", "Character Preference","#"+left_eye_color) as color|null + if(new_eyes) + left_eye_color = sanitize_hexcolor(new_eyes, 6) + + if("eye_right") + var/new_eyes = input(user, "Choose your character's right eye colour:", "Character Preference","#"+right_eye_color) as color|null + if(new_eyes) + right_eye_color = sanitize_hexcolor(new_eyes, 6) + + if("toggle_split_eyes") + split_eye_colors = !split_eye_colors + right_eye_color = left_eye_color if("species") var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_race_names @@ -2353,6 +2422,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) parent.mob.hud_used.update_parallax_pref(parent.mob) // Citadel edit - Prefs don't work outside of this. :c + + if("genital_examine") + cit_toggles ^= GENITAL_EXAMINE + + if("vore_examine") + cit_toggles ^= VORE_EXAMINE + if("hound_sleeper") cit_toggles ^= MEDIHOUND_SLEEPER @@ -2462,7 +2538,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) ShowChoices(user) return 1 -/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE) +/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1, roundstart_checks = TRUE, initial_spawn = FALSE) if(be_random_name) real_name = pref_species.random_name(gender) @@ -2486,12 +2562,15 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.gender = gender character.age = age - character.eye_color = eye_color + character.left_eye_color = left_eye_color + character.right_eye_color = right_eye_color var/obj/item/organ/eyes/organ_eyes = character.getorgan(/obj/item/organ/eyes) if(organ_eyes) - if(!initial(organ_eyes.eye_color)) - organ_eyes.eye_color = eye_color - organ_eyes.old_eye_color = eye_color + if(!initial(organ_eyes.left_eye_color)) + organ_eyes.left_eye_color = left_eye_color + organ_eyes.right_eye_color = right_eye_color + organ_eyes.old_left_eye_color = left_eye_color + organ_eyes.old_right_eye_color = right_eye_color character.hair_color = hair_color character.facial_hair_color = facial_hair_color character.skin_tone = skin_tone @@ -2557,6 +2636,34 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(custom_speech_verb != "default") character.dna.species.say_mod = custom_speech_verb + //limb stuff, only done when initially spawning in + if(initial_spawn) + //delete any existing prosthetic limbs to make sure no remnant prosthetics are left over + for(var/obj/item/bodypart/part in character.bodyparts) + if(part.status == BODYPART_ROBOTIC) + qdel(part) + character.regenerate_limbs() //regenerate limbs so now you only have normal limbs + for(var/modified_limb in modified_limbs) + var/modification = modified_limbs[modified_limb][1] + var/obj/item/bodypart/old_part = character.get_bodypart(modified_limb) + if(modification == LOADOUT_LIMB_PROSTHETIC) + var/obj/item/bodypart/new_limb + switch(modified_limb) + if(BODY_ZONE_L_ARM) + new_limb = new/obj/item/bodypart/l_arm/robot/surplus(character) + if(BODY_ZONE_R_ARM) + new_limb = new/obj/item/bodypart/r_arm/robot/surplus(character) + if(BODY_ZONE_L_LEG) + new_limb = new/obj/item/bodypart/l_leg/robot/surplus(character) + if(BODY_ZONE_R_LEG) + new_limb = new/obj/item/bodypart/r_leg/robot/surplus(character) + var/prosthetic_type = modified_limbs[modified_limb][2] + if(prosthetic_type != "prosthetic") //lets just leave the old sprites as they are + new_limb.icon = file("icons/mob/augmentation/cosmetic_prosthetic/[prosthetic_type].dmi") + new_limb.replace_limb(character) + qdel(old_part) + + character.regenerate_icons() SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks) @@ -2565,6 +2672,18 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.update_body() character.update_hair() +/datum/preferences/proc/post_copy_to(mob/living/carbon/human/character) + //if no legs, and not a paraplegic or a slime, give them a free wheelchair + if(modified_limbs[BODY_ZONE_L_LEG] == LOADOUT_LIMB_AMPUTATED && modified_limbs[BODY_ZONE_R_LEG] == LOADOUT_LIMB_AMPUTATED && !character.has_quirk(/datum/quirk/paraplegic) && !isjellyperson(character)) + if(character.buckled) + character.buckled.unbuckle_mob(character) + var/turf/T = get_turf(character) + var/obj/structure/chair/spawn_chair = locate() in T + var/obj/vehicle/ridden/wheelchair/wheels = new(T) + if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking + wheels.setDir(spawn_chair.dir) + wheels.buckle_mob(character) + /datum/preferences/proc/get_default_name(name_id) switch(name_id) if("human") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 55a594cf21..23d0288163 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 35 +#define SAVEFILE_VERSION_MAX 36 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -204,6 +204,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(S["species"] == "lizard") features["mam_snouts"] = features["snout"] + if(current_version < 36) + left_eye_color = S["eye_color"] + right_eye_color = S["eye_color"] + /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return @@ -476,7 +480,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["age"] >> age S["hair_color"] >> hair_color S["facial_hair_color"] >> facial_hair_color - S["eye_color"] >> eye_color + S["left_eye_color"] >> left_eye_color + S["right_eye_color"] >> right_eye_color S["use_custom_skin_tone"] >> use_custom_skin_tone S["skin_tone"] >> skin_tone S["hair_style_name"] >> hair_style @@ -514,8 +519,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["scars3"] >> scars_list["3"] S["scars4"] >> scars_list["4"] S["scars5"] >> scars_list["5"] + var/limbmodstr + S["modified_limbs"] >> limbmodstr + if(length(limbmodstr)) + modified_limbs = safe_json_decode(limbmodstr) + else + modified_limbs = list() S["chosen_limb_id"] >> chosen_limb_id - + S["hide_ckey"] >> hide_ckey //saved per-character //Custom names for(var/custom_name_id in GLOB.preferences_custom_names) @@ -648,7 +659,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) hair_color = sanitize_hexcolor(hair_color, 6, FALSE) facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE) - eye_color = sanitize_hexcolor(eye_color, 6, FALSE) + left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE) + right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE) var/static/allow_custom_skintones if(isnull(allow_custom_skintones)) @@ -777,7 +789,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["age"] , age) WRITE_FILE(S["hair_color"] , hair_color) WRITE_FILE(S["facial_hair_color"] , facial_hair_color) - WRITE_FILE(S["eye_color"] , eye_color) + WRITE_FILE(S["left_eye_color"] , left_eye_color) + WRITE_FILE(S["right_eye_color"] , right_eye_color) WRITE_FILE(S["use_custom_skin_tone"] , use_custom_skin_tone) WRITE_FILE(S["skin_tone"] , skin_tone) WRITE_FILE(S["hair_style_name"] , hair_style) @@ -845,8 +858,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"]) - WRITE_FILE(S["chosen_limb_id"], chosen_limb_id) - //Custom names for(var/custom_name_id in GLOB.preferences_custom_names) var/savefile_slot_name = custom_name_id + "_name" //TODO remove this @@ -859,6 +870,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["joblessrole"] , joblessrole) //Write prefs WRITE_FILE(S["job_preferences"] , job_preferences) + WRITE_FILE(S["hide_ckey"] , hide_ckey) //Quirks WRITE_FILE(S["all_quirks"] , all_quirks) @@ -873,6 +885,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["scars3"] , scars_list["3"]) WRITE_FILE(S["scars4"] , scars_list["4"]) WRITE_FILE(S["scars5"] , scars_list["5"]) + if(islist(modified_limbs)) + WRITE_FILE(S["modified_limbs"] , safe_json_encode(modified_limbs)) + WRITE_FILE(S["chosen_limb_id"], chosen_limb_id) + //gear loadout if(chosen_gear.len) diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 951e36f9a6..e16a491c61 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -145,8 +145,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglemidis)() to_chat(usr, "You will no longer hear sounds uploaded by admins") usr.stop_sound_channel(CHANNEL_ADMIN) var/client/C = usr.client - if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) - C.chatOutput.stopMusic() + C?.tgui_panel?.stop_music() SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Hearing Midis", "[usr.client.prefs.toggles & SOUND_MIDI ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /datum/verbs/menu/Settings/Sound/togglemidis/Get_checked(client/C) return C.prefs.toggles & SOUND_MIDI @@ -234,8 +233,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)() set desc = "Stop Current Sounds" SEND_SOUND(usr, sound(null)) var/client/C = usr.client - if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) - C.chatOutput.stopMusic() + C?.tgui_panel?.stop_music() SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Stop Self Sounds")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index fa1145ecea..dd1ebd74f9 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -158,88 +158,6 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") else to_chat(src, "There are no admin notices at the moment.") -/client/verb/fix_chat() - set name = "Fix chat" - set category = "OOC" - if (!chatOutput || !istype(chatOutput)) - var/action = alert(src, "Invalid Chat Output data found!\nRecreate data?", "Wot?", "Recreate Chat Output data", "Cancel") - if (action != "Recreate Chat Output data") - return - chatOutput = new /datum/chatOutput(src) - chatOutput.start() - action = alert(src, "Goon chat reloading, wait a bit and tell me if it's fixed", "", "Fixed", "Nope") - if (action == "Fixed") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by re-creating the chatOutput datum") - else - chatOutput.load() - action = alert(src, "How about now? (give it a moment (it may also try to load twice))", "", "Yes", "No") - if (action == "Yes") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by re-creating the chatOutput datum and forcing a load()") - else - action = alert(src, "Welp, I'm all out of ideas. Try closing byond and reconnecting.\nWe could also disable fancy chat and re-enable oldchat", "", "Thanks anyways", "Switch to old chat") - if (action == "Switch to old chat") - winset(src, "output", "is-visible=true;is-disabled=false") - winset(src, "browseroutput", "is-visible=false") - log_game("GOONCHAT: [key_name(src)] Failed to fix their goonchat window after recreating the chatOutput and forcing a load()") - - else if (chatOutput.loaded) - var/action = alert(src, "ChatOutput seems to be loaded\nDo you want me to force a reload, wiping the chat log or just refresh the chat window because it broke/went away?", "Hmmm", "Force Reload", "Refresh", "Cancel") - switch (action) - if ("Force Reload") - chatOutput.loaded = FALSE - chatOutput.start() //this is likely to fail since it asks , but we should try it anyways so we know. - action = alert(src, "Goon chat reloading, wait a bit and tell me if it's fixed", "", "Fixed", "Nope") - if (action == "Fixed") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by forcing a start()") - else - chatOutput.load() - action = alert(src, "How about now? (give it a moment (it may also try to load twice))", "", "Yes", "No") - if (action == "Yes") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by forcing a load()") - else - action = alert(src, "Welp, I'm all out of ideas. Try closing byond and reconnecting.\nWe could also disable fancy chat and re-enable oldchat", "", "Thanks anyways", "Switch to old chat") - if (action == "Switch to old chat") - winset(src, "output", "is-visible=true;is-disabled=false") - winset(src, "browseroutput", "is-visible=false") - log_game("GOONCHAT: [key_name(src)] Failed to fix their goonchat window forcing a start() and forcing a load()") - - if ("Refresh") - chatOutput.showChat() - action = alert(src, "Goon chat refreshing, wait a bit and tell me if it's fixed", "", "Fixed", "Nope, force a reload") - if (action == "Fixed") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by forcing a show()") - else - chatOutput.loaded = FALSE - chatOutput.load() - action = alert(src, "How about now? (give it a moment)", "", "Yes", "No") - if (action == "Yes") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by forcing a load()") - else - action = alert(src, "Welp, I'm all out of ideas. Try closing byond and reconnecting.\nWe could also disable fancy chat and re-enable oldchat", "", "Thanks anyways", "Switch to old chat") - if (action == "Switch to old chat") - winset(src, "output", "is-visible=true;is-disabled=false") - winset(src, "browseroutput", "is-visible=false") - log_game("GOONCHAT: [key_name(src)] Failed to fix their goonchat window forcing a show() and forcing a load()") - return - - else - chatOutput.start() - var/action = alert(src, "Manually loading Chat, wait a bit and tell me if it's fixed", "", "Fixed", "Nope") - if (action == "Fixed") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by manually calling start()") - else - chatOutput.load() - alert(src, "How about now? (give it a moment (it may also try to load twice))", "", "Yes", "No") - if (action == "Yes") - log_game("GOONCHAT: [key_name(src)] Had to fix their goonchat by manually calling start() and forcing a load()") - else - action = alert(src, "Welp, I'm all out of ideas. Try closing byond and reconnecting.\nWe could also disable fancy chat and re-enable oldchat", "", "Thanks anyways", "Switch to old chat") - if (action == "Switch to old chat") - winset(src, "output", list2params(list("on-show" = "", "is-disabled" = "false", "is-visible" = "true"))) - winset(src, "browseroutput", "is-disabled=true;is-visible=false") - log_game("GOONCHAT: [key_name(src)] Failed to fix their goonchat window after manually calling start() and forcing a load()") - - /client/verb/motd() set name = "MOTD" @@ -362,3 +280,9 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") pct += delta winset(src, "mainwindow.split", "splitter=[pct]") + +/client/verb/fix_stat_panel() + set name = "Fix Stat Panel" + set hidden = TRUE + + init_verbs() diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 3f6d21bcd2..11de0124cb 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -373,7 +373,7 @@ /obj/item/clothing/glasses/sunglasses/blindfold/white/update_icon(mob/living/carbon/human/user) if(ishuman(user) && !colored_before) - add_atom_colour("#[user.eye_color]", FIXED_COLOUR_PRIORITY) + add_atom_colour("#[user.left_eye_color]", FIXED_COLOUR_PRIORITY) colored_before = TRUE /obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) @@ -382,7 +382,7 @@ var/mob/living/carbon/human/H = loc var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/eyes.dmi', "blindfoldwhite") M.appearance_flags |= RESET_COLOR - M.color = "#[H.eye_color]" + M.color = "#[H.left_eye_color]" . += M /obj/item/clothing/glasses/sunglasses/big diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index cf7dbc7462..6732f1c86c 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -80,7 +80,9 @@ item_state = "hostrench" flags_inv = 0 strip_delay = 80 - unique_reskin = list("Coat" = "hostrench", "Cloak" = "trenchcloak") + unique_reskin = list("Coat" = "hostrench", + "Cloak" = "trenchcloak" + ) /obj/item/clothing/suit/armor/vest/warden name = "warden's jacket" diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 632d59187f..f496468371 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -5,9 +5,9 @@ var/obj/item/clothing/head/hooded/hood var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this -/obj/item/clothing/suit/hooded/New() +/obj/item/clothing/suit/hooded/Initialize() + . = ..() hood = MakeHelmet() - ..() /obj/item/clothing/suit/hooded/Destroy() . = ..() @@ -48,7 +48,7 @@ /obj/item/clothing/suit/hooded/update_icon_state() icon_state = "[initial(icon_state)]" - if(ishuman(hood.loc)) + if(ishuman(hood?.loc)) var/mob/living/carbon/human/H = hood.loc if(H.head == hood) icon_state += "_t" @@ -131,8 +131,8 @@ //Hardsuit toggle code /obj/item/clothing/suit/space/hardsuit/Initialize() - helmet = MakeHelmet() . = ..() + helmet = MakeHelmet() /obj/item/clothing/suit/space/hardsuit/Destroy() if(helmet) diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index 18cd104ff8..f8292738ee 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -267,7 +267,7 @@ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON|USE_TAUR_CLIP_MASK /obj/item/clothing/under/costume/christmas/croptop/green - name = "green feminine christmas suit" + name = "green croptop christmas suit" desc = "A simple green christmas suit. Smells minty!" icon_state = "christmasfemaleg" item_state = "christmasfemaleg" diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 5693468b3b..e5340fe411 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -45,10 +45,18 @@ /obj/item/clothing/under/rank/engineering/engineer/hazard name = "engineer's hazard jumpsuit" desc = "A high visibility jumpsuit made from heat and radiation resistant materials." - icon_state = "hazard" - item_state = "suit-orange" + icon_state = "hazard_orange" + item_state = "engi_suit" alt_covers_chest = TRUE +/obj/item/clothing/under/rank/engineering/engineer/hazard/green + icon_state = "hazard_green" + item_state = "g_suit" + +/obj/item/clothing/under/rank/engineering/engineer/hazard/white + icon_state = "hazard_white" + item_state = "gy_suit" + /obj/item/clothing/under/rank/engineering/engineer/skirt name = "engineer's jumpskirt" desc = "It's an orange high visibility jumpskirt worn by engineers." diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 27fb0cc00d..5d750f3c75 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -118,7 +118,6 @@ icon_state = "plasmaman" item_state = "plasmaman" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) - slowdown = 1 body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS mutantrace_variation = USE_TAUR_CLIP_MASK can_adjust = FALSE @@ -326,3 +325,22 @@ desc = "A blue bathrobe." icon_state = "bathrobe" item_state = "bathrobe" + +/obj/item/clothing/under/misc/mechsuitred + name = "red mech suit" + desc = "What are you, stupid?" + icon_state = "red_mech_suit" + item_state = "red_mech_suit" + +/obj/item/clothing/under/misc/mechsuitwhite + name = "white mech suit" + desc = "...Mom?" + icon_state = "white_mech_suit" + item_state = "white_mech_suit" + +/obj/item/clothing/under/misc/mechsuitblue + name = "blue mech suit" + desc = "Get in the damn robot already!" + icon_state = "blue_mech_suit" + item_state = "blue_mech_suit" + diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm index 3fd83899c9..64c07f5a38 100644 --- a/code/modules/emoji/emoji_parse.dm +++ b/code/modules/emoji/emoji_parse.dm @@ -17,7 +17,7 @@ if(search) emoji = lowertext(copytext(text, pos + length(text[pos]), search)) var/isthisapath = (emoji[1] == "/") && text2path(emoji) - var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat) + var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) var/tag = sheet.icon_tag("emoji-[emoji]") if(tag) parsed += "[tag]" //evil way of enforcing 16x16 diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm index 395b3b88a5..7f0dedaab6 100644 --- a/code/modules/events/anomaly_bluespace.dm +++ b/code/modules/events/anomaly_bluespace.dm @@ -4,7 +4,6 @@ max_occurrences = 1 weight = 5 - gamemode_blacklist = list("dynamic") /datum/round_event/anomaly/anomaly_bluespace startWhen = 3 diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm index a9a7ed50b9..8047976330 100644 --- a/code/modules/events/anomaly_flux.dm +++ b/code/modules/events/anomaly_flux.dm @@ -5,7 +5,6 @@ min_players = 10 max_occurrences = 5 weight = 20 - gamemode_blacklist = list("dynamic") /datum/round_event/anomaly/anomaly_flux startWhen = 10 diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm index cabd7face8..7d2bb33889 100644 --- a/code/modules/events/anomaly_grav.dm +++ b/code/modules/events/anomaly_grav.dm @@ -4,7 +4,6 @@ max_occurrences = 5 weight = 20 - gamemode_blacklist = list("dynamic") /datum/round_event/anomaly/anomaly_grav diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm index 8c8fbd6d36..350c8fc946 100644 --- a/code/modules/events/anomaly_pyro.dm +++ b/code/modules/events/anomaly_pyro.dm @@ -4,7 +4,6 @@ max_occurrences = 5 weight = 20 - gamemode_blacklist = list("dynamic") /datum/round_event/anomaly/anomaly_pyro startWhen = 3 diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm index 96d084873d..e2a4ceadf3 100644 --- a/code/modules/events/anomaly_vortex.dm +++ b/code/modules/events/anomaly_vortex.dm @@ -5,7 +5,6 @@ min_players = 20 max_occurrences = 2 weight = 5 - gamemode_blacklist = list("dynamic") /datum/round_event/anomaly/anomaly_vortex startWhen = 10 diff --git a/code/modules/events/brain_trauma.dm b/code/modules/events/brain_trauma.dm index 3e8182a827..75c514774c 100644 --- a/code/modules/events/brain_trauma.dm +++ b/code/modules/events/brain_trauma.dm @@ -3,6 +3,13 @@ typepath = /datum/round_event/brain_trauma weight = 25 +/datum/round_event_control/brain_trauma/canSpawnEvent(var/players_amt, var/gamemode) + var/list/enemy_roles = list("Medical Doctor","Chief Medical Officer","Paramedic") + for (var/mob/M in GLOB.alive_mob_list) + if(M.stat != DEAD && (M.mind?.assigned_role in enemy_roles)) + return TRUE + return FALSE + /datum/round_event/brain_trauma fakeable = FALSE @@ -14,19 +21,21 @@ continue if(!H.getorgan(/obj/item/organ/brain)) // If only I had a brain continue - + if(HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS)) + continue + if(!is_station_level(H.z)) + continue traumatize(H) break /datum/round_event/brain_trauma/proc/traumatize(mob/living/carbon/human/H) var/resistance = pick( 65;TRAUMA_RESILIENCE_BASIC, - 30;TRAUMA_RESILIENCE_SURGERY, - 5;TRAUMA_RESILIENCE_LOBOTOMY) + 35;TRAUMA_RESILIENCE_SURGERY) var/trauma_type = pickweight(list( - BRAIN_TRAUMA_MILD = 60, - BRAIN_TRAUMA_SEVERE = 30, + BRAIN_TRAUMA_MILD = 80, + BRAIN_TRAUMA_SEVERE = 10, BRAIN_TRAUMA_SPECIAL = 10 )) diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index 1c88e68377..7c55bbfcd1 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -5,7 +5,6 @@ min_players = 15 max_occurrences = 1 - gamemode_blacklist = list("dynamic") /datum/round_event/brand_intelligence announceWhen = 21 @@ -65,7 +64,7 @@ originMachine.visible_message("[originMachine] beeps and seems lifeless.") kill() return - vendingMachines = removeNullsFromList(vendingMachines) + vendingMachines = listclearnulls(vendingMachines) if(!vendingMachines.len) //if every machine is infected for(var/obj/machinery/vending/upriser in infectedMachines) if(prob(70) && !QDELETED(upriser)) diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index 2c553fc8a7..d08e6267a0 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -5,7 +5,6 @@ min_players = 2 earliest_start = 10 MINUTES max_occurrences = 6 - gamemode_blacklist = list("dynamic") /datum/round_event/carp_migration announceWhen = 3 diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index 45fa1c8a01..cb62e0df22 100644 --- a/code/modules/events/communications_blackout.dm +++ b/code/modules/events/communications_blackout.dm @@ -2,7 +2,6 @@ name = "Communications Blackout" typepath = /datum/round_event/communications_blackout weight = 30 - gamemode_blacklist = list("dynamic") /datum/round_event/communications_blackout announceWhen = 1 diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 860685c787..eb7edcafbf 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -5,7 +5,6 @@ max_occurrences = 1000 earliest_start = 0 MINUTES alert_observers = FALSE - gamemode_blacklist = list("dynamic") /datum/round_event/space_dust startWhen = 1 @@ -29,4 +28,4 @@ fakeable = FALSE /datum/round_event/sandstorm/tick() - spawn_meteors(10, GLOB.meteorsC) \ No newline at end of file + spawn_meteors(10, GLOB.meteorsC) diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index 5e5e318e3c..b850b4db62 100644 --- a/code/modules/events/electrical_storm.dm +++ b/code/modules/events/electrical_storm.dm @@ -5,7 +5,6 @@ min_players = 5 weight = 40 alert_observers = FALSE - gamemode_blacklist = list("dynamic") /datum/round_event/electrical_storm var/lightsoutAmount = 1 diff --git a/code/modules/events/fake_virus.dm b/code/modules/events/fake_virus.dm index 77520198e8..cebf1ed14b 100644 --- a/code/modules/events/fake_virus.dm +++ b/code/modules/events/fake_virus.dm @@ -6,7 +6,7 @@ /datum/round_event/fake_virus/start() var/list/fake_virus_victims = list() for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list)) - if(!H.client || H.stat == DEAD || H.InCritical()) + if(!H.client || H.stat == DEAD || H.InCritical() || HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS)) continue fake_virus_victims += H diff --git a/code/modules/events/heart_attack.dm b/code/modules/events/heart_attack.dm index b3bc571a4a..8c33e69107 100644 --- a/code/modules/events/heart_attack.dm +++ b/code/modules/events/heart_attack.dm @@ -4,7 +4,6 @@ weight = 20 max_occurrences = 2 min_players = 40 // To avoid shafting lowpop - gamemode_blacklist = list("dynamic") /datum/round_event/heart_attack/start() var/list/heart_attack_contestants = list() @@ -20,4 +19,4 @@ var/mob/living/carbon/human/winner = pickweight(heart_attack_contestants) var/datum/disease/D = new /datum/disease/heart_failure() winner.ForceContractDisease(D, FALSE, TRUE) - announce_to_ghosts(winner) \ No newline at end of file + announce_to_ghosts(winner) diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index b15e9d1f99..c75aff0c4a 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -3,7 +3,6 @@ /datum/round_event_control/ion_storm name = "Ion Storm" typepath = /datum/round_event/ion_storm - gamemode_blacklist = list("dynamic") weight = 15 min_players = 2 diff --git a/code/modules/events/major_dust.dm b/code/modules/events/major_dust.dm index c594d7b3c0..d7d8f1aec8 100644 --- a/code/modules/events/major_dust.dm +++ b/code/modules/events/major_dust.dm @@ -2,7 +2,6 @@ name = "Major Space Dust" typepath = /datum/round_event/meteor_wave/major_dust weight = 8 - gamemode_blacklist = list("dynamic") /datum/round_event/meteor_wave/major_dust wave_name = "space dust" diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm index 7763f9950d..e69af1df13 100644 --- a/code/modules/events/meteor_wave.dm +++ b/code/modules/events/meteor_wave.dm @@ -10,7 +10,6 @@ min_players = 15 max_occurrences = 3 earliest_start = 25 MINUTES - gamemode_blacklist = list("dynamic") /datum/round_event/meteor_wave startWhen = 6 @@ -23,7 +22,7 @@ /datum/round_event/meteor_wave/setup() announceWhen = 1 - startWhen = rand(90, 180) // Apparently it is by 2 seconds, so 90 is actually 180 seconds, and 180 is 360 seconds. So this is 3-6 minutes + startWhen = 150 // 5 minutes if(GLOB.singularity_counter) startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE) endWhen = startWhen + 60 diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm index 6e5512a617..698f5130f1 100644 --- a/code/modules/events/nightmare.dm +++ b/code/modules/events/nightmare.dm @@ -2,7 +2,6 @@ name = "Spawn Nightmare" typepath = /datum/round_event/ghost_role/nightmare max_occurrences = 1 - gamemode_blacklist = list("dynamic") min_players = 20 /datum/round_event/ghost_role/nightmare diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 9ab5e8d517..4cbfb8ae9a 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -5,7 +5,7 @@ max_occurrences = 1 min_players = 10 earliest_start = 30 MINUTES - gamemode_blacklist = list("nuclear","dynamic") + gamemode_blacklist = list("nuclear") /datum/round_event_control/pirates/preRunEvent() if (!SSmapping.empty_space) diff --git a/code/modules/events/portal_storm.dm b/code/modules/events/portal_storm.dm index 457b5bd4ec..5ef30d0030 100644 --- a/code/modules/events/portal_storm.dm +++ b/code/modules/events/portal_storm.dm @@ -4,7 +4,6 @@ weight = 2 min_players = 15 earliest_start = 30 MINUTES - gamemode_blacklist = list("dynamic") /datum/round_event/portal_storm/syndicate_shocktroop boss_types = list(/mob/living/simple_animal/hostile/syndicate/melee/space/stormtrooper = 2) diff --git a/code/modules/events/processor_overload.dm b/code/modules/events/processor_overload.dm index 22e475a8ef..6bedce6b4b 100644 --- a/code/modules/events/processor_overload.dm +++ b/code/modules/events/processor_overload.dm @@ -3,7 +3,6 @@ typepath = /datum/round_event/processor_overload weight = 15 min_players = 20 - gamemode_blacklist = list("dynamic") /datum/round_event/processor_overload announceWhen = 1 diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 0a5bedb464..36e16bb2c9 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -2,7 +2,6 @@ name = "Radiation Storm" typepath = /datum/round_event/radiation_storm max_occurrences = 1 - gamemode_blacklist = list("dynamic") /datum/round_event/radiation_storm diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index d1c327e0f7..23ce6ce730 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -2,7 +2,6 @@ name = "Spider Infestation" typepath = /datum/round_event/spider_infestation weight = 5 - gamemode_blacklist = list("dynamic") max_occurrences = 1 min_players = 15 diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index dc672cec45..cd7b23a577 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -3,7 +3,6 @@ typepath = /datum/round_event/vent_clog weight = 10 max_occurrences = 3 - gamemode_blacklist = list("dynamic") min_players = 25 /datum/round_event/vent_clog diff --git a/code/modules/events/wizard/ghost.dm b/code/modules/events/wizard/ghost.dm index d5366c5769..c288953efb 100644 --- a/code/modules/events/wizard/ghost.dm +++ b/code/modules/events/wizard/ghost.dm @@ -21,6 +21,6 @@ /datum/round_event/wizard/possession/start() for(var/mob/dead/observer/G in GLOB.player_list) - G.verbs += /mob/dead/observer/verb/boo - G.verbs += /mob/dead/observer/verb/possess + add_verb(G, /mob/dead/observer/verb/boo) + add_verb(G, /mob/dead/observer/verb/possess) to_chat(G, "You suddenly feel a welling of new spooky powers...") diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 1b4716b407..0920c9ccb6 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -4,7 +4,6 @@ max_occurrences = 3 weight = 2 min_players = 2 - gamemode_blacklist = list("dynamic") /datum/round_event/wormholes diff --git a/code/modules/food_and_drinks/food/snacks_cake.dm b/code/modules/food_and_drinks/food/snacks_cake.dm index 1117dbc3d3..be07826a7f 100644 --- a/code/modules/food_and_drinks/food/snacks_cake.dm +++ b/code/modules/food_and_drinks/food/snacks_cake.dm @@ -133,7 +133,7 @@ slices_num = 5 bonus_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 10) tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2) - foodtype = GRAIN | DAIRY | FRUIT | SUGAR + foodtype = GRAIN | DAIRY | FRUIT | SUGAR | ANTITOXIC /obj/item/reagent_containers/food/snacks/cakeslice/lime name = "lime cake slice" @@ -141,7 +141,7 @@ icon_state = "limecake_slice" filling_color = "#00FF00" tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2) - foodtype = GRAIN | DAIRY | FRUIT | SUGAR + foodtype = GRAIN | DAIRY | FRUIT | SUGAR | ANTITOXIC /obj/item/reagent_containers/food/snacks/store/cake/lemon name = "lemon cake" diff --git a/code/modules/food_and_drinks/food/snacks_frozen.dm b/code/modules/food_and_drinks/food/snacks_frozen.dm index 39c9c6c04f..32a89dbd58 100644 --- a/code/modules/food_and_drinks/food/snacks_frozen.dm +++ b/code/modules/food_and_drinks/food/snacks_frozen.dm @@ -103,7 +103,7 @@ icon_state = "lime_sc" list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/limejuice = 5) tastes = list("ice" = 1, "water" = 1, "limes" = 5) - foodtype = FRUIT + foodtype = FRUIT | ANTITOXIC /obj/item/reagent_containers/food/snacks/snowcones/lemon name = "lemon snowcone" @@ -191,7 +191,7 @@ icon_state = "fruitsalad_sc" list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/lemonjuice = 5, /datum/reagent/consumable/limejuice = 5, /datum/reagent/consumable/orangejuice = 5) tastes = list("ice" = 1, "water" = 1, "oranges" = 5, "limes" = 5, "lemons" = 5, "citrus" = 5, "salad" = 5) - foodtype = FRUIT + foodtype = FRUIT | ANTITOXIC /obj/item/reagent_containers/food/snacks/snowcones/pineapple name = "pineapple snowcone" diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index e0697cecea..b771a90907 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -232,7 +232,7 @@ list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/toxin = 1, /datum/reagent/iron = 10, /datum/reagent/consumable/sugar = 5, /datum/reagent/medicine/omnizine = 2) //lollipop, but vitamins = toxins filling_color = "#00800" tastes = list("cobwebs" = 1, "sugar" = 2) - foodtype = JUNKFOOD | SUGAR + foodtype = JUNKFOOD | SUGAR | ANTITOXIC /obj/item/reagent_containers/food/snacks/tobiko name = "tobiko" @@ -451,7 +451,7 @@ var/mutable_appearance/head var/headcolor = rgb(0, 0, 0) tastes = list("candy" = 1) - foodtype = JUNKFOOD | SUGAR + foodtype = JUNKFOOD | SUGAR | ANTITOXIC /obj/item/reagent_containers/food/snacks/lollipop/Initialize() . = ..() @@ -756,4 +756,4 @@ bitesize = 2 name = "hot-cross bun" desc = "The Cross represents the Assistants that died for your sins." - icon_state = "hotcrossbun" \ No newline at end of file + icon_state = "hotcrossbun" diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm index d65907daea..13a46395ea 100644 --- a/code/modules/food_and_drinks/food/snacks_pastry.dm +++ b/code/modules/food_and_drinks/food/snacks_pastry.dm @@ -509,7 +509,7 @@ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/medicine/omnizine = 3) cooked_type = null tastes = list("meat" = 2, "dough" = 2, "laziness" = 1) - foodtype = GRAIN + foodtype = GRAIN | ANTITOXIC /obj/item/reagent_containers/food/snacks/dankpocket name = "\improper Dank-pocket" @@ -556,9 +556,11 @@ name = "exceptional plump helmet biscuit" desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!" bonus_reagents = list(/datum/reagent/medicine/omnizine = 5, /datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + foodtype += ANTITOXIC . = ..() if(fey) reagents.add_reagent(/datum/reagent/medicine/omnizine, 5) + foodtype += ANTITOXIC /obj/item/reagent_containers/food/snacks/cracker name = "cracker" diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm index 81805f5529..24522503c1 100644 --- a/code/modules/food_and_drinks/food/snacks_pie.dm +++ b/code/modules/food_and_drinks/food/snacks_pie.dm @@ -171,8 +171,10 @@ name = "exceptional plump pie" desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!" bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/medicine/omnizine = 5, /datum/reagent/consumable/nutriment/vitamin = 4) + foodtype += ANTITOXIC if(fey) reagents.add_reagent(/datum/reagent/medicine/omnizine, 5) + foodtype += ANTITOXIC /obj/item/reagent_containers/food/snacks/pie/xemeatpie diff --git a/code/modules/food_and_drinks/food/snacks_pizza.dm b/code/modules/food_and_drinks/food/snacks_pizza.dm index f30c182963..75cf8ffb82 100644 --- a/code/modules/food_and_drinks/food/snacks_pizza.dm +++ b/code/modules/food_and_drinks/food/snacks_pizza.dm @@ -109,7 +109,7 @@ bonus_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 5) list_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/medicine/omnizine = 10, /datum/reagent/consumable/nutriment/vitamin = 5) tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1, "laziness" = 1) - foodtype = GRAIN | VEGETABLES | DAIRY | MEAT | JUNKFOOD + foodtype = GRAIN | VEGETABLES | DAIRY | MEAT | JUNKFOOD | ANTITOXIC /obj/item/reagent_containers/food/snacks/pizzaslice/donkpocket name = "donkpocket pizza slice" @@ -117,7 +117,7 @@ icon_state = "donkpocketpizzaslice" filling_color = "#FFA500" tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1, "laziness" = 1) - foodtype = GRAIN | VEGETABLES | DAIRY | MEAT | JUNKFOOD + foodtype = GRAIN | VEGETABLES | DAIRY | MEAT | JUNKFOOD | ANTITOXIC /obj/item/reagent_containers/food/snacks/pizza/dank name = "dank pizza" @@ -127,7 +127,7 @@ bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 6) list_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/doctor_delight = 5, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 5) tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1) - foodtype = GRAIN | VEGETABLES | FRUIT | DAIRY + foodtype = GRAIN | VEGETABLES | FRUIT | DAIRY | ANTITOXIC /obj/item/reagent_containers/food/snacks/pizzaslice/dank name = "dank pizza slice" @@ -135,7 +135,7 @@ icon_state = "dankpizzaslice" filling_color = "#2E8B57" tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1) - foodtype = GRAIN | VEGETABLES | FRUIT | DAIRY + foodtype = GRAIN | VEGETABLES | FRUIT | DAIRY | ANTITOXIC /obj/item/reagent_containers/food/snacks/pizza/sassysage name = "sassysage pizza" @@ -187,6 +187,7 @@ slice_path = /obj/item/reagent_containers/food/snacks/pizzaslice/arnold bonus_reagents = list(/datum/reagent/consumable/nutriment = 30, /datum/reagent/consumable/nutriment/vitamin = 6, /datum/reagent/iron = 10, /datum/reagent/medicine/omnizine = 30) tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pepperoni" = 2, "9 millimeter bullets" = 2) + /obj/item/reagent_containers/food/snacks/proc/try_break_off(mob/living/M, mob/living/user) //maybe i give you a pizza maybe i break off your arm var/obj/item/bodypart/l_arm = user.get_bodypart(BODY_ZONE_L_ARM) @@ -244,4 +245,4 @@ icon_state = "meatpizzaslice" filling_color = "#A52A2A" tastes = list("cardboard" = 1, "tomato" = 1, "cheese" = 1, "pepperoni" = 2) - foodtype = GRAIN | VEGETABLES | DAIRY | MEAT \ No newline at end of file + foodtype = GRAIN | VEGETABLES | DAIRY | MEAT diff --git a/code/modules/food_and_drinks/food/snacks_salad.dm b/code/modules/food_and_drinks/food/snacks_salad.dm index be7c3d25da..8c6eecb829 100644 --- a/code/modules/food_and_drinks/food/snacks_salad.dm +++ b/code/modules/food_and_drinks/food/snacks_salad.dm @@ -20,7 +20,7 @@ bonus_reagents = list(/datum/reagent/medicine/omnizine = 2, /datum/reagent/consumable/nutriment/vitamin = 6) list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/medicine/omnizine = 8, /datum/reagent/consumable/nutriment/vitamin = 6) tastes = list("leaves" = 1) - foodtype = VEGETABLES + foodtype = VEGETABLES | ANTITOXIC /obj/item/reagent_containers/food/snacks/salad/herbsalad name = "herb salad" @@ -38,7 +38,7 @@ bonus_reagents = list(/datum/reagent/consumable/doctor_delight = 5, /datum/reagent/consumable/nutriment/vitamin = 4) list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/doctor_delight = 5, /datum/reagent/consumable/nutriment/vitamin = 2) tastes = list("leaves" = 1, "potato" = 1, "meat" = 1, "valids" = 1) - foodtype = VEGETABLES | MEAT | FRIED | JUNKFOOD | FRUIT + foodtype = VEGETABLES | MEAT | FRIED | JUNKFOOD | FRUIT | ANTITOXIC /obj/item/reagent_containers/food/snacks/salad/oatmeal name = "oatmeal" @@ -133,7 +133,7 @@ trash = /obj/item/reagent_containers/glass/bowl list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/nutriment/vitamin = 5, /datum/reagent/medicine/earthsblood = 3, /datum/reagent/medicine/omnizine = 5, /datum/reagent/drug/happiness = 2) tastes = list("hope" = 1) - foodtype = VEGETABLES + foodtype = VEGETABLES | ANTITOXIC /obj/item/reagent_containers/food/snacks/salad/gumbo name = "black eyed gumbo" diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm index ffafcc6b1e..eea7cdb87d 100644 --- a/code/modules/food_and_drinks/food/snacks_soup.dm +++ b/code/modules/food_and_drinks/food/snacks_soup.dm @@ -89,7 +89,7 @@ icon_state = "nettlesoup" bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/medicine/omnizine = 5, /datum/reagent/consumable/nutriment/vitamin = 5) tastes = list("nettles" = 1) - foodtype = VEGETABLES + foodtype = VEGETABLES | ANTITOXIC /obj/item/reagent_containers/food/snacks/soup/mystery name = "mystery soup" diff --git a/code/modules/food_and_drinks/food/snacks_vend.dm b/code/modules/food_and_drinks/food/snacks_vend.dm index b4c7c89b74..4e8687fc23 100644 --- a/code/modules/food_and_drinks/food/snacks_vend.dm +++ b/code/modules/food_and_drinks/food/snacks_vend.dm @@ -89,7 +89,7 @@ list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/doctor_delight = 5) filling_color = "#F5F5DC" tastes = list("sweetness" = 3, "cake" = 1) - foodtype = GRAIN | FRUIT | VEGETABLES + foodtype = GRAIN | FRUIT | VEGETABLES | ANTITOXIC custom_price = PRICE_CHEAP /obj/item/reagent_containers/food/snacks/energybar diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm deleted file mode 100644 index ce27dccb74..0000000000 --- a/code/modules/goonchat/browserOutput.dm +++ /dev/null @@ -1,341 +0,0 @@ -/********************************* -For the main html chat area -*********************************/ - -/// Should match the value set in the browser js -#define MAX_COOKIE_LENGTH 5 - -//Precaching a bunch of shit. Someone ship this out of here -GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of icons for the browser output - -//lazy renaming to chat_output, instead renamed to old chatOutput -/** - * The chatOutput datum exists to handle the goonchat browser. - * On client, created on Client/New() - */ -/datum/chatOutput - /// The client that owns us. - var/client/owner - /// How many times client data has been checked - var/total_checks = 0 - /// When to next clear the client data checks counter - var/next_time_to_clear = 0 - /// Has the client loaded the browser output area? - var/loaded = FALSE - /// If they haven't loaded chat, this is where messages will go until they do - var/list/messageQueue - var/cookieSent = FALSE // Has the client sent a cookie for analysis - var/broken = FALSE - var/list/connectionHistory //Contains the connection history passed from chat cookie - var/adminMusicVolume = 25 //This is for the Play Global Sound verb - -/datum/chatOutput/New(client/C) - owner = C - messageQueue = list() - connectionHistory = list() - -/** - * start: Tries to load the chat browser - * Aborts if a problem is encountered. - * Async because this is called from Client/New. - */ -/datum/chatOutput/proc/start() - set waitfor = FALSE - //Check for existing chat - if(!owner) - return FALSE - - if(!winexists(owner, "browseroutput")) // Oh goddamnit. - broken = TRUE - message_admins("Couldn't start chat for [key_name_admin(owner)]!") - . = FALSE - alert(owner.mob, "Updated chat window does not exist. If you are using a custom skin file please allow the game to update.") - return - - if(winget(owner, "browseroutput", "is-visible") == "true") //Already setup - doneLoading() - - else //Not setup - load() - - return TRUE - -/// Loads goonchat and sends assets. -/datum/chatOutput/proc/load() - set waitfor = FALSE - if(!owner) - return - - var/datum/asset/stuff = get_asset_datum(/datum/asset/group/goonchat) - stuff.send(owner) - - owner << browse(file('code/modules/goonchat/browserassets/html/browserOutput.html'), "window=browseroutput") - -/// Interprets input from the client. Will send data back if required. -/datum/chatOutput/Topic(href, list/href_list) - if(usr.client != owner) - return TRUE - - // Build arguments. - // Arguments are in the form "param[paramname]=thing" - var/list/params = list() - for(var/key in href_list) - if(length_char(key) > 7 && findtext(key, "param")) // 7 is the amount of characters in the basic param key template. - var/param_name = copytext_char(key, 7, -1) - var/item = href_list[key] - - params[param_name] = item - - var/data // Data to be sent back to the chat. - switch(href_list["proc"]) - if("doneLoading") - data = doneLoading(arglist(params)) - - if("debug") - data = debug(arglist(params)) - - if("ping") - data = ping(arglist(params)) - - if("analyzeClientData") - data = analyzeClientData(arglist(params)) - - if("setMusicVolume") - data = setMusicVolume(arglist(params)) - if("colorPresetPost") //User just swapped color presets in their goonchat preferences. Do we do anything else? - switch(href_list["preset"]) - if("light") - owner.force_white_theme() - if("dark" || "normal") - owner.force_dark_theme() - // if("swaptodarkmode") - // swaptodarkmode() - // if("swaptolightmode") - // swaptolightmode() - - if(data) - ehjax_send(data = data) - - -/// Called on chat output done-loading by JS. -/datum/chatOutput/proc/doneLoading() - if(loaded) - return - - testing("Chat loaded for [owner.ckey]") - loaded = TRUE - showChat() - - - for(var/message in messageQueue) - // whitespace has already been handled by the original to_chat - to_chat(owner, message, handle_whitespace=FALSE) - - messageQueue = null - sendClientData() - - syncRegex() - - //do not convert to to_chat() - SEND_TEXT(owner, "Failed to load fancy chat, reverting to old chat. Certain features won't work.") - -/// Hides the standard output and makes the browser visible. -/datum/chatOutput/proc/showChat() - winset(owner, "output", "is-visible=false") - winset(owner, "browseroutput", "is-disabled=false;is-visible=true") - -/// Calls syncRegex on all currently owned chatOutput datums -/proc/syncChatRegexes() - for (var/user in GLOB.clients) - var/client/C = user - var/datum/chatOutput/Cchat = C.chatOutput - if (Cchat && !Cchat.broken && Cchat.loaded) - Cchat.syncRegex() - -/// Used to dynamically add regexes to the browser output. Currently only used by the IC filter. -/datum/chatOutput/proc/syncRegex() - var/list/regexes = list() - /* - if (config.ic_filter_regex) - regexes["show_filtered_ic_chat"] = list( - config.ic_filter_regex.name, - "ig", - "$1" - ) - */ - if (regexes.len) - ehjax_send(data = list("syncRegex" = regexes)) - -/// Sends json encoded data to the browser. -/datum/chatOutput/proc/ehjax_send(client/C = owner, window = "browseroutput", data) - if(islist(data)) - data = json_encode(data) - C << output("[data]", "[window]:ehjaxCallback") - -/** - * Sends music data to the browser. If enabled by the browser, it will start playing. - * Arguments: - * music must be a https adress. - * extra_data is a list. The keys "pitch", "start" and "end" are used. - ** "pitch" determines the playback rate - ** "start" determines the start time of the sound - ** "end" determines when the musics stops playing - */ -/datum/chatOutput/proc/sendMusic(music, pitch, list/extra_data) //someone remove pitch - if(!findtext(music, GLOB.is_http_protocol)) - return - var/list/music_data = list("adminMusic" = url_encode(url_encode(music))) - - if(extra_data?.len) - music_data["musicRate"] = extra_data["pitch"] || pitch - music_data["musicSeek"] = extra_data["start"] - music_data["musicHalt"] = extra_data["end"] - - ehjax_send(data = music_data) - -/// Stops music playing throw the browser. -/datum/chatOutput/proc/stopMusic() - ehjax_send(data = "stopMusic") - -/// Setter for adminMusicVolume. Sanitizes the value to between 0 and 100. -/datum/chatOutput/proc/setMusicVolume(volume = "") - if(volume) - adminMusicVolume = clamp(text2num(volume), 0, 100) - -/// Sends client connection details to the chat to handle and save -/datum/chatOutput/proc/sendClientData() - //Get dem deets - var/list/deets = list("clientData" = list()) - deets["clientData"]["ckey"] = owner.ckey - deets["clientData"]["ip"] = owner.address - deets["clientData"]["compid"] = owner.computer_id - var/data = json_encode(deets) - ehjax_send(data = data) - -/// Called by client, sent data to investigate (cookie history so far) -/datum/chatOutput/proc/analyzeClientData(cookie = "") - //Spam check - if(world.time > next_time_to_clear) - next_time_to_clear = world.time + (3 SECONDS) - total_checks = 0 - - total_checks += 1 - - if(total_checks > SPAM_TRIGGER_AUTOMUTE) - message_admins("[key_name(owner)] kicked for goonchat topic spam") - qdel(owner) - return - - if(!cookie) - return - - if(cookie != "none") - var/list/connData = json_decode(cookie) - if (connData && islist(connData) && connData.len > 0 && connData["connData"]) - connectionHistory = connData["connData"] //lol fuck - var/list/found = new() - - if(connectionHistory.len > MAX_COOKIE_LENGTH) - message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)") - qdel(owner) - return - - for(var/i in connectionHistory.len to 1 step -1) - if(QDELETED(owner)) - //he got cleaned up before we were done - return - var/list/row = src.connectionHistory[i] - if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object - return - if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE)) - found = row - break - CHECK_TICK - - //Uh oh this fucker has a history of playing on a banned account!! - if (found.len > 0) - message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") - log_admin_private("[key_name(owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") - - cookieSent = TRUE - -/// Called by js client every 60 seconds -/datum/chatOutput/proc/ping() - return "pong" - -/// Called by js client on js error -/datum/chatOutput/proc/debug(error) - log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]") - -/// Global chat proc. to_chat_immediate will circumvent SSchat and send data as soon as possible. -/proc/to_chat_immediate(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) - if(!target || !message) - return - - if(target == world) - target = GLOB.clients - - var/original_message = message - if(handle_whitespace) - message = replacetext(message, "\n", "
    ") - message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") //EIGHT SPACES IN TOTAL!! - if(trailing_newline) - message += "
    " - - if(islist(target)) - // Do the double-encoding outside the loop to save nanoseconds - var/twiceEncoded = url_encode(url_encode(message)) - for(var/I in target) - var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible - - if (!C) - continue - - //Send it to the old style output window. - SEND_TEXT(C, original_message) - - if(!C.chatOutput || C.chatOutput.broken) // A player who hasn't updated his skin file. - continue - - if(!C.chatOutput.loaded) - //Client still loading, put their messages in a queue - C.chatOutput.messageQueue += message - continue - - C << output(twiceEncoded, "browseroutput:output") - else - var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible - - if (!C) - return - - //Send it to the old style output window. - SEND_TEXT(C, original_message) - - if(!C.chatOutput || C.chatOutput.broken) // A player who hasn't updated his skin file. - return - - if(!C.chatOutput.loaded) - //Client still loading, put their messages in a queue - C.chatOutput.messageQueue += message - return - - // url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. - C << output(url_encode(url_encode(message)), "browseroutput:output") - -/// Sends a text message to the target. -/proc/to_chat(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) - if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) - to_chat_immediate(target, message, handle_whitespace, trailing_newline, confidential) - return - SSchat.queue(target, message, handle_whitespace, trailing_newline, confidential) - -/// Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation) -/datum/chatOutput/proc/swaptolightmode() - owner.force_white_theme() - -/// Light mode stuff. (See darkmode.dm for documentation) -/datum/chatOutput/proc/swaptodarkmode() - owner.force_dark_theme() - -#undef MAX_COOKIE_LENGTH diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css deleted file mode 100644 index 2669a3634a..0000000000 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ /dev/null @@ -1,464 +0,0 @@ -/***************************************** -* -* GLOBAL STYLES -* -******************************************/ -html, body { - padding: 0; - margin: 0; - height: 100%; - color: #000000; -} -body { - background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/ - font-family: Verdana, sans-serif; - font-size: 13px; - line-height: 1.2; - overflow-x: hidden; - overflow-y: scroll; - word-wrap: break-word; -} - -em { - font-style: normal; - font-weight: bold; -} - -img { - margin: 0; - padding: 0; - line-height: 1; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; -} -img.icon { - height: 1em; - min-height: 16px; - width: auto; - vertical-align: bottom; -} - - -.r:before { /* "repeated" badge class for combined messages */ - content: 'x'; -} -.r { - display: inline-block; - min-width: 0.5em; - font-size: 0.7em; - padding: 0.2em 0.3em; - line-height: 1; - color: white; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: crimson; - border-radius: 10px; -} - -a {color: #0000ff;} -a.visited {color: #ff00ff;} -a:visited {color: #ff00ff;} -a.popt {text-decoration: none;} - -/***************************************** -* -* OUTPUT NOT RELATED TO ACTUAL MESSAGES -* -******************************************/ -#loading { - position: fixed; - width: 300px; - height: 150px; - text-align: center; - left: 50%; - top: 50%; - margin: -75px 0 0 -150px; -} -#loading i {display: block; padding-bottom: 3px;} - -#messages { - font-size: 13px; - padding: 3px; - margin: 0; - word-wrap: break-word; -} -#newMessages { - position: fixed; - display: block; - bottom: 0; - right: 0; - padding: 8px; - background: #d0d0d0; - text-decoration: none; - font-variant: small-caps; - font-size: 1.1em; - font-weight: bold; - color: #333; -} -#newMessages:hover {background: #ccc;} -#newMessages i {vertical-align: middle; padding-left: 3px;} -#ping { - position: fixed; - top: 0; - right: 135px; - width: 45px; - background: #d0d0d0; - height: 30px; - padding: 8px 0 2px 0; -} -#ping i {display: block; text-align: center;} -#ping .ms { - display: block; - text-align: center; - font-size: 8pt; - padding-top: 2px; -} -#userBar { - position: fixed; - top: 0; - right: 0; -} -#userBar .subCell { - background: #d0d0d0; - height: 30px; - padding: 5px 0; - display: block; - color: #333; - text-decoration: none; - line-height: 28px; - border-top: 1px solid #b4b4b4; -} -#userBar .subCell:hover {background: #ccc;} -#userBar .toggle { - width: 45px; - background: #ccc; - border-top: 0; - float: right; - text-align: center; -} -#userBar .sub {clear: both; display: none; width: 180px;} -#userBar .sub.scroll {overflow-y: scroll;} -#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;} -#userBar .sub span { - display: block; - line-height: 30px; - float: left; -} -#userBar .sub i { - display: block; - padding: 0 5px; - font-size: 1.1em; - width: 22px; - text-align: center; - line-height: 30px; - float: right; -} -#userBar .sub input { - position: absolute; - padding: 7px 5px; - width: 121px; - line-height: 30px; - float: left; -} -#userBar .topCell {border-top: 0;} - -/* POPUPS */ -.popup { - position: fixed; - top: 50%; - left: 50%; - background: #d0d0d0; -} -.popup .close { - position: absolute; - background: #aaa; - top: 0; - right: 0; - color: #333; - text-decoration: none; - z-index: 2; - padding: 0 10px; - height: 30px; - line-height: 30px; -} -.popup .close:hover {background: #999;} -.popup .head { - background: #999; - color: #d0d0d0; - padding: 0 10px; - height: 30px; - line-height: 30px; - text-transform: uppercase; - font-size: 0.9em; - font-weight: bold; - border-bottom: 2px solid green; -} -.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;} -.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;} -.popup input[type=submit] {padding: 5px 10px; background: #999; color: #d0d0d0; text-transform: uppercase; font-size: 0.9em; font-weight: bold;} -.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;} - -.changeFont {padding: 10px;} -.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;} -.changeFont a:hover {background: #ccc;} - -.highlightPopup {padding: 10px; text-align: center;} -.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;} -.highlightPopup input.highlightColor {background-color: #FFFF00;} -.highlightPopup input.highlightTermSubmit {margin-top: 5px;} - -/* ADMIN CONTEXT MENU */ -.contextMenu { - background-color: #d0d0d0; - position: fixed; - margin: 2px; - width: 150px; -} -.contextMenu a { - display: block; - padding: 2px 5px; - text-decoration: none; - color: #333; -} - -.contextMenu a:hover { - background-color: #ccc; -} - -/* ADMIN FILTER MESSAGES MENU */ -.filterMessages {padding: 5px;} -.filterMessages div {padding: 2px 0;} -.filterMessages input {} -.filterMessages label {} - -.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;} - - -/***************************************** -* -* OUTPUT ACTUALLY RELATED TO MESSAGES -* -******************************************/ - -/* MOTD */ -.motd {color: #638500; font-family: Verdana, sans-serif;} -.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;} -.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;} - -/* ADD HERE FOR BOLD */ -.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;} - -/* ADD HERE FOR ITALIC */ -.italic, .italics, .emote {font-style: italic;} - -/* OUTPUT COLORS */ -.highlight {background: yellow;} - -h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;} -h1.alert, h2.alert {color: #000000;} - -em {font-style: normal; font-weight: bold;} - -.ooc {color: #002eb8; font-weight: bold;} -.looc {color: #6699CC; font-weight: bold;} -.antagooc {color: #b8002e; font-weight: bold;} -.adminobserverooc {color: #0099cc; font-weight: bold;} -.adminooc {color: #700038; font-weight: bold;} - -.adminsay {color: #FF4500} -.admin {color: #386aff; font-weight: bold;} - -.name { font-weight: bold;} - -.say {} -.deadsay {color: #5c00e6;} -.binarysay {color: #20c20e; background-color: #000000; display: block;} -.binarysay a {color: #00ff00;} -.binarysay a:active, .binarysay a:visited {color: #88ff88;} -.radio {color: #008000;} -.sciradio {color: #993399;} -.comradio {color: #948f02;} -.secradio {color: #a30000;} -.medradio {color: #337296;} -.engradio {color: #fb5613;} -.suppradio {color: #a8732b;} -.servradio {color: #6eaa2c;} -.syndradio {color: #6d3f40;} -.centcomradio {color: #686868;} -.aiprivradio {color: #ff00ff;} -.redteamradio {color: #ff0000;} -.blueteamradio {color: #0000ff;} - -.yell { font-weight: bold;} - -.alert {color: #ff0000;} -h1.alert, h2.alert {color: #000000;} - -.emote { font-style: italic;} -.selecteddna {color: #ffffff; background-color: #001B1B} - -.attack {color: #ff0000;} -.disarm {color: #990000;} -.passive {color: #660000;} - -.userdanger {color: #ff0000; font-weight: bold; font-size: 185%;} -.bolddanger {color: #c51e1e;font-weight: bold;} -.danger {color: #ff0000;} -.tinydanger {color: #c51e1e; font-size: 85%;} -.smalldanger {color: #c51e1e; font-size: 90%;} -.warning {color: #ff0000; font-style: italic;} -.alertwarning {color: #FF0000; font-weight: bold} -.boldwarning {color: #ff0000; font-style: italic; font-weight: bold} -.announce {color: #228b22; font-weight: bold;} -.boldannounce {color: #ff0000; font-weight: bold;} -.greenannounce {color: #00ff00; font-weight: bold;} -.rose {color: #ff5050;} -.info {color: #0000CC;} -.notice {color: #000099;} -.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;} -.smallnotice {color: #6685f5; font-size: 90%;} -.smallnoticeital {color: #6685f5; font-style: italic; font-size: 90%;} -.boldnotice {color: #000099; font-weight: bold;} -.adminnotice {color: #0000ff;} -.adminhelp {color: #ff0000; font-weight: bold;} -.unconscious {color: #0000ff; font-weight: bold;} -.suicide {color: #ff5050; font-style: italic;} -.green {color: #03ff39;} -.red {color: #FF0000;} -.pink {color: #FF69Bf;} -.blue {color: #0000FF;} -.nicegreen {color: #14a833;} -.userlove {color: #FF1493; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #ff6dbc;} -.love {color: #ff006a; font-style: italic; text-shadow: 0 0 6px #ff6d6d;} -.shadowling {color: #3b2769;} -.cult {color: #960000;} - -.cultitalic {color: #960000; font-style: italic;} -.cultbold {color: #960000; font-style: italic; font-weight: bold;} -.cultboldtalic {color: #960000; font-weight: bold; font-size: 185%;} - -.cultlarge {color: #960000; font-weight: bold; font-size: 185%;} -.narsie {color: #960000; font-weight: bold; font-size: 925%;} -.narsiesmall {color: #960000; font-weight: bold; font-size: 370%;} -.colossus {color: #7F282A; font-size: 310%;} -.hierophant {color: #660099; font-weight: bold; font-style: italic;} -.hierophant_warning {color: #660099; font-style: italic;} -.purple {color: #5e2d79;} -.holoparasite {color: #35333a;} - -.revennotice {color: #1d2953;} -.revenboldnotice {color: #1d2953; font-weight: bold;} -.revenbignotice {color: #1d2953; font-weight: bold; font-size: 185%;} -.revenminor {color: #823abb} -.revenwarning {color: #760fbb; font-style: italic;} -.revendanger {color: #760fbb; font-weight: bold; font-size: 185%;} -.umbra {color: #5000A0;} -.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;} -.umbra_large {color: #5000A0; font-size: 185%; font-weight: bold; font-style: italic;} - -.deconversion_message {color: #5000A0; font-size: 185%; font-style: italic;} - -.brass {color: #BE8700;} -.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;} -.large_brass {color: #BE8700; font-size: 185%;} -.big_brass {color: #BE8700; font-size: 185%; font-weight: bold; font-style: italic;} -.ratvar {color: #BE8700; font-size: 370%; font-weight: bold; font-style: italic;} -.alloy {color: #42474D;} -.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;} -.nezbere_large {color: #42474D; font-size: 185%; font-weight: bold; font-style: italic;} -.nezbere {color: #42474D; font-weight: bold; font-style: italic;} -.nezbere_small {color: #42474D;} -.sevtug_large {color: #AF0AAF; font-size: 185%; font-weight: bold; font-style: italic;} -.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;} -.sevtug_small {color: #AF0AAF;} -.inathneq_large {color: #1E8CE1; font-size: 185%; font-weight: bold; font-style: italic;} -.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;} -.inathneq_small {color: #1E8CE1;} -.nzcrentr_large {color: #DAAA18; font-size: 185%; font-weight: bold; font-style: italic;} -.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;} -.nzcrentr_small {color: #DAAA18;} -.neovgre_large {color: #6E001A; font-size: 185%; font-weight: bold; font-style: italic;} -.neovgre {color: #6E001A; font-weight: bold; font-style: italic;} -.neovgre_small {color: #6E001A;} - -.newscaster {color: #800000;} -.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;} - -.alien {color: #543354;} -.noticealien {color: #00c000;} -.alertalien {color: #00c000; font-weight: bold;} -.changeling {color: #800080; font-style: italic;} - -.spider {color: #4d004d; font-weight: bold; font-size: 185%;} - -.interface {color: #330033;} - -.sans {font-family: "Comic Sans MS", cursive, sans-serif;} -.papyrus {font-family: "Papyrus", cursive, sans-serif;} -.robot {font-family: "Courier New", cursive, sans-serif;} - -.command_headset {font-weight: bold; font-size: 160%;} -.small {font-size: 60%;} -.big {font-size: 185%;} -.reallybig {font-size: 245%;} -.extremelybig {font-size: 310%;} -.greentext {color: #00FF00; font-size: 185%;} -.redtext {color: #FF0000; font-size: 185%;} -.clown {color: #FF69Bf; font-size: 160%; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;} -.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;} -.spooky {color: #FF6100;} -.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;} - -.lethal {color: #bf3d3d; font-weight: bold;} -.stun {color: #0f81bc; font-weight: bold;} -.ion {color: #d084d6; font-weight: bold;} -.xray {color: #32c025; font-weight: bold;} - -@keyframes velvet { - 0% { color: #400020; } - 40% { color: #FF0000; } - 50% { color: #FF8888; } - 60% { color: #FF0000; } - 100% { color: #400020; } -} - -.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;} -@keyframes hypnocolor { - 0% { color: #202020; } - 25% { color: #4b02ac; } - 50% { color: #9f41f1; } - 75% { color: #541c9c; } - 100% { color: #7adbf3; } -} - -.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;} -@keyframes phobia { - 0% { color: #f75a5a; } - 50% { color: #dd0000; } - 100% { color: #f75a5a; } -} - - -.icon {height: 1em; width: auto;} - -.memo {color: #638500; text-align: center;} -.memoedit {text-align: center; font-size: 125%;} -.abductor {color: #800080; font-style: italic;} -.mind_control {color: #A00D6F; font-size: 100%; font-weight: bold; font-style: italic;} -.slime {color: #00CED1;} -.drone {color: #848482;} -.monkey {color: #975032;} -.swarmer {color: #2C75FF;} -.resonate {color: #298F85;} - -.monkeyhive {color: #774704;} -.monkeylead {color: #774704; font-size: 125%;} - -.connectionClosed, .fatalError {background: red; color: white; padding: 5px;} -.connectionClosed.restored {background: green;} -.internal.boldnshit {color: #000099; font-weight: bold;} - -/* HELPER CLASSES */ -.text-normal {font-weight: normal; font-style: normal;} -.hidden {display: none; visibility: hidden;} diff --git a/code/modules/goonchat/browserassets/css/browserOutput_dark.css b/code/modules/goonchat/browserassets/css/browserOutput_dark.css deleted file mode 100644 index 3377bcf72c..0000000000 --- a/code/modules/goonchat/browserassets/css/browserOutput_dark.css +++ /dev/null @@ -1,159 +0,0 @@ -html, body {color: #E0E0E0;} -body { - background: #171717; - font-color: #E0E0E0; - scrollbar-face-color:#1A1A1A; - scrollbar-track-color:#171717; - scrollbar-highlight-color:#171717; -} - -a {color: #397ea5;} -a.visited {color: #7c00e6;} -a:visited {color: #7c00e6;} - -#newMessages { - background: #242424; - color: #E0E0E0; -} -#newMessages:hover {background: #272727;} - -#ping {background: #272727;} - -#userBar .subCell { - background: #272727; - color: #E0E0E0; - border-top: 1px solid #171717; -} -#userBar .subCell:hover {background: #272727;} -#userBar .toggle {background: #272727;} - -/* MOTD */ -.motd {color: #E0E0E0;} -.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #E0E0E0;} -.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #E0E0E0;} - -h1, h2, h3, h4, h5, h6 {color: #E0E0E0;} -h1.alert, h2.alert {color: #E0E0E0;} - -.ooc {color: #cca300;} -.looc {color: #d8b555;} -.antagooc {color: #ce254f;} -.adminobserverooc {color: #0099cc;} -.adminooc {color: #3d5bc3;} - -.admin {color: #5975da;} - -.deadsay {color: #e2c1ff;} -.radio {color: #1ecc43;} -.sciradio {color: #c68cfa;} -.comradio {color: #5177ff;} -.secradio {color: #dd3535;} -.medradio {color: #57b8f0;} -.engradio {color: #f37746;} -.suppradio {color: #b88646;} -.servradio {color: #6ca729;} -.syndradio {color: #8f4a4b;} -.centcomradio {color: #2681a5;} -.aiprivradio {color: #d65d95;} -.redteamradio {color: #ff4444;} -.blueteamradio {color: #3434fd;} - -.alert {color: #d82020;} -h1.alert, h2.alert {color: #99aab5;} - -.attack {color: #e01c1c;} -.disarm {color: #b42525;} -.passive {color: #a00f0f;} - -.userdanger {color: #c51e1e;} -.danger {color: #c51e1e;} -.warning {color: #c51e1e;} -.alertwarning {color: #c51e1e;} -.boldwarning {color: #c51e1e;} -.announce {color: #c51e1e;} -.boldannounce {color: #c51e1e;} -.greenannounce {color: #059223;} -.info {color: #6685f5;} -.notice {color: #6685f5;} -.boldnotice {color: #6685f5;} -.adminnotice {color: #6685f5;} -.adminhelp {color: #ff0000;} -.unconscious {color: #E0E0E0;} -.red {color: #FF0000;} -.pink {color: #ff70c1;} -.blue {color: #215cff;} -.green {color: #059223;} -.nicegreen {color: #059223;} -.userlove {color: #ff42a6; text-shadow: 0 0 6px #82365e;} -.love {color: #ff4591; text-shadow: 0 0 6px #994449;} -.shadowling {color: #8e8a99;} -.cult {color: #aa1c1c;} - -.cultitalic {color: #aa1c1c;} -.cultbold {color: #aa1c1c;} -.cultboldtalic {color: #aa1c1c;} - -.cultlarge {color: #aa1c1c;} -.narsie {color: #aa1c1c;} -.narsiesmall {color: #aa1c1c;} -.hierophant {color: #b441ee;} -.hierophant_warning {color: #c56bf1;} -.purple {color: #9956d3;} -.holoparasite {color: #88809c;} - -.revennotice {color: #3645aa;} -.revenboldnotice {color: #3645aa;} -.revenbignotice {color: #3645aa;} -.revenminor {color: #823ddd;} -.revenwarning {color: #8911d9;} -.revendanger {color: #8911d9;} -.umbra {color: #7c00e6;} -.umbra_emphasis {color: #7c00e6;} -.umbra_large {color: #7c00e6;} - -.deconversion_message {color: #a947ff;} - -.alloy {color: #545b64;} -.heavy_alloy {color: #545b64;} -.nezbere_large {color: #545b64;} -.nezbere {color: #545b64;} -.nezbere_small {color: #545b64;} -.inathneq_large {color: #1d7dc7;} -.inathneq {color: #1d7dc7;} -.inathneq_small {color: #1d7dc7;} -.neovgre_large {color: #7c0622;} -.neovgre {color: #7c0622;} -.neovgre_small {color: #7c0622;} - -.newscaster {color: #c05d5d;} -.ghostalert {color: #6600ff;} - -.alien {color: #855d85;} -.noticealien {color: #059223;} -.alertalien {color: #059223;} -.changeling {color: #059223;} - -.spider {color: #8800ff;} - -.interface {color: #750e75;} - -.greentext {color: #059223;} -.redtext {color: #c51e1e;} -.clown {color: #ff70c1;} -.velvet {color: #660015;} -@keyframes velvet { - 0% { color: #890020; } - 40% { color: #c51e1e; } - 50% { color: #FF8888; } - 60% { color: #c51e1e; } - 100% { color: #890020; } -} - -.abductor {color: #c204c2;} -.mind_control {color: #df3da9;} -.drone {color: #979795;} - -.monkeyhive {color: #a56408;} -.monkeylead {color: #af6805;} - -.internal.boldnshit {color: #3d5bc3;} diff --git a/code/modules/goonchat/browserassets/css/browserOutput_light.css b/code/modules/goonchat/browserassets/css/browserOutput_light.css deleted file mode 100644 index b7036c74d8..0000000000 --- a/code/modules/goonchat/browserassets/css/browserOutput_light.css +++ /dev/null @@ -1,14 +0,0 @@ -body {background: #F1F1F1;} - -#newMessages {background: #ddd;} -#ping {background: #ddd;} - -#userBar .subCell {background: #ddd;} - -/* POPUPS */ -.popup {background: #ddd;} -.popup .head {color: #ddd;} -.popup input[type=submit] {color: #ddd;} - -/* ADMIN CONTEXT MENU */ -.contextMenu {background-color: #ddd;} diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html deleted file mode 100644 index ce51cd8de8..0000000000 --- a/code/modules/goonchat/browserassets/html/browserOutput.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - Chat - - - - - - - - - - -
    - -
    - Loading...

    - If this takes longer than 30 seconds, it will automatically reload a maximum of 5 times.
    - If it still doesn't work, use the bug report button at the top right of the window. -
    -
    -
    - -
    - - - - - diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js deleted file mode 100644 index ac30076de4..0000000000 --- a/code/modules/goonchat/browserassets/js/browserOutput.js +++ /dev/null @@ -1,1104 +0,0 @@ - -/***************************************** -* -* FUNCTION AND VAR DECLARATIONS -* -******************************************/ - -//DEBUG STUFF -var escaper = encodeURIComponent || escape; -var decoder = decodeURIComponent || unescape; -window.onerror = function(msg, url, line, col, error) { - if (document.location.href.indexOf("proc=debug") <= 0) { - var extra = !col ? '' : ' | column: ' + col; - extra += !error ? '' : ' | error: ' + error; - extra += !navigator.userAgent ? '' : ' | user agent: ' + navigator.userAgent; - var debugLine = 'Error: ' + msg + ' | url: ' + url + ' | line: ' + line + extra; - window.location = '?_src_=chat&proc=debug¶m[error]='+escaper(debugLine); - } - return true; -}; - -//Globals -window.status = 'Output'; -var $messages, $subOptions, $subAudio, $selectedSub, $contextMenu, $filterMessages, $last_message; -var opts = { - //General - 'messageCount': 0, //A count...of messages... - 'messageLimit': 2053, //A limit...for the messages... - 'scrollSnapTolerance': 10, //If within x pixels of bottom - 'clickTolerance': 10, //Keep focus if outside x pixels of mousedown position on mouseup - 'imageRetryDelay': 50, //how long between attempts to reload images (in ms) - 'imageRetryLimit': 50, //how many attempts should we make? - 'popups': 0, //Amount of popups opened ever - 'wasd': false, //Is the user in wasd mode? - 'priorChatHeight': 0, //Thing for height-resizing detection - 'restarting': false, //Is the round restarting? - 'colorPreset': 0, // index in the color presets list. - //'darkmode':false, //Are we using darkmode? If not WHY ARE YOU LIVING IN 2009??? <- /tg/ take on darktheme - - //Options menu - 'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu - 'suppressSubClose': false, //Whether or not we should be hiding the selected sub menu - 'highlightTerms': [], - 'highlightLimit': 5, - 'highlightColor': '#FFFF00', //The color of the highlighted message - 'pingDisabled': false, //Has the user disabled the ping counter - - //Ping display - 'lastPang': 0, //Timestamp of the last response from the server. - 'pangLimit': 35000, - 'pingTime': 0, //Timestamp of when ping sent - 'pongTime': 0, //Timestamp of when ping received - 'noResponse': false, //Tracks the state of the previous ping request - 'noResponseCount': 0, //How many failed pings? - - //Clicks - 'mouseDownX': null, - 'mouseDownY': null, - 'preventFocus': false, //Prevents switching focus to the game window - - //Client Connection Data - 'clientDataLimit': 5, - 'clientData': [], - - //Admin music volume update - 'volumeUpdateDelay': 5000, //Time from when the volume updates to data being sent to the server - 'volumeUpdating': false, //True if volume update function set to fire - 'updatedVolume': 0, //The volume level that is sent to the server - 'musicStartAt': 0, //The position the music starts playing - 'musicEndAt': 0, //The position the music... stops playing... if null, doesn't apply (so the music runs through) - - 'defaultMusicVolume': 25, - - 'messageCombining': true, - -}; -var replaceRegexes = {}; - -// Array of names for chat display color presets. CIT SPECIFIC. -// If not set to normal, a CSS file `browserOutput_${name}.css` will be added to the head. -var colorPresets = [ - 'normal', - 'light', - 'dark' -] - -function clamp(val, min, max) { - return Math.max(min, Math.min(val, max)) -} - -//Polyfill for fucking date now because of course IE8 and below don't support it -if (!Date.now) { - Date.now = function now() { - return new Date().getTime(); - }; -} -//Polyfill for trim() (IE8 and below) -if (typeof String.prototype.trim !== 'function') { - String.prototype.trim = function () { - return this.replace(/^\s+|\s+$/g, ''); - }; -} - -// CIT SPECIFIC. -function updateColorPreset() { - var el = $("#colorPresetLink")[0]; - el.href = "browserOutput_"+colorPresets[opts.colorPreset]+".css"; - runByond('?_src_=chat&proc=colorPresetPost&preset='+colorPresets[opts.colorPreset]); -} - -// Linkify the contents of a node, within its parent. -function linkify(parent, insertBefore, text) { - var start = 0; - var match; - var regex = /(?:(?:https?:\/\/)|(?:www\.))(?:[^ ]*?\.[^ ]*?)+[-A-Za-z0-9+&@#\/%?=~_|$!:,.;()]+/ig; - while ((match = regex.exec(text)) !== null) { - // add the unmatched text - parent.insertBefore(document.createTextNode(text.substring(start, match.index)), insertBefore); - - var href = match[0]; - if (!/^https?:\/\//i.test(match[0])) { - href = "http://" + match[0]; - } - - // add the link - var link = document.createElement("a"); - link.href = href; - link.textContent = match[0]; - parent.insertBefore(link, insertBefore); - - start = regex.lastIndex; - } - if (start !== 0) { - // add the remaining text and remove the original text node - parent.insertBefore(document.createTextNode(text.substring(start)), insertBefore); - parent.removeChild(insertBefore); - } -} - -// Recursively linkify the children of a given node. -function linkify_node(node) { - var children = node.childNodes; - // work backwards to avoid the risk of looping forever on our own output - for (var i = children.length - 1; i >= 0; --i) { - var child = children[i]; - if (child.nodeType == Node.TEXT_NODE) { - // text is to be linkified - linkify(node, child, child.textContent); - } else if (child.nodeName != "A" && child.nodeName != "a") { - // do not linkify existing links - linkify_node(child); - } - } -} - -//Shit fucking piece of crap that doesn't work god fuckin damn it -function linkify_fallback(text) { - var rex = /((?:'+$0+''; - } - else { - return $1 ? $0: ''+$0+''; - } - }); -} - -function byondDecode(message) { - // Basically we url_encode twice server side so we can manually read the encoded version and actually do UTF-8. - // The replace for + is because FOR SOME REASON, BYOND replaces spaces with a + instead of %20, and a plus with %2b. - // Marvelous. - message = message.replace(/\+/g, "%20"); - try { - // This is a workaround for the above not always working when BYOND's shitty url encoding breaks. (byond bug id:2399401) - if (decodeURIComponent) { - message = decodeURIComponent(message); - } else { - throw new Error("Easiest way to trigger the fallback") - } - } catch (err) { - message = unescape(message); - } - return message; -} - -function replaceRegex() { - var selectedRegex = replaceRegexes[$(this).attr('replaceRegex')]; - if (selectedRegex) { - var replacedText = $(this).html().replace(selectedRegex[0], selectedRegex[1]); - $(this).html(replacedText); - } - $(this).removeAttr('replaceRegex'); -} - -// Get a highlight markup span -function createHighlightMarkup() { - var extra = ''; - if (opts.highlightColor) { - extra += ' style="background-color: ' + opts.highlightColor + '"'; - } - return ''; -} - -// Get all child text nodes that match a regex pattern -function getTextNodes(elem, pattern) { - var result = $([]); - $(elem).contents().each(function(idx, child) { - if (child.nodeType === 3 && /\S/.test(child.nodeValue) && pattern.test(child.nodeValue)) { - result = result.add(child); - } - else { - result = result.add(getTextNodes(child, pattern)); - } - }); - return result; -} - -// Highlight all text terms matching the registered regex patterns -function highlightTerms(el) { - var pattern = new RegExp("(" + opts.highlightTerms.join('|') + ")", 'gi'); - var nodes = getTextNodes(el, pattern); - - nodes.each(function (idx, node) { - var content = $(node).text(); - var parent = $(node).parent(); - var pre = $(node.previousSibling); - $(node).remove(); - content.split(pattern).forEach(function (chunk) { - // Get our highlighted span/text node - var toInsert = null; - if (pattern.test(chunk)) { - var tmpElem = $(createHighlightMarkup()); - tmpElem.text(chunk); - toInsert = tmpElem; - } - else { - toInsert = document.createTextNode(chunk); - } - - // Insert back into our element - if (pre.length == 0) { - var result = parent.prepend(toInsert); - pre = $(result[0].firstChild); - } - else { - pre.after(toInsert); - pre = $(pre[0].nextSibling); - } - }); - }); -} - -function iconError(E) { - var that = this; - setTimeout(function() { - var attempts = $(that).data('reload_attempts'); - if (typeof attempts === 'undefined' || !attempts) { - attempts = 1; - } - if (attempts > opts.imageRetryLimit) - return; - var src = that.src; - that.src = null; - that.src = src+'#'+attempts; - $(that).data('reload_attempts', ++attempts); - }, opts.imageRetryDelay); -} - -//Send a message to the client -function output(message, flag) { - if (typeof message === 'undefined') { - return; - } - if (typeof flag === 'undefined') { - flag = ''; - } - - if (flag !== 'internal') - opts.lastPang = Date.now(); - - message = byondDecode(message).trim(); - - //The behemoth of filter-code (for Admin message filters) - //Note: This is proooobably hella inefficient - var filteredOut = false; - if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) { - //Get this filter type (defined by class on message) - var messageHtml = $.parseHTML(message), - messageClasses; - if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) { - var internal = false; - messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false); - if (messageClasses) { - for (var i = 0; i < messageClasses.length; i++) { //Every class - if (messageClasses[i] == 'internal') { - internal = true; - break; - } - } - } - if (!internal) { - filteredOut = 'All'; - } - } else { - //If the element or it's child have any classes - if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) { - messageClasses = $(messageHtml).attr('class').split(/\s+/); - if (!!$(messageHtml).children().attr('class')) { - messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/)); - } - var tempCount = 0; - for (var i = 0; i < messageClasses.length; i++) { //Every class - var thisClass = messageClasses[i]; - $.each(opts.showMessagesFilters, function(key, val) { //Every filter - if (key !== 'All' && val.show === false && typeof val.match != 'undefined') { - for (var i = 0; i < val.match.length; i++) { - var matchClass = val.match[i]; - if (matchClass == thisClass) { - filteredOut = key; - break; - } - } - } - if (filteredOut) return false; - }); - if (filteredOut) break; - tempCount++; - } - } else { - if (!opts.showMessagesFilters['Misc'].show) { - filteredOut = 'Misc'; - } - } - } - } - - //Stuff we do along with appending a message - var atBottom = false; - if (!filteredOut) { - var bodyHeight = $('body').height(); - var messagesHeight = $messages.outerHeight(); - var scrollPos = $('body,html').scrollTop(); - - //Should we snap the output to the bottom? - if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { - atBottom = true; - if ($('#newMessages').length) { - $('#newMessages').remove(); - } - //If not, put the new messages box in - } else { - if ($('#newMessages').length) { - var messages = $('#newMessages .number').text(); - messages = parseInt(messages); - messages++; - $('#newMessages .number').text(messages); - if (messages == 2) { - $('#newMessages .messageWord').append('s'); - } - } else { - $messages.after('1 new message '); - } - } - } - - opts.messageCount++; - - //Pop the top message off if history limit reached - if (opts.messageCount >= opts.messageLimit) { - $messages.children('div.entry:first-child').remove(); - opts.messageCount--; //I guess the count should only ever equal the limit - } - - // Create the element - if combining is off, we use it, and if it's on, we - // might discard it bug need to check its text content. Some messages vary - // only in HTML markup, have the same text content, and should combine. - var entry = document.createElement('div'); - entry.innerHTML = message; - var trimmed_message = entry.textContent || entry.innerText || ""; - - var handled = false; - if (opts.messageCombining) { - var lastmessages = $messages.children('div.entry:last-child').last(); - if (lastmessages.length && $last_message && $last_message == trimmed_message) { - var badge = lastmessages.children('.r').last(); - if (badge.length) { - badge = badge.detach(); - badge.text(parseInt(badge.text()) + 1); - } else { - badge = $('', {'class': 'r', 'text': 2}); - } - lastmessages.html(message); - lastmessages.find('[replaceRegex]').each(replaceRegex); - lastmessages.append(badge); - badge.animate({ - "font-size": "0.9em" - }, 100, function() { - badge.animate({ - "font-size": "0.7em" - }, 100); - }); - opts.messageCount--; - handled = true; - } - } - - if (!handled) { - //Actually append the message - entry.className = 'entry'; - - if (filteredOut) { - entry.className += ' hidden'; - entry.setAttribute('data-filter', filteredOut); - } - - $(entry).find('[replaceRegex]').each(replaceRegex); - - $last_message = trimmed_message; - $messages[0].appendChild(entry); - $(entry).find("img.icon").error(iconError); - - var to_linkify = $(entry).find(".linkify"); - if (typeof Node === 'undefined') { - // Linkify fallback for old IE - for(var i = 0; i < to_linkify.length; ++i) { - to_linkify[i].innerHTML = linkify_fallback(to_linkify[i].innerHTML); - } - } else { - // Linkify for modern IE versions - for(var i = 0; i < to_linkify.length; ++i) { - linkify_node(to_linkify[i]); - } - } - - //Actually do the snap - //Stuff we can do after the message shows can go here, in the interests of responsiveness - if (opts.highlightTerms && opts.highlightTerms.length > 0) { - highlightTerms($(entry)); - } - } - - if (!filteredOut && atBottom) { - $('body,html').scrollTop($messages.outerHeight()); - } -} - -function internalOutput(message, flag) -{ - output(escaper(message), flag) -} - -//Runs a route within byond, client or server side. Consider this "ehjax" for byond. -function runByond(uri) { - window.location = uri; -} - -function setCookie(cname, cvalue, exdays) { - cvalue = escaper(cvalue); - var d = new Date(); - d.setTime(d.getTime() + (exdays*24*60*60*1000)); - var expires = 'expires='+d.toUTCString(); - document.cookie = cname + '=' + cvalue + '; ' + expires + "; path=/"; -} - -function getCookie(cname) { - var name = cname + '='; - var ca = document.cookie.split(';'); - for(var i=0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0)==' ') c = c.substring(1); - if (c.indexOf(name) === 0) { - return decoder(c.substring(name.length,c.length)); - } - } - return ''; -} - -function rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B);} -function toHex(n) { - n = parseInt(n,10); - if (isNaN(n)) return "00"; - n = Math.max(0,Math.min(n,255)); - return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16); -} - -/* -function swap() { //Swap to darkmode - if (opts.darkmode){ - document.getElementById("sheetofstyles").href = "browserOutput_white.css"; - opts.darkmode = false; - runByond('?_src_=chat&proc=swaptolightmode'); - } else { - document.getElementById("sheetofstyles").href = "browserOutput.css"; - opts.darkmode = true; - runByond('?_src_=chat&proc=swaptodarkmode'); - } - setCookie('darkmode', (opts.darkmode ? 'true' : 'false'), 365); -} -*/ -function handleClientData(ckey, ip, compid) { - //byond sends player info to here - var currentData = {'ckey': ckey, 'ip': ip, 'compid': compid}; - if (opts.clientData && !$.isEmptyObject(opts.clientData)) { - runByond('?_src_=chat&proc=analyzeClientData¶m[cookie]='+JSON.stringify({'connData': opts.clientData})); - - for (var i = 0; i < opts.clientData.length; i++) { - var saved = opts.clientData[i]; - if (currentData.ckey == saved.ckey && currentData.ip == saved.ip && currentData.compid == saved.compid) { - return; //Record already exists - } - } - //Lets make sure we obey our limit (can connect from server with higher limit) - while (opts.clientData.length >= opts.clientDataLimit) { - opts.clientData.shift(); - } - } else { - runByond('?_src_=chat&proc=analyzeClientData¶m[cookie]=none'); - } - - //Update the cookie with current details - opts.clientData.push(currentData); - setCookie('connData', JSON.stringify(opts.clientData), 365); -} - -//Server calls this on ehjax response -//Or, y'know, whenever really -function ehjaxCallback(data) { - opts.lastPang = Date.now(); - if (data == 'softPang') { - return; - } else if (data == 'pang') { - opts.pingCounter = 0; //reset - opts.pingTime = Date.now(); - runByond('?_src_=chat&proc=ping'); - - } else if (data == 'pong') { - if (opts.pingDisabled) {return;} - opts.pongTime = Date.now(); - var pingDuration = Math.ceil((opts.pongTime - opts.pingTime) / 2); - $('#pingMs').text(pingDuration+'ms'); - pingDuration = Math.min(pingDuration, 255); - var red = pingDuration; - var green = 255 - pingDuration; - var blue = 0; - var hex = rgbToHex(red, green, blue); - $('#pingDot').css('color', '#'+hex); - - } else if (data == 'roundrestart') { - opts.restarting = true; - internalOutput('
    The connection has been closed because the server is restarting. Please wait while you automatically reconnect.
    ', 'internal'); - } else if (data == 'stopMusic') { - $('#adminMusic').prop('src', ''); - } else { - //Oh we're actually being sent data instead of an instruction - var dataJ; - try { - dataJ = $.parseJSON(data); - } catch (e) { - //But...incorrect :sadtrombone: - window.onerror('JSON: '+e+'. '+data, 'browserOutput.html', 327); - return; - } - data = dataJ; - - if (data.clientData) { - if (opts.restarting) { - opts.restarting = false; - $('.connectionClosed.restarting:not(.restored)').addClass('restored').text('The round restarted and you successfully reconnected!'); - } - if (!data.clientData.ckey && !data.clientData.ip && !data.clientData.compid) { - //TODO: Call shutdown perhaps - return; - } else { - handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid); - } - sendVolumeUpdate(); - } else if (data.adminMusic) { - if (typeof data.adminMusic === 'string') { - var adminMusic = byondDecode(data.adminMusic); - var bindLoadedData = false; - adminMusic = adminMusic.match(/https?:\/\/\S+/) || ''; - if (data.musicRate) { - var newRate = Number(data.musicRate); - if(newRate) { - $('#adminMusic').prop('defaultPlaybackRate', newRate); - } - } else { - $('#adminMusic').prop('defaultPlaybackRate', 1.0); - } - if (data.musicSeek) { - opts.musicStartAt = Number(data.musicSeek) || 0; - bindLoadedData = true; - } else { - opts.musicStartAt = 0; - } - if (data.musicHalt) { - opts.musicEndAt = Number(data.musicHalt) || null; - bindLoadedData = true; - } - if (bindLoadedData) { - $('#adminMusic').one('loadeddata', adminMusicLoadedData); - } - $('#adminMusic').prop('src', adminMusic); - $('#adminMusic').trigger("play"); - } - } else if (data.syncRegex) { - for (var i in data.syncRegex) { - - var regexData = data.syncRegex[i]; - var regexName = regexData[0]; - var regexFlags = regexData[1]; - var regexReplaced = regexData[2]; - - replaceRegexes[i] = [new RegExp(regexName, regexFlags), regexReplaced]; - } - } - } -} - -function createPopup(contents, width) { - opts.popups++; - $('body').append(''); - - //Attach close popup event - var $popup = $('#popup'+opts.popups); - var height = $popup.outerHeight(); - $popup.css({'height': height+'px', 'margin': '-'+(height/2)+'px 0 0 -'+(width/2)+'px'}); - - $popup.on('click', '.close', function(e) { - e.preventDefault(); - $popup.remove(); - }); -} - -function toggleWasd(state) { - opts.wasd = (state == 'on' ? true : false); -} - -function sendVolumeUpdate() { - opts.volumeUpdating = false; - if(opts.updatedVolume) { - runByond('?_src_=chat&proc=setMusicVolume¶m[volume]='+opts.updatedVolume); - } -} - -function adminMusicEndCheck(event) { - if (opts.musicEndAt) { - if ($('#adminMusic').prop('currentTime') >= opts.musicEndAt) { - $('#adminMusic').off(event); - $('#adminMusic').trigger('pause'); - $('#adminMusic').prop('src', ''); - } - } else { - $('#adminMusic').off(event); - } -} - -function adminMusicLoadedData(event) { - if (opts.musicStartAt && ($('#adminMusic').prop('duration') === Infinity || (opts.musicStartAt <= $('#adminMusic').prop('duration'))) ) { - $('#adminMusic').prop('currentTime', opts.musicStartAt); - } - if (opts.musicEndAt) { - $('#adminMusic').on('timeupdate', adminMusicEndCheck); - } -} - -function subSlideUp() { - $(this).removeClass('scroll'); - $(this).css('height', ''); -} - -function startSubLoop() { - if (opts.selectedSubLoop) { - clearInterval(opts.selectedSubLoop); - } - return setInterval(function() { - if (!opts.suppressSubClose && $selectedSub.is(':visible')) { - $selectedSub.slideUp('fast', subSlideUp); - clearInterval(opts.selectedSubLoop); - } - }, 5000); //every 5 seconds -} - -function handleToggleClick($sub, $toggle) { - if ($selectedSub !== $sub && $selectedSub.is(':visible')) { - $selectedSub.slideUp('fast', subSlideUp); - } - $selectedSub = $sub - if ($selectedSub.is(':visible')) { - $selectedSub.slideUp('fast', subSlideUp); - clearInterval(opts.selectedSubLoop); - } else { - $selectedSub.slideDown('fast', function() { - var windowHeight = $(window).height(); - var toggleHeight = $toggle.outerHeight(); - var priorSubHeight = $selectedSub.outerHeight(); - var newSubHeight = windowHeight - toggleHeight; - $(this).height(newSubHeight); - if (priorSubHeight > (windowHeight - toggleHeight)) { - $(this).addClass('scroll'); - } - }); - opts.selectedSubLoop = startSubLoop(); - } -} - -/***************************************** -* -* DOM READY -* -******************************************/ - -if (typeof $ === 'undefined') { - var div = document.getElementById('loading').childNodes[1]; - div += '

    ERROR: Jquery did not load.'; -} - -$(function() { - $messages = $('#messages'); - $subOptions = $('#subOptions'); - $subAudio = $('#subAudio'); - $selectedSub = $subOptions; - - //Hey look it's a controller loop! - setInterval(function() { - if (opts.lastPang + opts.pangLimit < Date.now() && !opts.restarting) { //Every pingLimit - if (!opts.noResponse) { //Only actually append a message if the previous ping didn't also fail (to prevent spam) - opts.noResponse = true; - opts.noResponseCount++; - internalOutput('
    You are either AFK, experiencing lag or the connection has closed.
    ', 'internal'); - } - } else if (opts.noResponse) { //Previous ping attempt failed ohno - $('.connectionClosed[data-count="'+opts.noResponseCount+'"]:not(.restored)').addClass('restored').text('Your connection has been restored (probably)!'); - opts.noResponse = false; - } - }, 2000); //2 seconds - - - /***************************************** - * - * LOAD SAVED CONFIG - * - ******************************************/ - var savedConfig = { - fontsize: getCookie('fontsize'), //no need for compatabiliy, cookie name is the same - lineheight: getCookie('lineheight'), - 'spingDisabled': getCookie('pingdisabled'), - 'shighlightTerms': getCookie('highlightterms'), - 'shighlightColor': getCookie('highlightcolor'), - 'smusicVolume': getCookie('musicVolume'), - 'smessagecombining': getCookie('messagecombining'), - 'sdarkmode': getCookie('darkmode'), - 'scolorPreset': getCookie('colorpreset'), - }; - - if (savedConfig.fontsize) { - $messages.css('font-size', savedConfig.fontsize); - internalOutput('Loaded font size setting of: '+savedConfig.fontsize+'', 'internal'); - } - if (savedConfig.lineheight) { - $("body").css('line-height', savedConfig.lineheight); - internalOutput('Loaded line height setting of: '+savedConfig.lineheight+'', 'internal'); - } - // if(savedConfig.sdarkmode == 'true'){ - // swap(); - // } - if (savedConfig.scolorPreset) { - opts.colorPreset = Number(savedConfig.scolorPreset); - updateColorPreset(); - internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal'); - } - if (savedConfig.spingDisabled) { - if (savedConfig.spingDisabled == 'true') { - opts.pingDisabled = true; - $('#ping').hide(); - } - internalOutput('Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'', 'internal'); - } - if (savedConfig.shighlightTerms) { - var savedTerms = $.parseJSON(savedConfig.shighlightTerms).filter(function (entry) { - return entry !== null && /\S/.test(entry); - }); - var actualTerms = savedTerms.length != 0 ? savedTerms.join(', ') : null; - if (actualTerms) { - internalOutput('Loaded highlight strings of: ' + actualTerms+'', 'internal'); - opts.highlightTerms = savedTerms; - } - } - if (savedConfig.shighlightColor) { - opts.highlightColor = savedConfig.shighlightColor; - internalOutput('Loaded highlight color of: '+savedConfig.shighlightColor+'', 'internal'); - } - if (savedConfig.smusicVolume) { - var newVolume = clamp(savedConfig.smusicVolume, 0, 100); - $('#adminMusic').prop('volume', newVolume / 100); - $('#musicVolume').val(newVolume); - opts.updatedVolume = newVolume; - sendVolumeUpdate(); - internalOutput('Loaded music volume of: '+savedConfig.smusicVolume+'', 'internal'); - } - else{ - $('#adminMusic').prop('volume', opts.defaultMusicVolume / 100); - } - - if (savedConfig.smessagecombining) { - if (savedConfig.smessagecombining == 'false') { - opts.messageCombining = false; - } else { - opts.messageCombining = true; - } - } - (function() { - var dataCookie = getCookie('connData'); - if (dataCookie) { - var dataJ; - try { - dataJ = $.parseJSON(dataCookie); - } catch (e) { - window.onerror('JSON '+e+'. '+dataCookie, 'browserOutput.html', 434); - return; - } - opts.clientData = dataJ; - } - })(); - - - /***************************************** - * - * BASE CHAT OUTPUT EVENTS - * - ******************************************/ - - $('body').on('click', 'a', function(e) { - e.preventDefault(); - }); - - $('body').on('mousedown', function(e) { - var $target = $(e.target); - - if ($contextMenu && opts.hasOwnProperty('contextMenuTarget') && opts.contextMenuTarget) { - hideContextMenu(); - return false; - } - - if ($target.is('a') || $target.parent('a').length || $target.is('input') || $target.is('textarea')) { - opts.preventFocus = true; - } else { - opts.preventFocus = false; - opts.mouseDownX = e.pageX; - opts.mouseDownY = e.pageY; - } - }); - - $messages.on('mousedown', function(e) { - if ($selectedSub && $selectedSub.is(':visible')) { - $selectedSub.slideUp('fast', subSlideUp); - clearInterval(opts.selectedSubLoop); - } - }); - - $('body').on('mouseup', function(e) { - if (!opts.preventFocus && - (e.pageX >= opts.mouseDownX - opts.clickTolerance && e.pageX <= opts.mouseDownX + opts.clickTolerance) && - (e.pageY >= opts.mouseDownY - opts.clickTolerance && e.pageY <= opts.mouseDownY + opts.clickTolerance) - ) { - opts.mouseDownX = null; - opts.mouseDownY = null; - runByond('byond://winset?mapwindow.map.focus=true'); - } - }); - - $messages.on('click', 'a', function(e) { - var href = $(this).attr('href'); - $(this).addClass('visited'); - if (href[0] == '?' || (href.length >= 8 && href.substring(0,8) == 'byond://')) { - runByond(href); - } else { - href = escaper(href); - runByond('?action=openLink&link='+href); - } - runByond('byond://winset?mapwindow.map.focus=true'); - }); - - $('body').on('keydown', function(e) { - if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') { - return; - } - if (e.ctrlKey || e.altKey || e.shiftKey) { //Band-aid "fix" for allowing ctrl+c copy paste etc. Needs a proper fix. - return; - } - runByond('byond://winset?mapwindow.map.focus=true'); - }); - - //Mildly hacky fix for scroll issues on mob change (interface gets resized sometimes, messing up snap-scroll) - $(window).on('resize', function(e) { - if ($(this).height() !== opts.priorChatHeight) { - $('body,html').scrollTop($messages.outerHeight()); - opts.priorChatHeight = $(this).height(); - } - }); - - - /***************************************** - * - * OPTIONS INTERFACE EVENTS - * - ******************************************/ - - $('body').on('click', '#newMessages', function(e) { - var messagesHeight = $messages.outerHeight(); - $('body,html').scrollTop(messagesHeight); - $('#newMessages').remove(); - runByond('byond://winset?mapwindow.map.focus=true'); - }); - - $('#toggleOptions').click(function(e) { - handleToggleClick($subOptions, $(this)); - }); - // $('#darkmodetoggle').click(function(e) { - // swap(); - // }); - $('#toggleAudio').click(function(e) { - handleToggleClick($subAudio, $(this)); - }); - - $('.sub, .toggle').mouseenter(function() { - opts.suppressSubClose = true; - }); - - $('.sub, .toggle').mouseleave(function() { - opts.suppressSubClose = false; - }); - - $('#decreaseFont').click(function(e) { - savedConfig.fontsize = Math.max(parseInt(savedConfig.fontsize || 13) - 1, 1) + 'px'; - $messages.css({'font-size': savedConfig.fontsize}); - setCookie('fontsize', savedConfig.fontsize, 365); - internalOutput('Font size set to '+savedConfig.fontsize+'', 'internal'); - }); - - $('#increaseFont').click(function(e) { - savedConfig.fontsize = (parseInt(savedConfig.fontsize || 13) + 1) + 'px'; - $messages.css({'font-size': savedConfig.fontsize}); - setCookie('fontsize', savedConfig.fontsize, 365); - internalOutput('Font size set to '+savedConfig.fontsize+'', 'internal'); - }); - - $('#decreaseLineHeight').click(function(e) { - savedConfig.lineheight = Math.max(parseFloat(savedConfig.lineheight || 1.2) - 0.1, 0.1).toFixed(1); - $("body").css({'line-height': savedConfig.lineheight}); - setCookie('lineheight', savedConfig.lineheight, 365); - internalOutput('Line height set to '+savedConfig.lineheight+'', 'internal'); - }); - - $('#increaseLineHeight').click(function(e) { - savedConfig.lineheight = (parseFloat(savedConfig.lineheight || 1.2) + 0.1).toFixed(1); - $("body").css({'line-height': savedConfig.lineheight}); - setCookie('lineheight', savedConfig.lineheight, 365); - internalOutput('Line height set to '+savedConfig.lineheight+'', 'internal'); - }); - - $('#togglePing').click(function(e) { - if (opts.pingDisabled) { - $('#ping').slideDown('fast'); - opts.pingDisabled = false; - } else { - $('#ping').slideUp('fast'); - opts.pingDisabled = true; - } - setCookie('pingdisabled', (opts.pingDisabled ? 'true' : 'false'), 365); - }); - - $('#saveLog').click(function(e) { - // Requires IE 10+ to issue download commands. Just opening a popup - // window will cause Ctrl+S to save a blank page, ignoring innerHTML. - if (!window.Blob) { - output('This function is only supported on IE 10 and up. Upgrade if possible.', 'internal'); - return; - } - - $.ajax({ - type: 'GET', - url: 'browserOutput.css', // browserOutput_white.css - success: function(styleData) { - var blob = new Blob(['Chat Log', $messages.html(), '']); - - var fname = 'SS13 Chat Log'; - var date = new Date(), month = date.getMonth(), day = date.getDay(), hours = date.getHours(), mins = date.getMinutes(), secs = date.getSeconds(); - fname += ' ' + date.getFullYear() + '-' + (month < 10 ? '0' : '') + month + '-' + (day < 10 ? '0' : '') + day; - fname += ' ' + (hours < 10 ? '0' : '') + hours + (mins < 10 ? '0' : '') + mins + (secs < 10 ? '0' : '') + secs; - fname += '.html'; - - window.navigator.msSaveBlob(blob, fname); - } - }); - }); - - $('#highlightTerm').click(function(e) { - if ($('.popup .highlightTerm').is(':visible')) {return;} - var termInputs = ''; - for (var i = 0; i < opts.highlightLimit; i++) { - termInputs += '
    '; - } - var popupContent = '
    String Highlighting
    ' + - '
    ' + - '
    Choose up to '+opts.highlightLimit+' strings that will highlight the line when they appear in chat.
    ' + - '
    ' + - termInputs + - '
    ' + - '
    ' + - '
    ' + - '
    '; - createPopup(popupContent, 250); - }); - - $('body').on('keyup', '#highlightColor', function() { - var color = $('#highlightColor').val(); - color = color.trim(); - if (!color || color.charAt(0) != '#') return; - $('#highlightColor').css('background-color', color); - }); - - $('body').on('submit', '#highlightTermForm', function(e) { - e.preventDefault(); - - opts.highlightTerms = []; - for (var count = 0; count < opts.highlightLimit; count++) { - var term = $('#highlightTermInput'+count).val(); - if (term !== null && /\S/.test(term)) { - opts.highlightTerms.push(term.trim().toLowerCase()); - } - } - - var color = $('#highlightColor').val(); - color = color.trim(); - if (color == '' || color.charAt(0) != '#') { - opts.highlightColor = '#FFFF00'; - } else { - opts.highlightColor = color; - } - var $popup = $('#highlightPopup').closest('.popup'); - $popup.remove(); - - setCookie('highlightterms', JSON.stringify(opts.highlightTerms), 365); - setCookie('highlightcolor', opts.highlightColor, 365); - }); - - $('#clearMessages').click(function() { - $messages.empty(); - opts.messageCount = 0; - }); - - $('#changeColorPreset').click(function() { //CIT SPECIFIC - opts.colorPreset = (opts.colorPreset+1) % colorPresets.length; - updateColorPreset(); - setCookie('colorpreset', opts.colorPreset, 365); - internalOutput('Changed color preset to: '+colorPresets[opts.colorPreset]); - }); - - $('#musicVolumeSpan').hover(function() { - $('#musicVolumeText').addClass('hidden'); - $('#musicVolume').removeClass('hidden'); - }, function() { - $('#musicVolume').addClass('hidden'); - $('#musicVolumeText').removeClass('hidden'); - }); - - $('#musicVolume').change(function() { - var newVolume = $('#musicVolume').val(); - newVolume = clamp(newVolume, 0, 100); - $('#adminMusic').prop('volume', newVolume / 100); - setCookie('musicVolume', newVolume, 365); - opts.updatedVolume = newVolume; - if(!opts.volumeUpdating) { - setTimeout(sendVolumeUpdate, opts.volumeUpdateDelay); - opts.volumeUpdating = true; - } - }); - - $('#toggleCombine').click(function(e) { - opts.messageCombining = !opts.messageCombining; - setCookie('messagecombining', (opts.messageCombining ? 'true' : 'false'), 365); - }); - - $('img.icon').error(iconError); - - - - - /***************************************** - * - * KICK EVERYTHING OFF - * - ******************************************/ - - runByond('?_src_=chat&proc=doneLoading'); - if ($('#loading').is(':visible')) { - $('#loading').remove(); - } - $('#userBar').show(); - opts.priorChatHeight = $(window).height(); -}); diff --git a/code/modules/goonchat/browserassets/js/json2.min.js b/code/modules/goonchat/browserassets/js/json2.min.js deleted file mode 100644 index d867407f26..0000000000 --- a/code/modules/goonchat/browserassets/js/json2.min.js +++ /dev/null @@ -1 +0,0 @@ -"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return 10>t?"0"+t:t}function this_value(){return this.valueOf()}function quote(t){return rx_escapable.lastIndex=0,rx_escapable.test(t)?'"'+t.replace(rx_escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var r,n,o,u,f,a=gap,i=e[t];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(t)),"function"==typeof rep&&(i=rep.call(e,t,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,f=[],"[object Array]"===Object.prototype.toString.apply(i)){for(u=i.length,r=0;u>r;r+=1)f[r]=str(r,i)||"null";return o=0===f.length?"[]":gap?"[\n"+gap+f.join(",\n"+gap)+"\n"+a+"]":"["+f.join(",")+"]",gap=a,o}if(rep&&"object"==typeof rep)for(u=rep.length,r=0;u>r;r+=1)"string"==typeof rep[r]&&(n=rep[r],o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));else for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));return o=0===f.length?"{}":gap?"{\n"+gap+f.join(",\n"+gap)+"\n"+a+"}":"{"+f.join(",")+"}",gap=a,o}}var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,r){var n;if(gap="",indent="","number"==typeof r)for(n=0;r>n;n+=1)indent+=" ";else"string"==typeof r&&(indent=r);if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(t,e){var r,n,o=t[e];if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(n=walk(o,r),void 0!==n?o[r]=n:delete o[r]);return reviver.call(t,e,o)}var j;if(text=String(text),rx_dangerous.lastIndex=0,rx_dangerous.test(text)&&(text=text.replace(rx_dangerous,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),rx_one.test(text.replace(rx_two,"@").replace(rx_three,"]").replace(rx_four,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(); \ No newline at end of file diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 4561e0ae3e..573b04a296 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -334,8 +334,7 @@ to_chat(C, " You feel an overwhelming desire to [message]") if(2) visible_message("[src] waves their arms around, \"If only you had a better upbringing, your ears are now full of my singing!\"") - var/client/C2 = C.client - C2.chatOutput.sendMusic("https://puu.sh/ExBbv.mp4", 1)//I hope this works! + C.client.tgui_panel?.play_music("https://puu.sh/ExBbv.mp4") if(3) visible_message("[src] waves their arms around, \"You're cute little bumpkin, On your head is a pumpkin!\"") if(C.head) diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm index e84025208a..b8480a1901 100644 --- a/code/modules/hydroponics/grown/ambrosia.dm +++ b/code/modules/hydroponics/grown/ambrosia.dm @@ -49,6 +49,7 @@ seed = /obj/item/seeds/ambrosia/deus name = "ambrosia deus branch" desc = "Eating this makes you feel immortal!" + foodtype = VEGETABLES | ANTITOXIC icon_state = "ambrosiadeus" filling_color = "#008B8B" wine_power = 50 diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm index 6525ac42d4..e4fe7fcdbc 100644 --- a/code/modules/hydroponics/grown/cannabis.dm +++ b/code/modules/hydroponics/grown/cannabis.dm @@ -104,6 +104,7 @@ seed = /obj/item/seeds/cannabis/death name = "death cannabis leaf" desc = "Looks a bit dark. Oh well." + foodtype = VEGETABLES | TOXIC icon_state = "blackcannabis" wine_power = 40 @@ -111,6 +112,7 @@ seed = /obj/item/seeds/cannabis/white name = "white cannabis leaf" desc = "It feels smooth and nice to the touch." + foodtype = VEGETABLES | ANTITOXIC icon_state = "whitecannabis" wine_power = 10 diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm index d130d50aa5..e199c2c6b1 100644 --- a/code/modules/hydroponics/grown/citrus.dm +++ b/code/modules/hydroponics/grown/citrus.dm @@ -29,6 +29,7 @@ seed = /obj/item/seeds/lime name = "lime" desc = "It's so sour, your face will twist." + foodtype = FRUIT | ANTITOXIC icon_state = "lime" filling_color = "#00FF00" juice_results = list(/datum/reagent/consumable/limejuice = 0) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm index 8c5171667a..e385eed142 100644 --- a/code/modules/instruments/songs/editor.dm +++ b/code/modules/instruments/songs/editor.dm @@ -82,7 +82,6 @@ var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500) popup.set_content(dat.Join("")) - popup.set_title_image(user.browse_rsc_icon(parent.icon, parent.icon_state)) popup.open() /datum/song/proc/ParseSong(text) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 1238b37919..0feceaf1a8 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -80,6 +80,9 @@ if(mind_traits) for(var/t in mind_traits) ADD_TRAIT(H.mind, t, JOB_TRAIT) + if(/datum/quirk/paraplegic in blacklisted_quirks) + H.regenerate_limbs() //if you can't be a paraplegic, attempt to regenerate limbs to stop amputated limb selection + H.set_resting(FALSE, TRUE) //they probably shouldn't be on the floor because they had no legs then suddenly had legs /datum/job/proc/announce(mob/living/carbon/human/H) if(head_announce) diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index 536bf06e8d..42b439ba03 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -35,7 +35,7 @@ return TRUE /datum/language/proc/get_icon() - var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat) + var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) return sheet.icon_tag("language-[icon_state]") /datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2) diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 80ce2522ff..a4d88158e2 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -22,7 +22,7 @@ max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) var/state = 0 - var/list/allowed_books = list(/obj/item/book, /obj/item/spellbook, /obj/item/storage/book) //Things allowed in the bookcase + var/list/allowed_books = list(/obj/item/book, /obj/item/spellbook, /obj/item/storage/book, /obj/item/gun/magic/wand/book) //Things allowed in the bookcase /obj/structure/bookcase/examine(mob/user) . = ..() @@ -192,7 +192,7 @@ desc = "Crack it open, inhale the musk of its pages, and learn something new." throw_speed = 1 throw_range = 5 - w_class = WEIGHT_CLASS_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) + w_class = WEIGHT_CLASS_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) attack_verb = list("bashed", "whacked", "educated") resistance_flags = FLAMMABLE var/dat //Actual page content diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index f777246453..3953f5e28c 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -66,7 +66,6 @@ dat += "\[Go Back\]
    " var/datum/browser/popup = new(user, "publiclibrary", name, 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/libraryconsole/Topic(href, href_list) @@ -314,7 +313,6 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums var/datum/browser/popup = new(user, "library", name, 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/libraryconsole/bookmanagement/proc/findscanner(viewrange) @@ -537,7 +535,6 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums dat += "
    " var/datum/browser/popup = new(user, "scanner", name, 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/libraryscanner/Topic(href, href_list) diff --git a/code/modules/mapping/minimaps.dm b/code/modules/mapping/minimaps.dm index 7a62e9ab44..e0eb174cb3 100644 --- a/code/modules/mapping/minimaps.dm +++ b/code/modules/mapping/minimaps.dm @@ -4,7 +4,7 @@ // The map icons var/icon/map_icon var/icon/meta_icon - + var/list/color_area_names = list() var/minx @@ -33,7 +33,7 @@ meta_icon = new('html/blank.png') map_icon.Scale(x2 - x1 + 1, y2 - y1 + 1) // arrays start at 1 meta_icon.Scale(x2 - x1 + 1, y2 - y1 + 1) - + var/list/area_to_color = list() for(var/turf/T in block(locate(x1, y1, z_level), locate(x2, y2, z_level))) var/area/A = T.loc @@ -44,7 +44,7 @@ crop_x2 = max(crop_x2, T.x) crop_y1 = min(crop_y1, T.y) crop_y2 = max(crop_y2, T.y) - + var/meta_color = area_to_color[A] if(!meta_color) meta_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens @@ -73,13 +73,15 @@ overlay_icon = new(map_icon) overlay_icon.Scale(16, 16) //we're done baking, now we ship it. - register_asset("minimap-[id].png", map_icon) - register_asset("minimap-[id]-meta.png", meta_icon) + if (!SSassets.cache["minimap-[id].png"]) + SSassets.transport.register_asset("minimap-[id].png", map_icon) + if (!SSassets.cache["minimap-[id]-meta.png"]) + SSassets.transport.register_asset("minimap-[id]-meta.png", meta_icon) /datum/minimap/proc/send(mob/user) if(!id) CRASH("ERROR: send called, but the minimap id is null/missing. ID: [id]") - send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon)) + SSassets.transport.send_assets(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon)) /datum/minimap_group var/list/minimaps = list() @@ -100,15 +102,17 @@ var/list/datas = list() var/list/info = list() - + for(var/i in 1 to length(minimaps))// OLD: for(var/i in 1 to length(minimaps)) var/datum/minimap/M = minimaps[i] + var/map_name = "minimap-[M.id].png" + var/meta_name = "minimap-[M.id]-meta.png" M.send(user) info += {"
    - - + +
    @@ -183,6 +187,4 @@ var/datum/browser/popup = new(user, "minimap_[id]", name, 500, 700) popup.add_head_content(headerJS) //set the head popup.set_content(info) - var/datum/minimap/MICO = minimaps[1] - popup.set_title_image(MICO.overlay_icon) popup.open(FALSE) diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm index 006065d048..b10177ebaf 100644 --- a/code/modules/mining/aux_base.dm +++ b/code/modules/mining/aux_base.dm @@ -70,7 +70,6 @@ interface with the mining shuttle at the landing site if a mobile beacon is also var/datum/browser/popup = new(user, "computer", "base management", 550, 300) //width, height popup.set_content("
    [dat]
    ") - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) popup.open() diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm index 9ccb7c0efc..b2cd840468 100644 --- a/code/modules/mining/equipment/mineral_scanner.dm +++ b/code/modules/mining/equipment/mineral_scanner.dm @@ -12,13 +12,14 @@ slot_flags = ITEM_SLOT_BELT var/cooldown = 35 var/current_cooldown = 0 + var/range = 7 /obj/item/mining_scanner/attack_self(mob/user) if(!user.client) return if(current_cooldown <= world.time) current_cooldown = world.time + cooldown - mineral_scan_pulse(get_turf(user)) + mineral_scan_pulse(get_turf(user), range) //Debug item to identify all ore spread quickly /obj/item/mining_scanner/admin diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 27259ce812..31ee37c3b0 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -66,6 +66,16 @@ force = 19 custom_materials = list(/datum/material/diamond=4000) +/obj/item/pickaxe/rosegold + name = "rose gold pickaxe" + icon_state = "rgpickaxe" + item_state = "rgpickaxe" + toolspeed = 0.1 + desc = "A pickaxe with a light rose gold head and some red glowing runes. Extremely robust at cracking rock walls and digging up dirt." + force = 19 + custom_materials = list(/datum/material/gold=4000) + digrange = 3 + /obj/item/pickaxe/plasteel name = "plasteel-tipped pickaxe" icon_state = "titaxe" diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index c17b62ba6c..e9f8079400 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -18,6 +18,15 @@ SSblackbox.record_feedback("tally", "jaunter", 1, "User") // user activated activate(user, TRUE) +/obj/item/wormhole_jaunter/equipped(mob/user, slot) + . = ..() + if(slot == SLOT_BELT) + RegisterSignal(user, COMSIG_MOVABLE_CHASM_DROP, .proc/chasm_react) + +/obj/item/wormhole_jaunter/dropped(mob/user) + . = ..() + UnregisterSignal(user, COMSIG_MOVABLE_CHASM_DROP) + /obj/item/wormhole_jaunter/proc/turf_check(mob/user) var/turf/device_turf = get_turf(user) if(!device_turf || is_centcom_level(device_turf.z) || is_reserved_level(device_turf.z)) @@ -71,13 +80,14 @@ SSblackbox.record_feedback("tally", "jaunter", 1, "EMP") // EMP accidental activation activate(M) -/obj/item/wormhole_jaunter/proc/chasm_react(mob/user) - if(user.get_item_by_slot(SLOT_BELT) == src) - to_chat(user, "Your [name] activates, saving you from the chasm!
    ") - SSblackbox.record_feedback("tally", "jaunter", 1, "Chasm") // chasm automatic activation - activate(user, FALSE, TRUE) - else - to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.
    ") +/obj/item/wormhole_jaunter/proc/chasm_react(mob/source, datum/component/chasm/C) + to_chat(source, "Your [name] activates, saving you from the chasm!
    ") + SSblackbox.record_feedback("tally", "jaunter", 1, "Chasm") // chasm automatic activation + activate(source, FALSE, TRUE) + if(C) + var/atom/A = C.parent + A.visible_message("[source] falls into [A]!") + return TRUE //jaunter tunnel /obj/effect/portal/jaunt_tunnel diff --git a/code/modules/mining/laborcamp/laborshuttle.dm b/code/modules/mining/laborcamp/laborshuttle.dm index dbe607f42f..2923e8447e 100644 --- a/code/modules/mining/laborcamp/laborshuttle.dm +++ b/code/modules/mining/laborcamp/laborshuttle.dm @@ -6,7 +6,6 @@ possible_destinations = "laborcamp_home;laborcamp_away" req_access = list(ACCESS_BRIG) - /obj/machinery/computer/shuttle/labor/one_way name = "prisoner shuttle console" desc = "A one-way shuttle console, used to summon the shuttle to the labor camp." @@ -14,14 +13,19 @@ circuit = /obj/item/circuitboard/computer/labor_shuttle/one_way req_access = list( ) -/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list) - if(href_list["move"]) - var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp") - if(!M) - to_chat(usr, "Cannot locate shuttle!") - return 0 - var/obj/docking_port/stationary/S = M.get_docked() - if(S && S.name == "laborcamp_away") - to_chat(usr, "Shuttle is already at the outpost!") - return 0 - ..() \ No newline at end of file +/obj/machinery/computer/shuttle/labor/one_way/ui_act(action, params) + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return + + switch(action) + if("move") + var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp") + if(!M) + to_chat(usr, "Cannot locate shuttle!") + return + var/obj/docking_port/stationary/S = M.get_docked() + if(S?.name == "laborcamp_away") + to_chat(usr, "Shuttle is already at the outpost!") + return + return ..() diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index e03de83e02..a967fea75a 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -7,81 +7,199 @@ icon_state = "necrocrate" resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF +/obj/structure/closet/crate/necropolis/tendril/random + name = "necropolis crate" + desc = "A chest for a chest, a head for a head." + +/obj/structure/closet/crate/necropolis/tendril/random/PopulateContents() + var/loot = rand(1,3) + switch(loot) + if(1) + new /obj/structure/closet/crate/necropolis/tendril/magic(src) + if(2) + new /obj/structure/closet/crate/necropolis/tendril/weapon_armor(src) + if(3) + new /obj/structure/closet/crate/necropolis/tendril/misc(src) + /obj/structure/closet/crate/necropolis/tendril desc = "It's watching you suspiciously." -/obj/structure/closet/crate/necropolis/tendril/PopulateContents() +/obj/structure/closet/crate/necropolis/tendril/magic + name = "relic necropolis chest" + +/obj/structure/closet/crate/necropolis/tendril/weapon_armor + name = "armament necropolis chest" + +/obj/structure/closet/crate/necropolis/tendril/misc + +/obj/structure/closet/crate/necropolis/tendril/all + desc = "It's watching you suspiciously." + +/obj/structure/closet/crate/necropolis/tendril/magic/PopulateContents() + var/loot = rand(1,10) + switch(loot) + if(1) + new /obj/item/soulstone/anybody(src) + if(2) + new /obj/item/rod_of_asclepius(src) + if(3) + new /obj/item/organ/heart/cursed/wizard(src) + if(4) + new /obj/item/book/granter/spell/summonitem(src) + if(5) + new /obj/item/borg/upgrade/modkit/lifesteal(src) + new /obj/item/bedsheet/cult(src) + if(6) + new /obj/item/clothing/neck/necklace/memento_mori(src) + if(7) + new /obj/item/warp_cube/red(src) + if(8) + new /obj/item/immortality_talisman(src) + if(9) + new /obj/item/gun/magic/wand/book/healing(src) + if(10) + new /obj/item/reagent_containers/glass/bottle/ichor/red(src) + new /obj/item/reagent_containers/glass/bottle/ichor/blue(src) + new /obj/item/reagent_containers/glass/bottle/ichor/green(src) + +/obj/structure/closet/crate/necropolis/tendril/weapon_armor/PopulateContents() + var/loot = rand(1,11) + switch(loot) + if(1) + new /obj/item/clothing/suit/space/hardsuit/cult(src) + if(2) + new /obj/item/katana/lavaland(src) + if(3) + if(prob(50)) + new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src) + else + new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src) + if(4) + new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src) + if(5) + new /obj/item/nullrod/scythe/talking(src) + if(6) + new /obj/item/nullrod/armblade(src) + if(7) + new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src) + new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old(src) + if(8) + new /obj/item/grenade/clusterbuster/inferno(src) + if(9) + new /obj/item/gun/magic/wand/book/shock(src) + if(10) + new /obj/item/gun/magic/wand/book/page(src) + if(11) + new /obj/item/gun/magic/wand/book/spark(src) + +/obj/structure/closet/crate/necropolis/tendril/misc/PopulateContents() + var/loot = rand(1,14) + switch(loot) + if(1) + new /obj/item/shared_storage/red(src) + if(2) + new /obj/item/reagent_containers/glass/bottle/potion/flight(src) + if(3) + new /obj/item/ship_in_a_bottle(src) + if(4) + new /obj/item/voodoo(src) + if(5) + new /obj/item/book_of_babel(src) + if(6) + new /obj/item/jacobs_ladder(src) + if(7) + if(prob(50)) + new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src) + else + new /obj/item/disk/design_disk/modkit_disc/bounty(src) + if(8) + new /obj/item/wisp_lantern(src) + if(9) + new /obj/item/pickaxe/rosegold(src) + if(10) + new /obj/item/bedsheet/cosmos(src) + new /obj/item/melee/skateboard/hoverboard(src) + if(11) + new /obj/item/disk/tech_disk/illegal(src) + if(12) + new /obj/item/clothing/suit/space/hardsuit/cult(src) + if(13) + new /obj/item/katana/lavaland(src) + if(14) + if(prob(50)) + new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src) + else + new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src) + +/obj/structure/closet/crate/necropolis/tendril/all/PopulateContents() var/loot = rand(1,29) switch(loot) if(1) new /obj/item/shared_storage/red(src) if(2) - new /obj/item/clothing/suit/space/hardsuit/cult(src) - if(3) - new /obj/item/soulstone/anybody(src) - if(4) - new /obj/item/katana/cursed(src) - if(5) - new /obj/item/clothing/glasses/godeye(src) - if(6) new /obj/item/reagent_containers/glass/bottle/potion/flight(src) - if(7) - new /obj/item/pickaxe/diamond(src) - if(8) - if(prob(50)) - new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src) - else - new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src) - if(9) - new /obj/item/rod_of_asclepius(src) - if(10) - new /obj/item/organ/heart/cursed/wizard(src) - if(11) + if(3) new /obj/item/ship_in_a_bottle(src) - if(12) - new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src) - if(13) + if(4) + new /obj/item/voodoo(src) + if(5) + new /obj/item/book_of_babel(src) + if(6) new /obj/item/jacobs_ladder(src) - if(14) - new /obj/item/nullrod/scythe/talking(src) - if(15) - new /obj/item/nullrod/armblade(src) - if(16) - new /obj/item/guardiancreator(src) - if(17) + if(7) if(prob(50)) new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src) else new /obj/item/disk/design_disk/modkit_disc/bounty(src) - if(18) - new /obj/item/warp_cube/red(src) - if(19) + if(8) new /obj/item/wisp_lantern(src) - if(20) - new /obj/item/immortality_talisman(src) - if(21) - new /obj/item/gun/magic/hook(src) - if(22) - new /obj/item/voodoo(src) - if(23) - new /obj/item/grenade/clusterbuster/inferno(src) - if(24) + if(9) + new /obj/item/pickaxe/rosegold(src) + if(10) + new /obj/item/bedsheet/cosmos(src) + new /obj/item/melee/skateboard/hoverboard(src) + if(11) + new /obj/item/disk/tech_disk/illegal(src) + if(12) + new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src) + if(13) + new /obj/item/nullrod/scythe/talking(src) + if(14) + new /obj/item/nullrod/armblade(src) + if(15) new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src) new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old(src) - if(25) + if(16) + new /obj/item/grenade/clusterbuster/inferno(src) + if(17) + new /obj/item/gun/magic/wand/book/shock(src) + if(18) + new /obj/item/gun/magic/wand/book/page(src) + if(19) + new /obj/item/gun/magic/wand/book/spark(src) + if(20) + new /obj/item/soulstone/anybody(src) + if(21) + new /obj/item/rod_of_asclepius(src) + if(22) + new /obj/item/organ/heart/cursed/wizard(src) + if(23) new /obj/item/book/granter/spell/summonitem(src) - if(26) - new /obj/item/book_of_babel(src) - if(27) + if(24) new /obj/item/borg/upgrade/modkit/lifesteal(src) new /obj/item/bedsheet/cult(src) - if(28) + if(25) new /obj/item/clothing/neck/necklace/memento_mori(src) + if(26) + new /obj/item/warp_cube/red(src) + if(27) + new /obj/item/immortality_talisman(src) + if(28) + new /obj/item/gun/magic/wand/book/healing(src) if(29) - if(prob(50)) - new /obj/item/malf_upgrade(src) - else - new /obj/item/disk/tech_disk/illegal(src) + new /obj/item/reagent_containers/glass/bottle/ichor/red(src) + new /obj/item/reagent_containers/glass/bottle/ichor/blue(src) + new /obj/item/reagent_containers/glass/bottle/ichor/green(src) //KA modkit design discs /obj/item/disk/design_disk/modkit_disc @@ -747,7 +865,7 @@ new /obj/item/lava_staff(src) if(3) new /obj/item/book/granter/spell/sacredflame(src) - new /obj/item/gun/magic/wand/fireball(src) + new /obj/item/gun/magic/hook(src) if(4) new /obj/item/dragons_blood(src) @@ -868,7 +986,8 @@ if(1) to_chat(user, "Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.") H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade") - H.eye_color = "fee5a3" + H.left_eye_color = "fee5a3" + H.right_eye_color = "fee5a3" H.set_species(/datum/species/lizard) if(2) to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.") @@ -986,7 +1105,7 @@ if(2) new /obj/item/gun/ballistic/revolver/doublebarrel/super(src) if(3) - new /obj/item/gun/magic/staff/spellblade(src) + new /obj/item/guardiancreator(src) /obj/structure/closet/crate/necropolis/bubblegum/crusher name = "bloody bubblegum chest" @@ -1075,6 +1194,7 @@ var/random_crystal = pick(choices) new random_crystal(src) new /obj/item/organ/vocal_cords/colossus(src) + new /obj/item/clothing/glasses/godeye(src) /obj/structure/closet/crate/necropolis/colossus/crusher name = "angelic colossus chest" diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 143aba3fe4..cae9f5b742 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -76,7 +76,7 @@ circuit = /obj/item/circuitboard/computer/mining_shuttle shuttleId = "mining" possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public" - no_destination_swap = 1 + no_destination_swap = TRUE var/static/list/dumb_rev_heads = list() /obj/machinery/computer/shuttle/mining/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index bd3a3d304a..87f9d716bd 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -17,7 +17,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) prepare_huds() if(length(CONFIG_GET(keyed_list/cross_server))) - verbs += /mob/dead/proc/server_hop + add_verb(src, /mob/dead/proc/server_hop) set_focus(src) return INITIALIZE_HINT_NORMAL @@ -42,27 +42,25 @@ INITIALIZE_IMMEDIATE(/mob/dead) loc = destination Moved(oldloc, NONE, TRUE) -/mob/dead/Stat() - ..() - - if(!statpanel("Status")) - return - //stat(null, "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]") +/mob/dead/get_status_tab_items() + . = ..() + . += "" + //. += "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]" if(SSticker.HasRoundStarted()) return var/time_remaining = SSticker.GetTimeLeft() if(time_remaining > 0) - stat(null, "Time To Start: [round(time_remaining/10)]s") + . += "Time To Start: [round(time_remaining/10)]s" else if(time_remaining == -10) - stat(null, "Time To Start: DELAYED") + . += "Time To Start: DELAYED" else - stat(null, "Time To Start: SOON") + . += "Time To Start: SOON" - stat(null, "Players: [SSticker.totalPlayers]") + . += "Players: [SSticker.totalPlayers]" if(client.holder) - stat(null, "Players Ready: [SSticker.totalPlayersReady]") + . += "Players Ready: [SSticker.totalPlayersReady]" /mob/dead/proc/server_hop() set category = "OOC" @@ -74,7 +72,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) var/pick switch(csa.len) if(0) - verbs -= /mob/dead/proc/server_hop + remove_verb(src, /mob/dead/proc/server_hop) to_chat(src, "Server Hop has been disabled.") if(1) pick = csa[0] diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 768c4c943e..1fdf3102a9 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -295,6 +295,7 @@ if(observer.client && observer.client.prefs) observer.real_name = observer.client.prefs.real_name observer.name = observer.real_name + observer.client.init_verbs() observer.update_icon() observer.stop_sound_channel(CHANNEL_LOBBYMUSIC) QDEL_NULL(mind) @@ -392,7 +393,7 @@ job.standard_assign_skills(character.mind) SSticker.minds += character.mind - + character.client.init_verbs() // init verbs for the late join var/mob/living/carbon/human/humanc if(ishuman(character)) humanc = character //Let's retypecast the var to be human, @@ -414,6 +415,8 @@ give_magic(humanc) if(GLOB.curse_of_madness_triggered) give_madness(humanc, GLOB.curse_of_madness_triggered) + if(humanc.client) + humanc.client.prefs.post_copy_to(humanc) GLOB.joined_player_list += character.ckey GLOB.latejoiners += character @@ -567,7 +570,7 @@ client.prefs.scars_list["[cur_scar_index]"] = valid_scars client.prefs.save_character() - client.prefs.copy_to(H) + client.prefs.copy_to(H, initial_spawn = TRUE) H.dna.update_dna_identity() if(mind) if(transfer_after) @@ -577,7 +580,7 @@ mind.original_character = H H.name = real_name - + client.init_verbs() . = H new_character = . if(transfer_after) diff --git a/code/modules/mob/dead/new_player/poll.dm b/code/modules/mob/dead/new_player/poll.dm index b6d9a3d476..84f5e97a3b 100644 --- a/code/modules/mob/dead/new_player/poll.dm +++ b/code/modules/mob/dead/new_player/poll.dm @@ -229,7 +229,7 @@ src << browse(null ,"window=playerpolllist") src << browse(output,"window=playerpoll;size=500x250") if(POLLTYPE_IRV) - var/datum/asset/irv_assets = get_asset_datum(/datum/asset/group/IRV) + var/datum/asset/irv_assets = get_asset_datum(/datum/asset/group/irv) irv_assets.send(src) var/datum/DBQuery/query_irv_get_votes = SSdbcore.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm index 9a0d9f9242..c3c0787aa8 100644 --- a/code/modules/mob/dead/new_player/preferences_setup.dm +++ b/code/modules/mob/dead/new_player/preferences_setup.dm @@ -17,7 +17,9 @@ facial_hair_style = random_facial_hair_style(gender) hair_color = random_short_color() facial_hair_color = hair_color - eye_color = random_eye_color() + var/random_eye_color = random_eye_color() + left_eye_color = random_eye_color + right_eye_color = random_eye_color if(!pref_species) var/rando_race = pick(GLOB.roundstart_races) pref_species = new rando_race() @@ -41,7 +43,7 @@ var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES) // Apply the Dummy's preview background first so we properly layer everything else on top of it. mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER)) - copy_to(mannequin) + copy_to(mannequin, initial_spawn = TRUE) if(previewJob && equip_job) mannequin.job = previewJob.title diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a0df1ee938..e1d078c632 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -1,6 +1,9 @@ GLOBAL_LIST_EMPTY(ghost_images_default) //this is a list of the default (non-accessorized, non-dir) images of the ghosts themselves GLOBAL_LIST_EMPTY(ghost_images_simple) //this is a list of all ghost images as the simple white ghost - +GLOBAL_LIST_INIT(ghost_verbs, list( + /mob/dead/observer/proc/dead_tele, + /mob/dead/observer/proc/open_spawners_menu, + /mob/dead/observer/proc/view_gas)) GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) /mob/dead/observer @@ -60,10 +63,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) /mob/dead/observer/Initialize(mapload, mob/body) set_invisibility(GLOB.observer_default_invisibility) - verbs += list( - /mob/dead/observer/proc/dead_tele, - /mob/dead/observer/proc/open_spawners_menu, - /mob/dead/observer/proc/view_gas) + add_verb(src, GLOB.ghost_verbs) if(icon_state in GLOB.ghost_forms_with_directions_list) ghostimage_default = image(src.icon,src,src.icon_state + "_nodir") @@ -118,8 +118,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) real_name = name if(!fun_verbs) - verbs -= /mob/dead/observer/verb/boo - verbs -= /mob/dead/observer/verb/possess + remove_verb(src, /mob/dead/observer/verb/boo) + remove_verb(src, /mob/dead/observer/verb/possess) animate(src, pixel_y = 2, time = 10, loop = -1) @@ -278,6 +278,7 @@ Works together with spawning an observer, noted above. if (!(client.prefs.chat_toggles & CHAT_OOC)) client.prefs.chat_toggles ^= CHAT_OOC transfer_ckey(ghost, FALSE) + ghost.client.init_verbs() if(penalize) var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES @@ -408,9 +409,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(usr, "Another consciousness is in your body...It is resisting you.") return client.change_view(CONFIG_GET(string/default_view)) - SStgui.on_transfer(src, mind.current) // Transfer NanoUIs. transfer_ckey(mind.current, FALSE) - return 1 + SStgui.on_transfer(src, mind.current) // Transfer NanoUIs. + mind.current.client.init_verbs() + return TRUE /mob/dead/observer/verb/stay_dead() set category = "Ghost" @@ -847,11 +849,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ghostimage_simple.icon_state = icon_state if(NAMEOF(src, fun_verbs)) if(fun_verbs) - verbs += /mob/dead/observer/verb/boo - verbs += /mob/dead/observer/verb/possess + add_verb(src, /mob/dead/observer/verb/boo) + add_verb(src, /mob/dead/observer/verb/possess) else - verbs -= /mob/dead/observer/verb/boo - verbs -= /mob/dead/observer/verb/possess + remove_verb(src, /mob/dead/observer/verb/boo) + remove_verb(src, /mob/dead/observer/verb/possess) /mob/dead/observer/reset_perspective(atom/A) if(client) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index b81172afad..3aa5f8e302 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -80,3 +80,8 @@ data["npcs"] = npcs return data + +/datum/orbit_menu/ui_assets() + . = ..() || list() + . += get_asset_datum(/datum/asset/simple/orbit) + diff --git a/code/modules/mob/living/brain/emote.dm b/code/modules/mob/living/brain/emote.dm index 540c7b3949..e1cb1a29cc 100644 --- a/code/modules/mob/living/brain/emote.dm +++ b/code/modules/mob/living/brain/emote.dm @@ -1,13 +1,3 @@ -/datum/emote/brain - mob_type_allowed_typecache = list(/mob/living/brain) - mob_type_blacklist_typecache = list() - -/datum/emote/brain/can_run_emote(mob/user, status_check = TRUE) - . = ..() - var/mob/living/brain/B = user - if(!istype(B) || (!(B.container && istype(B.container, /obj/item/mmi)))) - return FALSE - /datum/emote/brain/alarm key = "alarm" message = "sounds an alarm." diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 951185ee92..e7ad67d240 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -33,8 +33,8 @@ var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|queen)( \\(\\d+\\))?") /mob/living/carbon/alien/Initialize() - verbs += /mob/living/proc/mob_sleep - verbs += /mob/living/proc/lay_down + add_verb(src, /mob/living/proc/mob_sleep) + add_verb(src, /mob/living/proc/lay_down) create_bodyparts() //initialize bodyparts @@ -93,11 +93,9 @@ /mob/living/carbon/alien/IsAdvancedToolUser() return has_fine_manipulation -/mob/living/carbon/alien/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") +/mob/living/carbon/alien/get_status_tab_items() + . = ..() + . += "Intent: [a_intent]" /mob/living/carbon/alien/getTrail() if(getBruteLoss() < 200) diff --git a/code/modules/mob/living/carbon/alien/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm index 0ab448d2c5..963981b51e 100644 --- a/code/modules/mob/living/carbon/alien/emote.dm +++ b/code/modules/mob/living/carbon/alien/emote.dm @@ -1,6 +1,3 @@ -/datum/emote/living/alien - mob_type_allowed_typecache = list(/mob/living/carbon/alien) - /datum/emote/living/alien/gnarl key = "gnarl" key_third_person = "gnarls" diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 3827aef8c1..399efc4b29 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -148,10 +148,10 @@ Doesn't work on other aliens/AI.*/ action_icon_state = "alien_acid" /obj/effect/proc_holder/alien/acid/on_gain(mob/living/carbon/user) - user.verbs.Add(/mob/living/carbon/proc/corrosive_acid) + add_verb(user, /mob/living/carbon/proc/corrosive_acid) /obj/effect/proc_holder/alien/acid/on_lose(mob/living/carbon/user) - user.verbs.Remove(/mob/living/carbon/proc/corrosive_acid) + remove_verb(user, /mob/living/carbon/proc/corrosive_acid) /obj/effect/proc_holder/alien/acid/proc/corrode(atom/target,mob/living/carbon/user = usr) if(target in oview(1,user)) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 93050a4f9d..8f0ef2b384 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -30,10 +30,9 @@ ..() //This needs to be fixed -/mob/living/carbon/alien/larva/Stat() - ..() - if(statpanel("Status")) - stat(null, "Progress: [amount_grown]/[max_grown]") +/mob/living/carbon/alien/larva/get_status_tab_items() + . = ..() + . += "Progress: [amount_grown]/[max_grown]" /mob/living/carbon/alien/larva/adjustPlasma(amount) if(stat != DEAD && amount > 0) diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index d63686691d..0a2434055f 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -40,9 +40,6 @@ if(move_delay_add > 0) move_delay_add = max(0, move_delay_add - rand(1, 2)) -/mob/living/carbon/alien/handle_changeling() - return - /mob/living/carbon/alien/handle_fire()//Aliens on fire code if(..()) return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index b7d67e49a6..1706763f6b 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -481,16 +481,17 @@ var/turf/target = get_turf(loc) I.safe_throw_at(target,I.throw_range,I.throw_speed,src, force = move_force) -/mob/living/carbon/Stat() - ..() - if(statpanel("Status")) - var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel) - if(vessel) - stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]") - if(locate(/obj/item/assembly/health) in src) - stat(null, "Health: [health]") +/mob/living/carbon/get_status_tab_items() + . = ..() + var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel) + if(vessel) + . += "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]" + if(locate(/obj/item/assembly/health) in src) + . += "Health: [health]" - add_abilities_to_panel() +/mob/living/carbon/get_proc_holders() + . = ..() + . += add_abilities_to_panel() /mob/living/carbon/attack_ui(slot) if(!has_hand_for_held_index(active_hand_index)) diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm index e3512e3929..49501e0315 100644 --- a/code/modules/mob/living/carbon/emote.dm +++ b/code/modules/mob/living/carbon/emote.dm @@ -1,6 +1,3 @@ -/datum/emote/living/carbon - mob_type_allowed_typecache = list(/mob/living/carbon) - /datum/emote/living/carbon/airguitar key = "airguitar" message = "is strumming the air and headbanging like a safari chimp." @@ -22,7 +19,6 @@ muzzle_ignore = TRUE restraint_check = TRUE emote_type = EMOTE_AUDIBLE - mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai) /datum/emote/living/carbon/clap/run_emote(mob/living/user, params) . = ..() @@ -41,7 +37,6 @@ key = "gnarl" key_third_person = "gnarls" message = "gnarls and shows its teeth..." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) /datum/emote/living/carbon/moan key = "moan" @@ -55,27 +50,23 @@ key = "roll" key_third_person = "rolls" message = "rolls." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) restraint_check = TRUE /datum/emote/living/carbon/scratch key = "scratch" key_third_person = "scratches" message = "scratches." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) restraint_check = TRUE /datum/emote/living/carbon/screech key = "screech" key_third_person = "screeches" message = "screeches." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) /datum/emote/living/carbon/sign key = "sign" key_third_person = "signs" message_param = "signs the number %t." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) restraint_check = TRUE /datum/emote/living/carbon/sign/select_param(mob/user, params) @@ -87,13 +78,11 @@ key = "signal" key_third_person = "signals" message_param = "raises %t fingers." - mob_type_allowed_typecache = list(/mob/living/carbon/human) restraint_check = TRUE /datum/emote/living/carbon/tail key = "tail" message = "waves their tail." - mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) /datum/emote/living/carbon/wink key = "wink" diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 2f5c94b784..ed1ba3852f 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -18,6 +18,9 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) /mob/living/carbon/human/dummy/Life() return +/mob/living/carbon/human/dummy/update_mobility() + return + /mob/living/carbon/human/dummy/proc/wipe_state() delete_equipment() icon_render_key = null diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 04747ffcb4..837b4f73cf 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,6 +1,3 @@ -/datum/emote/living/carbon/human - mob_type_allowed_typecache = list(/mob/living/carbon/human) - /datum/emote/living/carbon/human/cry key = "cry" key_third_person = "cries" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 65b2931e08..6af171568b 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -92,7 +92,7 @@ if(!(SLOT_GLASSES in obscured)) if(glasses) . += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes." - else if(eye_color == BLOODCULT_EYE && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES)) + else if((left_eye_color == BLOODCULT_EYE || right_eye_color == BLOODCULT_EYE) && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES)) . += "[t_His] eyes are glowing an unnatural red!" else if(HAS_TRAIT(src, TRAIT_HIJACKER)) var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack) @@ -113,14 +113,14 @@ . += effects_exam //CIT CHANGES START HERE - adds genital details to examine text - if(LAZYLEN(internal_organs)) + if(LAZYLEN(internal_organs) && CHECK_BITFIELD(user.client?.prefs.cit_toggles, GENITAL_EXAMINE)) for(var/obj/item/organ/genital/dicc in internal_organs) if(istype(dicc) && dicc.is_exposed()) . += "[dicc.desc]" - - var/cursed_stuff = attempt_vr(src,"examine_bellies",args) //vore Code - if(cursed_stuff) - . += cursed_stuff + if(CHECK_BITFIELD(user.client?.prefs.cit_toggles, VORE_EXAMINE)) + var/cursed_stuff = attempt_vr(src,"examine_bellies",args) //vore Code + if(cursed_stuff) + . += cursed_stuff //END OF CIT CHANGES //Jitters diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 38b420aaba..389787df67 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -6,10 +6,11 @@ appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE /mob/living/carbon/human/Initialize() - verbs += /mob/living/proc/mob_sleep - verbs += /mob/living/proc/lay_down - verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee - + add_verb(src, /mob/living/proc/mob_sleep) + add_verb(src, /mob/living/proc/lay_down) + add_verb(src, /mob/living/carbon/human/verb/underwear_toggle) + add_verb(src, /mob/living/verb/subtle) + add_verb(src, /mob/living/verb/subtler) //initialize limbs first create_bodyparts() @@ -61,55 +62,51 @@ //...and display them. add_to_all_human_data_huds() -/mob/living/carbon/human/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - if (internal) - if (!internal.air_contents) - qdel(internal) - else - stat("Internal Atmosphere Info", internal.name) - stat("Tank Pressure", internal.air_contents.return_pressure()) - stat("Distribution Pressure", internal.distribute_pressure) - - if(mind) - var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling) - stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]") - stat("Absorbed DNA", changeling.absorbedcount) - - +/mob/living/carbon/human/get_status_tab_items() + . = ..() + . += "Intent: [a_intent]" + . += "Move Mode: [m_intent]" + if(internal) + if(!internal.air_contents) + qdel(internal) + else + . += "" + . += "Internal Atmosphere Info: [internal.name]" + . += "Tank Pressure: [internal.air_contents.return_pressure()]" + . += "Distribution Pressure: [internal.distribute_pressure]" + if(mind) + var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) + if(changeling) + . += "" + . += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]" + . += "Absorbed DNA: [changeling.absorbedcount]" //NINJACODE if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja. var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit - if(statpanel("SpiderOS")) - stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]") - stat("Current Time:", "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]") - if(SN.s_initialized) - //Suit gear - stat("Energy Charge:", "[round(SN.cell.charge/100)]%") - stat("Smoke Bombs:", "\Roman [SN.s_bombs]") - //Ninja status - stat("Fingerprints:", "[md5(dna.uni_identity)]") - stat("Unique Identity:", "[dna.unique_enzymes]") - stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") - stat("Nutrition Status:", "[nutrition]") - stat("Oxygen Loss:", "[getOxyLoss()]") - stat("Toxin Levels:", "[getToxLoss()]") - stat("Burn Severity:", "[getFireLoss()]") - stat("Brute Trauma:", "[getBruteLoss()]") - stat("Radiation Levels:","[radiation] rad") - stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)") + . += "SpiderOS Status: [SN.s_initialized ? "Initialized" : "Disabled"]" + . += "Current Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]" + if(SN.s_initialized) + //Suit gear + . += "Energy Charge: [round(SN.cell.charge/100)]%" + . += "Smoke Bombs: \Roman [SN.s_bombs]" + //Ninja status + . += "Fingerprints: [md5(dna.uni_identity)]" + . += "Unique Identity: [dna.unique_enzymes]" + . += "Overall Status: [stat > 1 ? "dead" : "[health]% healthy"]" + . += "Nutrition Status: [nutrition]" + . += "Oxygen Loss: [getOxyLoss()]" + . += "Toxin Levels: [getToxLoss()]" + . += "Burn Severity: [getFireLoss()]" + . += "Brute Trauma: [getBruteLoss()]" + . += "Radiation Levels: [radiation] rad" + . += "Body Temperature: [bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)" - //Diseases - if(diseases.len) - stat("Viruses:", null) - for(var/thing in diseases) - var/datum/disease/D = thing - stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]") + //Diseases + if(length(diseases)) + . += "Viruses:" + for(var/thing in diseases) + var/datum/disease/D = thing + . += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]" /mob/living/carbon/human/show_inv(mob/user) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 13456ed61c..a6a3f408dc 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -24,7 +24,8 @@ var/facial_hair_style = "Shaved" //Eye colour - var/eye_color = "000" + var/left_eye_color = "000" + var/right_eye_color = "000" var/skin_tone = "caucasian1" //Skin tone diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index af95b9e1b7..5f30d902b1 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -75,12 +75,8 @@ . = pda.owner else if(istype(tablet)) var/obj/item/computer_hardware/card_slot/card_slot = tablet.all_components[MC_CARD] - if(card_slot && (card_slot.stored_card2 || card_slot.stored_card)) - if(card_slot.stored_card2) //The second card is the one used for authorization in the ID changing program, so we prioritize it here for consistency - . = card_slot.stored_card2.registered_name - else - if(card_slot.stored_card) - . = card_slot.stored_card.registered_name + if(card_slot?.stored_card) + . = card_slot.stored_card.registered_name if(!.) . = if_no_id //to prevent null-names making the mob unclickable return diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index ed509f900a..d433ca1821 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -570,19 +570,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // eyes if(!(NOEYES in species_traits)) var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES) - var/mutable_appearance/eye_overlay if(!has_eyes) - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER) + standing += mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER) else - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) - if((EYECOLOR in species_traits) && has_eyes) - eye_overlay.color = "#" + H.eye_color - - if(OFFSET_EYES in H.dna.species.offset_features) - eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1] - eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2] - - standing += eye_overlay + var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER) + var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER) + if((EYECOLOR in species_traits) && has_eyes) + left_eye.color = "#" + H.left_eye_color + right_eye.color = "#" + H.right_eye_color + if(OFFSET_EYES in offset_features) + left_eye.pixel_x += offset_features[OFFSET_EYES][1] + left_eye.pixel_y += offset_features[OFFSET_EYES][2] + right_eye.pixel_x += offset_features[OFFSET_EYES][1] + right_eye.pixel_y += offset_features[OFFSET_EYES][2] + standing += left_eye + standing += right_eye //Underwear, Undershirts & Socks if(!(NO_UNDERWEAR in species_traits)) @@ -783,7 +785,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(FACEHAIR) accessory_overlay.color = "#[H.facial_hair_color]" if(EYECOLOR) - accessory_overlay.color = "#[H.eye_color]" + accessory_overlay.color = "#[H.left_eye_color]" if(HORNCOLOR) accessory_overlay.color = "#[H.dna.features["horns_color"]]" if(WINGCOLOR) @@ -838,7 +840,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(FACEHAIR) extra_accessory_overlay.color = "#[H.facial_hair_color]" if(EYECOLOR) - extra_accessory_overlay.color = "#[H.eye_color]" + extra_accessory_overlay.color = "#[H.left_eye_color]" if(HORNCOLOR) extra_accessory_overlay.color = "#[H.dna.features["horns_color"]]" @@ -1379,6 +1381,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected)) + if(!affecting) //Maybe the bodypart is missing? Or things just went wrong.. + affecting = target.get_bodypart(BODY_ZONE_CHEST) //target chest instead, as failsafe. Or hugbox? You decide. + var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK) miss_chance = 0 @@ -1594,6 +1599,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H, attackchain_flags = NONE, damage_multiplier = 1) var/totitemdamage = H.pre_attacked_by(I, user) * damage_multiplier + + if(!affecting) //Something went wrong. Maybe the limb is missing? + affecting = H.get_bodypart(BODY_ZONE_CHEST) //If the limb is missing, or something went terribly wrong, just hit the chest instead + // Allows you to put in item-specific reactions based on species if(user != H) var/list/block_return = list() @@ -1605,8 +1614,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) return 0 var/hit_area - if(!affecting) //Something went wrong. Maybe the limb is missing? - affecting = H.bodyparts[1] hit_area = affecting.name var/def_zone = affecting.body_zone @@ -1956,19 +1963,19 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + min(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR, BODYTEMP_HEATING_MAX)) switch((loc_temp - H.bodytemperature)*thermal_protection) if(-INFINITY to -50) - H.throw_alert("temp", /obj/screen/alert/cold, 3) + H.throw_alert("tempfeel", /obj/screen/alert/cold, 3) if(-50 to -35) - H.throw_alert("temp", /obj/screen/alert/cold, 2) + H.throw_alert("tempfeel", /obj/screen/alert/cold, 2) if(-35 to -20) - H.throw_alert("temp", /obj/screen/alert/cold, 1) + H.throw_alert("tempfeel", /obj/screen/alert/cold, 1) if(-20 to 0) //This is the sweet spot where air is considered normal - H.clear_alert("temp") + H.clear_alert("tempfeel") if(0 to 15) //When the air around you matches your body's temperature, you'll start to feel warm. - H.throw_alert("temp", /obj/screen/alert/hot, 1) + H.throw_alert("tempfeel", /obj/screen/alert/hot, 1) if(15 to 30) - H.throw_alert("temp", /obj/screen/alert/hot, 2) + H.throw_alert("tempfeel", /obj/screen/alert/hot, 2) if(30 to INFINITY) - H.throw_alert("temp", /obj/screen/alert/hot, 3) + H.throw_alert("tempfeel", /obj/screen/alert/hot, 3) // +/- 50 degrees from 310K is the 'safe' zone, where no damage is dealt. if(H.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTHEAT)) @@ -1986,6 +1993,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) else firemodifier = min(firemodifier, 0) burn_damage = max(log(2-firemodifier,(H.bodytemperature-BODYTEMP_NORMAL))-5,0) // this can go below 5 at log 2.5 + if (burn_damage) + switch(burn_damage) + if(0 to 2) + H.throw_alert("temp", /obj/screen/alert/sweat, 1) + if(2 to 4) + H.throw_alert("temp", /obj/screen/alert/sweat, 2) + else + H.throw_alert("temp", /obj/screen/alert/sweat, 3) burn_damage = burn_damage * heatmod * H.physiology.heat_mod if (H.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4) //40% for level 3 damage on humans H.emote("scream") @@ -1998,14 +2013,18 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR)) switch(H.bodytemperature) if(200 to BODYTEMP_COLD_DAMAGE_LIMIT) + H.throw_alert("temp", /obj/screen/alert/shiver, 1) H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod*H.physiology.cold_mod, BURN) if(120 to 200) + H.throw_alert("temp", /obj/screen/alert/shiver, 2) H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod*H.physiology.cold_mod, BURN) else + H.throw_alert("temp", /obj/screen/alert/shiver, 3) H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod*H.physiology.cold_mod, BURN) else H.remove_movespeed_modifier(/datum/movespeed_modifier/cold) + H.clear_alert("temp") SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold") SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot") diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index d8dfe63b35..f3b499093b 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -83,17 +83,7 @@ /obj/item/organ/tongue/dullahan zone = "abstract" - modifies_speech = TRUE - -/obj/item/organ/tongue/dullahan/handle_speech(datum/source, list/speech_args) - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - if(isdullahan(H)) - var/datum/species/dullahan/D = H.dna.species - if(isobj(D.myhead.loc)) - var/obj/O = D.myhead.loc - O.say(speech_args[SPEECH_MESSAGE]) - speech_args[SPEECH_MESSAGE] = "" + accents = list(/datum/accent/dullahan) /obj/item/organ/ears/dullahan zone = "abstract" diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index 806782a8b2..b675925aeb 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -5,7 +5,8 @@ default_color = "00FF00" blacklisted = 0 sexes = 0 - species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE) + species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR) + hair_alpha = 210 inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 49c55f70b3..43f5ca5526 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -18,7 +18,8 @@ var/datum/action/innate/regenerate_limbs/regenerate_limbs var/datum/action/innate/slime_change/slime_change //CIT CHANGE liked_food = TOXIC | MEAT - toxic_food = null + disliked_food = null + toxic_food = ANTITOXIC coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage burnmod = 0.5 // = 1/2x generic burn damage diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 723c4848fe..857fb6d8ed 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -114,6 +114,14 @@ #undef VAMP_DRAIN_AMOUNT + +/mob/living/carbon/get_status_tab_items() + . = ..() + var/obj/item/organ/heart/vampire/darkheart = getorgan(/obj/item/organ/heart/vampire) + if(darkheart) + . += "Current blood level: [blood_volume]/[BLOOD_VOLUME_MAXIMUM]." + + /obj/item/organ/heart/vampire name = "vampire heart" actions_types = list(/datum/action/item_action/organ_action/vampire_heart) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 9b39438563..cfb35fbb00 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -758,17 +758,22 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if // eyes if(!(NOEYES in dna.species.species_traits)) var/has_eyes = getorganslot(ORGAN_SLOT_EYES) - var/mutable_appearance/eye_overlay if(!has_eyes) - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER) + add_overlay(mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)) else - eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) - if((EYECOLOR in dna.species.species_traits) && has_eyes) - eye_overlay.color = "#" + eye_color - if(OFFSET_EYES in dna.species.offset_features) - eye_overlay.pixel_x += dna.species.offset_features[OFFSET_EYES][1] - eye_overlay.pixel_y += dna.species.offset_features[OFFSET_EYES][2] - add_overlay(eye_overlay) + var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER) + var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER) + if((EYECOLOR in dna.species.species_traits) && has_eyes) + left_eye.color = "#" + left_eye_color + right_eye.color = "#" + right_eye_color + if(OFFSET_EYES in dna.species.offset_features) + left_eye.pixel_x += dna.species.offset_features[OFFSET_EYES][1] + left_eye.pixel_y += dna.species.offset_features[OFFSET_EYES][2] + right_eye.pixel_x += dna.species.offset_features[OFFSET_EYES][1] + right_eye.pixel_y += dna.species.offset_features[OFFSET_EYES][2] + add_overlay(left_eye) + add_overlay(right_eye) + dna.species.handle_hair(src) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e29c6b9ffe..8f181d47fd 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -1,8 +1,4 @@ /mob/living/carbon/BiologicalLife(seconds, times_fired) - //Updates the number of stored chemicals for powers - handle_changeling() - //Handles the unique mentabolism of bloodsuckers, look at /datum/antagonist/bloodsucker/proc/LifeTick() - handle_bloodsucker() //Reagent processing needs to come before breathing, to prevent edge cases. handle_organs() . = ..() // if . is false, we are dead. @@ -410,25 +406,7 @@ for(var/thing in all_wounds) var/datum/wound/W = thing if(W.processes) // meh - W.handle_process() - -//todo generalize this and move hud out -/mob/living/carbon/proc/handle_changeling() - if(mind && hud_used && hud_used.lingchemdisplay) - var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling) - changeling.regenerate() - hud_used.lingchemdisplay.invisibility = 0 - hud_used.lingchemdisplay.maptext = "
    [round(changeling.chem_charges)]
    " - else - hud_used.lingchemdisplay.invisibility = INVISIBILITY_ABSTRACT - - -/mob/living/carbon/proc/handle_bloodsucker() - if(mind && AmBloodsucker(src)) - var/datum/antagonist/bloodsucker/B = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - B.LifeTick() - + W.handle_process() /mob/living/carbon/handle_mutations_and_radiation() if(dna && dna.temporary_mutations.len) diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 5b91119789..1f3e0a1b81 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -18,8 +18,8 @@ hud_type = /datum/hud/monkey /mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner) - verbs += /mob/living/proc/mob_sleep - verbs += /mob/living/proc/lay_down + add_verb(src, /mob/living/proc/mob_sleep) + add_verb(src, /mob/living/proc/lay_down) if(unique_name) //used to exclude pun pun gender = pick(MALE, FEMALE) @@ -90,16 +90,16 @@ return add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_temperature_speedmod, TRUE, slow) -/mob/living/carbon/monkey/Stat() - ..() - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - if(client && mind) - var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling) - stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]") - stat("Absorbed DNA", changeling.absorbedcount) +/mob/living/carbon/monkey/get_status_tab_items() + . = ..() + . += "Intent: [a_intent]" + . += "Move Mode: [m_intent]" + if(client && mind) + var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) + if(changeling) + . += "" + . += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]" + . += "Absorbed DNA: [changeling.absorbedcount]" /mob/living/carbon/monkey/verb/removeinternal() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index a735baceae..1d78979cbd 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -1,9 +1,3 @@ - -/* EMOTE DATUMS */ -/datum/emote/living - mob_type_allowed_typecache = /mob/living - mob_type_blacklist_typecache = list(/mob/living/simple_animal/slime, /mob/living/brain) - /datum/emote/living/blush key = "blush" key_third_person = "blushes" @@ -233,6 +227,21 @@ return else if(isinsect(C)) playsound(C, 'sound/voice/moth/mothlaugh.ogg', 50, 1) + else if(isjellyperson(C)) + var/mob/living/carbon/human/H = C + if(H.dna.features["mam_ears"] == "Cat" || H.dna.features["mam_ears"] == "Cat, Big") //slime have cat ear. slime go nya. + playsound(C, pick('sound/voice/jelly/nyahaha1.ogg', + 'sound/voice/jelly/nyahaha2.ogg', + 'sound/voice/jelly/nyaha.ogg', + 'sound/voice/jelly/nyahehe.ogg'), + 50, 1) + return + else if(user.gender == FEMALE) + playsound(C, 'sound/voice/jelly/womanlaugh.ogg', 50, 1) + return + else + playsound(C, pick('sound/voice/jelly/manlaugh1.ogg', 'sound/voice/jelly/manlaugh2.ogg'), 50, 1) + return else if(ishumanbasic(C)) if(user.gender == FEMALE) playsound(C, 'sound/voice/human/womanlaugh.ogg', 50, 1) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 89321082c9..e7727fcedc 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -1,5 +1,5 @@ /** - * Called by SSmobs at (hopefully) an interval of 1 second. + * Called by SSmobs at an interval of 2 seconds. * Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this. */ /mob/living/proc/Life(seconds, times_fired) @@ -43,6 +43,7 @@ * Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop. */ /mob/living/proc/BiologicalLife(seconds, times_fired) + SEND_SIGNAL(src,COMSIG_LIVING_BIOLOGICAL_LIFE, seconds, times_fired) handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not. handle_wounds() @@ -78,6 +79,7 @@ * Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop. */ /mob/living/proc/PhysicalLife(seconds, times_fired) + SEND_SIGNAL(src,COMSIG_LIVING_PHYSICAL_LIFE, seconds, times_fired) if(digitalinvis) handle_diginvis() //AI becomes unable to see mob diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2a461b5921..8dac56a8c9 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1163,8 +1163,10 @@ A.action.Remove(src) /mob/living/proc/add_abilities_to_panel() + var/list/L = list() for(var/obj/effect/proc_holder/A in abilities) - statpanel("[A.panel]",A.get_panel_text(),A) + L[++L.len] = list("[A.panel]",A.get_panel_text(),A.name,"[REF(A)]") + return L /mob/living/lingcheck() if(mind) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index aab741edd6..7ce1c1e7cc 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -23,6 +23,7 @@ a_intent = INTENT_HARM //so we always get pushed instead of trying to swap sight = SEE_TURFS | SEE_MOBS | SEE_OBJS see_in_dark = 8 + deathsound = 'sound/voice/scream/android_scream.ogg' hud_type = /datum/hud/ai med_hud = DATA_HUD_MEDICAL_BASIC sec_hud = DATA_HUD_SECURITY_BASIC @@ -139,7 +140,7 @@ spark_system.set_up(5, 0, src) spark_system.attach(src) - verbs += /mob/living/silicon/ai/proc/show_laws_verb + add_verb(src, /mob/living/silicon/ai/proc/show_laws_verb) aiPDA = new/obj/item/pda/ai(src) aiPDA.owner = name @@ -153,10 +154,10 @@ deploy_action.Grant(src) if(isturf(loc)) - verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ + add_verb(src, list(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, \ - /mob/living/silicon/ai/proc/set_automatic_say_channel) + /mob/living/silicon/ai/proc/set_automatic_say_channel)) GLOB.ai_list += src GLOB.shuttle_caller_list += src @@ -208,26 +209,26 @@ display_icon_override = ai_core_icon set_core_display_icon(ai_core_icon) -/mob/living/silicon/ai/Stat() - ..() - if(statpanel("Status")) - if(!stat) - stat(null, text("System integrity: [(health+100)/2]%")) - stat(null, text("Connected cyborgs: [connected_robots.len]")) - for(var/mob/living/silicon/robot/R in connected_robots) - var/robot_status = "Nominal" - if(R.shell) - robot_status = "AI SHELL" - else if(R.stat || !R.client) - robot_status = "OFFLINE" - else if(!R.cell || R.cell.charge <= 0) - robot_status = "DEPOWERED" - //Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies! - stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \ - Module: [R.designation] | Loc: [get_area_name(R, TRUE)] | Status: [robot_status]")) - stat(null, text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]")) //Count of total AI shells - else - stat(null, text("Systems nonfunctional")) +/mob/living/silicon/ai/get_status_tab_items() + . = ..() + if(stat != CONSCIOUS) + . += text("Systems nonfunctional") + return + . += text("System integrity: [(health + 100) * 0.5]%") + . += text("Connected cyborgs: [length(connected_robots)]") + for(var/r in connected_robots) + var/mob/living/silicon/robot/connected_robot = r + var/robot_status = "Nominal" + if(connected_robot.shell) + robot_status = "AI SHELL" + else if(connected_robot.stat != CONSCIOUS || !connected_robot.client) + robot_status = "OFFLINE" + else if(!connected_robot.cell || connected_robot.cell.charge <= 0) + robot_status = "DEPOWERED" + //Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies! + . += text("[connected_robot.name] | S.Integrity: [connected_robot.health]% | Cell: [connected_robot.cell ? "[connected_robot.cell.charge]/[connected_robot.cell.maxcharge]" : "Empty"] | \ + Module: [connected_robot.designation] | Loc: [get_area_name(connected_robot, TRUE)] | Status: [robot_status]") + . += text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]") //Count of total AI shells /mob/living/silicon/ai/proc/ai_alerts() var/dat = "Current Station Alerts\n" @@ -858,7 +859,7 @@ to_chat(src, "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices.") to_chat(src, "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds.") view_core() //A BYOND bug requires you to be viewing your core before your verbs update - verbs += /mob/living/silicon/ai/proc/choose_modules + add_verb(src, /mob/living/silicon/ai/proc/choose_modules) malf_picker = new /datum/module_picker diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 704a23b8db..6d2da187a1 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -184,13 +184,12 @@ else client.eye = card -/mob/living/silicon/pai/Stat() - ..() - if(statpanel("Status")) - if(!stat) - stat(null, text("Emitter Integrity: [emitterhealth * (100/emittermaxhealth)]")) - else - stat(null, text("Systems nonfunctional")) +/mob/living/silicon/pai/get_status_tab_items() + . += ..() + if(!stat) + . += text("Emitter Integrity: [emitterhealth * (100/emittermaxhealth)]") + else + . += text("Systems nonfunctional") /mob/living/silicon/pai/restrained(ignore_grab) . = FALSE diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index c0fca997f5..c532e44ff5 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -5,7 +5,7 @@ /datum/emote/sound/silicon mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human) emote_type = EMOTE_AUDIBLE - var/unrestricted = FALSE + var/unrestricted = TRUE /datum/emote/sound/silicon/run_emote(mob/user, params) if(!unrestricted && !(issilicon(user) || isipcperson(user))) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index d8299d42ad..6143bde602 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -72,8 +72,8 @@ toner = tonermax diag_hud_set_borgcell() - verbs += /mob/living/proc/lay_down //CITADEL EDIT gimmie rest verb kthx - verbs += /mob/living/silicon/robot/proc/rest_style + add_verb(src, /mob/living/proc/lay_down) //CITADEL EDIT gimmie rest verb kthx + add_verb(src, /mob/living/silicon/robot/proc/rest_style) //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO /mob/living/silicon/robot/Destroy() @@ -99,7 +99,7 @@ radio.keyslot = null //END CITADEL EDIT if(connected_ai) - connected_ai.connected_robots -= src + set_connected_ai(null) if(shell) GLOB.available_ai_shells -= src else @@ -222,19 +222,19 @@ if(thruster_button) thruster_button.icon_state = "ionpulse[ionpulse_on]" -/mob/living/silicon/robot/Stat() - ..() - if(statpanel("Status")) - if(cell) - stat("Charge Left:", "[cell.charge]/[cell.maxcharge]") - else - stat(null, text("No Cell Inserted!")) +/mob/living/silicon/robot/get_status_tab_items() + . = ..() + . += "" + if(cell) + . += "Charge Left: [cell.charge]/[cell.maxcharge]" + else + . += text("No Cell Inserted!") - if(module) - for(var/datum/robot_energy_storage/st in module.storages) - stat("[st.name]:", "[st.energy]/[st.max_energy]") - if(connected_ai) - stat("Master AI:", connected_ai.name) + if(module) + for(var/datum/robot_energy_storage/st in module.storages) + . += "[st.name]: [st.energy]/[st.max_energy]" + if(connected_ai) + . += "Master AI: [connected_ai.name]" /mob/living/silicon/robot/restrained(ignore_grab) . = 0 @@ -560,11 +560,10 @@ gib() /mob/living/silicon/robot/proc/UnlinkSelf() - if(src.connected_ai) - connected_ai.connected_robots -= src - src.connected_ai = null - lawupdate = 0 - scrambledcodes = 1 + set_connected_ai(null) + lawupdate = FALSE + locked_down = FALSE + scrambledcodes = TRUE //Disconnect it's camera so it's not so easily tracked. if(!QDELETED(builtInCamera)) QDEL_NULL(builtInCamera) @@ -586,10 +585,10 @@ W.attack_self(src) -/mob/living/silicon/robot/proc/SetLockdown(state = 1) +/mob/living/silicon/robot/proc/SetLockdown(state = TRUE) // They stay locked down if their wire is cut. if(wires.is_cut(WIRE_LOCKDOWN)) - state = 1 + state = TRUE if(state) throw_alert("locked", /obj/screen/alert/locked) else @@ -991,7 +990,7 @@ builtInCamera.c_tag = real_name //update the camera name too mainframe = AI deployed = TRUE - connected_ai = mainframe + set_connected_ai(mainframe) mainframe.connected_robots |= src lawupdate = TRUE lawsync() @@ -1090,9 +1089,8 @@ . = ..(user) /mob/living/silicon/robot/proc/TryConnectToAI() - connected_ai = select_active_ai_with_fewest_borgs() + set_connected_ai(select_active_ai_with_fewest_borgs(z)) if(connected_ai) - connected_ai.connected_robots += src lawsync() lawupdate = 1 return TRUE @@ -1134,7 +1132,7 @@ /mob/living/silicon/robot/adjustStaminaLossBuffered(amount, updating_health = 1) if(istype(cell)) - cell.charge -= amount*5 + cell.charge -= amount * 5 /mob/living/silicon/robot/verb/viewmanifest() set category = "Robot Commands" @@ -1143,3 +1141,14 @@ if(usr.stat == DEAD) return //won't work if dead ai_roster() + +/mob/living/silicon/robot/proc/set_connected_ai(new_ai) + if(connected_ai == new_ai) + return + . = connected_ai + connected_ai = new_ai + if(.) + var/mob/living/silicon/ai/old_ai = . + old_ai.connected_robots -= src + if(connected_ai) + connected_ai.connected_robots |= src diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 746c4f469d..a0ea9b735c 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -138,8 +138,8 @@ /mob/living/silicon/robot/proc/beep_boop_rogue_bot(mob/user) SetEmagged(1) SetStun(60) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown - lawupdate = 0 - connected_ai = null + lawupdate = FALSE + set_connected_ai(null) message_admins("[ADMIN_LOOKUPFLW(user)] emagged cyborg [ADMIN_LOOKUPFLW(src)]. Laws overridden.") log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") var/time = time2text(world.realtime,"hh:mm:ss") diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 6b58988c31..7c4125fbc6 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -361,8 +361,7 @@ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"), "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"), "Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"), - "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed"), - "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakemedbox") + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed") ) var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed") for(var/a in L) @@ -423,13 +422,6 @@ moduleselect_icon = "medihound" moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi' dogborg = TRUE - if("Drake") - cyborg_base_icon = "drakemed" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakemedsleeper" - moduleselect_icon = "medihound" - moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi' - dogborg = TRUE else return FALSE return ..() @@ -486,8 +478,7 @@ "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"), "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"), "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"), - "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng"), - "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakeengbox") + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng") ) var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng") for(var/a in L) @@ -545,11 +536,6 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "alinasleeper" dogborg = TRUE - if("Drake") - cyborg_base_icon = "drakeeng" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakesecsleeper" - dogborg = TRUE else return FALSE return ..() @@ -588,8 +574,7 @@ "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"), "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"), "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"), - "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec"), - "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakesecbox") + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec") ) var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark") for(var/a in L) @@ -645,11 +630,6 @@ sleeper_overlay = "valesecsleeper" cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' dogborg = TRUE - if("Drake") - cyborg_base_icon = "drakesec" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakesecsleeper" - dogborg = TRUE else return FALSE return ..() @@ -693,8 +673,7 @@ var/static/list/peace_icons = sortList(list( "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"), "Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"), - "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider"), - "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakepeacebox") + "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider") )) var/peace_borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) switch(peace_borg_icon) @@ -710,11 +689,6 @@ hat_offset = INFINITY cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' has_snowflake_deadsprite = TRUE - if("Drake") - cyborg_base_icon = "drakepeace" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakepeacesleeper" - dogborg = TRUE else return FALSE return ..() @@ -853,8 +827,7 @@ "(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"), "(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"), "(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"), - "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"), - "(Janitor) Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakejanitbox") + "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan") ) var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark", "(Janitor) Scrubpuppy" = "scrubpup") @@ -926,11 +899,6 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "jsleeper" dogborg = TRUE - if("(Janitor) Drake") - cyborg_base_icon = "drakejanit" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakesecsleeper" - dogborg = TRUE else return FALSE return ..() @@ -976,8 +944,7 @@ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"), "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"), "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"), - "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"), - "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakeminebox") + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin") ) var/list/L = list("Blade" = "blade", "Vale" = "valemine") for(var/a in L) @@ -1021,11 +988,6 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "valeminesleeper" dogborg = TRUE - if("Drake") - cyborg_base_icon = "drakemine" - cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' - sleeper_overlay = "drakeminesleeper" - dogborg = TRUE else return FALSE return ..() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index c6aee397e4..944b909463 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -13,6 +13,7 @@ mob_biotypes = MOB_ROBOTIC rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE speech_span = SPAN_ROBOT + deathsound = 'sound/voice/borg_deathsound.ogg' flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 vore_flags = NO_VORE diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm index f79a2b5b3e..ec2180ccb3 100644 --- a/code/modules/mob/living/simple_animal/astral.dm +++ b/code/modules/mob/living/simple_animal/astral.dm @@ -24,6 +24,7 @@ incorporeal_move = 1 alpha = 50 speak_emote = list("echos") + rad_flags = RAD_NO_CONTAMINATE movement_type = FLYING var/pseudo_death = FALSE var/posses_safe = FALSE diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index d9bf8cc553..ceaf7a6f96 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -438,6 +438,16 @@ +/mob/living/simple_animal/bot/mulebot/get_status_tab_items() + . = ..() + if(cell) + . += "Charge Left: [cell.charge]/[cell.maxcharge]" + else + . += text("No Cell Inserted!") + if(load) + . += "Current Load: [load.name]" + + /mob/living/simple_animal/bot/mulebot/call_bot() ..() if(path && path.len) diff --git a/code/modules/mob/living/simple_animal/friendly/bumbles.dm b/code/modules/mob/living/simple_animal/friendly/bumbles.dm index 3707aa33f8..0debb7b98c 100644 --- a/code/modules/mob/living/simple_animal/friendly/bumbles.dm +++ b/code/modules/mob/living/simple_animal/friendly/bumbles.dm @@ -34,7 +34,7 @@ /mob/living/simple_animal/pet/bumbles/Initialize() . = ..() - verbs += /mob/living/proc/lay_down + add_verb(src, /mob/living/proc/lay_down) /mob/living/simple_animal/pet/bumbles/ComponentInitialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index c21875d1db..71ae3b4c03 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -39,7 +39,7 @@ /mob/living/simple_animal/pet/cat/Initialize() . = ..() - verbs += /mob/living/proc/lay_down + add_verb(src, /mob/living/proc/lay_down) /mob/living/simple_animal/pet/cat/ComponentInitialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index da39fb71cf..55339a02fd 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -142,8 +142,8 @@ set_light(2, 0.5) qdel(access_card) //we don't have free access access_card = null - verbs -= /mob/living/simple_animal/drone/verb/check_laws - verbs -= /mob/living/simple_animal/drone/verb/drone_ping + remove_verb(src, /mob/living/simple_animal/drone/verb/check_laws) + remove_verb(src, /mob/living/simple_animal/drone/verb/drone_ping) /mob/living/simple_animal/drone/cogscarab/Login() ..() diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 7abecc7c81..954e968bd7 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -196,18 +196,17 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians REMOVE_TRAIT(summoner, TRAIT_NODEATH, "memento_mori") to_chat(summoner,"You feel incredibly vulnerable as the memento mori pulls your life force in one too many directions!") -/mob/living/simple_animal/hostile/guardian/Stat() - ..() - if(statpanel("Status")) - if(summoner) - var/resulthealth - if(iscarbon(summoner)) - resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100) - else - resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5) - stat(null, "Summoner Health: [resulthealth]%") - if(cooldown >= world.time) - stat(null, "Manifest/Recall Cooldown Remaining: [DisplayTimeText(cooldown - world.time)]") +/mob/living/simple_animal/hostile/guardian/get_status_tab_items() + . += ..() + if(summoner) + var/resulthealth + if(iscarbon(summoner)) + resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100) + else + resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5) + . += "Summoner Health: [resulthealth]%" + if(cooldown >= world.time) + . += "Manifest/Recall Cooldown Remaining: [DisplayTimeText(cooldown - world.time)]" /mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range . = ..() @@ -477,13 +476,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians to_chat(src, "[G.real_name] has been caught!") guardians -= G if(!guardians.len) - verbs -= /mob/living/proc/guardian_reset + remove_verb(src, /mob/living/proc/guardian_reset) else to_chat(src, "There were no ghosts willing to take control of [G.real_name]. Looks like you're stuck with it for now.") else to_chat(src, "You decide not to reset [guardians.len > 1 ? "any of your guardians":"your guardian"].") else - verbs -= /mob/living/proc/guardian_reset + remove_verb(src, /mob/living/proc/guardian_reset) ////////parasite tracking/finding procs @@ -608,9 +607,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians if("carp") to_chat(user, "[G.carp_fluff_string]") to_chat(user, "[G.real_name] has been caught!") - user.verbs += /mob/living/proc/guardian_comm - user.verbs += /mob/living/proc/guardian_recall - user.verbs += /mob/living/proc/guardian_reset + add_verb(user, list(/mob/living/proc/guardian_comm, \ + /mob/living/proc/guardian_recall, \ + /mob/living/proc/guardian_reset)) /obj/item/guardiancreator/choose random = FALSE diff --git a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm index 885f907997..3bc079f6d5 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm @@ -26,11 +26,10 @@ if(loc == summoner && toggle) ToggleMode(0) -/mob/living/simple_animal/hostile/guardian/assassin/Stat() - ..() - if(statpanel("Status")) - if(stealthcooldown >= world.time) - stat(null, "Stealth Cooldown Remaining: [DisplayTimeText(stealthcooldown - world.time)]") +/mob/living/simple_animal/hostile/guardian/assassin/get_status_tab_items() + . = ..() + if(stealthcooldown >= world.time) + . += "Stealth Cooldown Remaining: [DisplayTimeText(stealthcooldown - world.time)]" /mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget() . = ..() diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index 26e5d791f3..b9037ff4a4 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -7,11 +7,10 @@ carp_fluff_string = "CARP CARP CARP! Caught one! It's an explosive carp! Boom goes the fishy." var/bomb_cooldown = 0 -/mob/living/simple_animal/hostile/guardian/bomb/Stat() - ..() - if(statpanel("Status")) - if(bomb_cooldown >= world.time) - stat(null, "Bomb Cooldown Remaining: [DisplayTimeText(bomb_cooldown - world.time)]") +/mob/living/simple_animal/hostile/guardian/bomb/get_status_tab_items() + . = ..() + if(bomb_cooldown >= world.time) + . += "Bomb Cooldown Remaining: [DisplayTimeText(bomb_cooldown - world.time)]" /mob/living/simple_animal/hostile/guardian/bomb/AttackingTarget() . = ..() @@ -29,7 +28,7 @@ /mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A) if(!istype(A)) - altclick_listed_turf(A) + AltClickNoInteract(src, A) return if(loc == summoner) to_chat(src, "You must be manifested to create bombs!") diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm index 21460b5c6b..eee3eb0cdb 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/support.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm @@ -18,11 +18,10 @@ var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) -/mob/living/simple_animal/hostile/guardian/healer/Stat() - ..() - if(statpanel("Status")) - if(beacon_cooldown >= world.time) - stat(null, "Beacon Cooldown Remaining: [DisplayTimeText(beacon_cooldown - world.time)]") +/mob/living/simple_animal/hostile/guardian/healer/get_status_tab_items() + . = ..() + if(beacon_cooldown >= world.time) + . += "Beacon Cooldown Remaining: [DisplayTimeText(beacon_cooldown - world.time)]" /mob/living/simple_animal/hostile/guardian/healer/AttackingTarget() . = ..() @@ -106,7 +105,7 @@ /mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A) if(!istype(A)) - altclick_listed_turf(A) + AltClickNoInteract(src, A) return if(loc == summoner) to_chat(src, "You must be manifested to warp a target!") diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm index 100db06174..8fb531f1fb 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm @@ -1,6 +1,5 @@ /datum/emote/sound/gorilla mob_type_allowed_typecache = /mob/living/simple_animal/hostile/gorilla - mob_type_blacklist_typecache = list() /datum/emote/sound/gorilla/ooga key = "ooga" @@ -8,4 +7,3 @@ message = "oogas." message_param = "oogas at %t." sound = 'sound/creatures/gorilla.ogg' - diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index 362432b2af..b98ee5adfb 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -128,7 +128,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/Initialize() . = ..() - verbs -= /mob/living/verb/pulled + remove_verb(src, /mob/living/verb/pulled) /mob/living/simple_animal/hostile/jungle/leaper/CtrlClickOn(atom/A) face_atom(A) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 883ad39261..debd7f2e7b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -642,8 +642,8 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/lightgeist/Initialize() . = ..() - verbs -= /mob/living/verb/pulled - verbs -= /mob/verb/me_verb + remove_verb(src, /mob/living/verb/pulled) + remove_verb(src, /mob/verb/me_verb) var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) @@ -732,7 +732,7 @@ Difficulty: Very Hard L.mind.transfer_to(holder_animal) var/obj/effect/proc_holder/spell/targeted/exit_possession/P = new /obj/effect/proc_holder/spell/targeted/exit_possession holder_animal.mind.AddSpell(P) - holder_animal.verbs -= /mob/living/verb/pulled + remove_verb(holder_animal, /mob/living/verb/pulled) /obj/structure/closet/stasis/dump_contents(override = TRUE, kill = 1) STOP_PROCESSING(SSobj, src) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 4dfd4561d6..f0ab3fba4c 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -274,7 +274,7 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/dragon/AltClickOn(atom/movable/A) if(!istype(A)) - altclick_listed_turf(A) + AltClickNoInteract(src, A) return if(swoop_cooldown >= world.time) to_chat(src, "You need to wait 20 seconds between swoop attacks!") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index bd3a6e8232..006bef974d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -445,7 +445,7 @@ Difficulty: Normal /mob/living/simple_animal/hostile/megafauna/hierophant/AltClickOn(atom/A) //player control handler(don't give this to a player holy fuck) if(!istype(A) || get_dist(A, src) <= 2) - return altclick_listed_turf(A) + return AltClickNoInteract(src, A) blink(A) //Hierophant overlays diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 795184bad5..3de4c8b41b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -141,7 +141,7 @@ Difficulty: Medium loot = list(/obj/item/staff/storm) elimination = 0 else if(prob(20)) - loot = list(/obj/structure/closet/crate/necropolis/tendril) + loot = list(/obj/structure/closet/crate/necropolis/tendril/random) //This one spawns a chest that could be any of the three types ..() /obj/item/gps/internal/legion diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index e3edd171c0..e347056924 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -25,6 +25,7 @@ var/list/attack_action_types = list() var/can_talk = FALSE var/obj/loot_drop = null + var/crate_type = /obj/structure/closet/crate/necropolis/tendril var/owner //Gives player-controlled variants the ability to swap attacks @@ -182,7 +183,7 @@ While using this makes the system rely on OnFire, it still gives options for tim activator = null -obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind) +/obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind) var/selectedspawn = pick(potentialspawns) mychild = new selectedspawn(loc) visible_message("[mychild] emerges from [src]!") @@ -193,7 +194,7 @@ obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind) icon_state = "tumor_popped" INVOKE_ASYNC(src, .proc/arena_checks) -obj/structure/elite_tumor/proc/return_elite() +/obj/structure/elite_tumor/proc/return_elite() mychild.forceMove(loc) visible_message("[mychild] emerges from [src]!") playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) @@ -271,11 +272,11 @@ obj/structure/elite_tumor/proc/return_elite() visible_message("[mychild] suddenly reappears above [src]!") playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) -obj/structure/elite_tumor/proc/onEliteLoss() +/obj/structure/elite_tumor/proc/onEliteLoss() playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE) visible_message("[src] begins to convulse violently before beginning to dissipate.") visible_message("As [src] closes, something is forced up from down below.") - var/obj/structure/closet/crate/necropolis/tendril/lootbox = new /obj/structure/closet/crate/necropolis/tendril(loc) + var/obj/structure/closet/crate/necropolis/tendril/lootbox = new mychild.crate_type(loc) if(!boosted) mychild = null activator = null @@ -290,7 +291,7 @@ obj/structure/elite_tumor/proc/onEliteLoss() activator = null qdel(src) -obj/structure/elite_tumor/proc/onEliteWon() +/obj/structure/elite_tumor/proc/onEliteWon() activity = TUMOR_PASSIVE activator = null mychild.revive(full_heal = TRUE, admin_revive = TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index d9f3cfba3d..4e8f4f6160 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -40,6 +40,7 @@ mouse_opacity = MOUSE_OPACITY_ICON deathmessage = "explodes into gore!" loot_drop = /obj/item/crusher_trophy/broodmother_tongue + crate_type = /obj/structure/closet/crate/necropolis/tendril/weapon_armor attack_action_types = list(/datum/action/innate/elite_attack/tentacle_patch, /datum/action/innate/elite_attack/spawn_children, diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index fce5b636e4..032bc2d60d 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -38,7 +38,7 @@ deathsound = 'sound/magic/demon_dies.ogg' deathmessage = "begins to shudder as it becomes transparent..." loot_drop = /obj/item/clothing/neck/cloak/herald_cloak - + crate_type = /obj/structure/closet/crate/necropolis/tendril/magic can_talk = 1 attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot, diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index 15ed0135fe..6c13bb903e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -38,7 +38,7 @@ deathsound = 'sound/magic/curse.ogg' deathmessage = "'s arms reach out before it falls apart onto the floor, lifeless." loot_drop = /obj/item/crusher_trophy/legionnaire_spine - + crate_type = /obj/structure/closet/crate/necropolis/tendril/misc attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge, /datum/action/innate/elite_attack/head_detach, /datum/action/innate/elite_attack/bonfire_teleport, diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm index 7995e4d20f..b3300a86bb 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm @@ -38,7 +38,7 @@ deathsound = 'sound/magic/repulse.ogg' deathmessage = "'s lights flicker, before its top part falls down." loot_drop = /obj/item/clothing/accessory/pandora_hope - + crate_type = /obj/structure/closet/crate/necropolis/tendril/magic attack_action_types = list(/datum/action/innate/elite_attack/singular_shot, /datum/action/innate/elite_attack/magic_box, /datum/action/innate/elite_attack/pandora_teleport, @@ -190,4 +190,4 @@ /obj/item/clothing/accessory/pandora_hope/on_uniform_dropped(obj/item/clothing/under/U, user) var/mob/living/L = user if(L && L.mind) - SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "hope_lavaland") + SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "hope_lavaland") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 4fcb1ed5bf..3ca29b6746 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -115,12 +115,12 @@ parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var - verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \ + add_verb(src, list(/mob/living/simple_animal/parrot/proc/steal_from_ground, \ /mob/living/simple_animal/parrot/proc/steal_from_mob, \ /mob/living/simple_animal/parrot/verb/drop_held_item_player, \ /mob/living/simple_animal/parrot/proc/perch_player, \ /mob/living/simple_animal/parrot/proc/toggle_mode, - /mob/living/simple_animal/parrot/proc/perch_mob_player) + /mob/living/simple_animal/parrot/proc/perch_mob_player)) /mob/living/simple_animal/parrot/examine(mob/user) @@ -142,11 +142,11 @@ ..(gibbed) -/mob/living/simple_animal/parrot/Stat() - ..() - if(statpanel("Status")) - stat("Held Item", held_item) - stat("Mode",a_intent) +/mob/living/simple_animal/parrot/get_status_tab_items() + . = ..() + . += "" + . += "Held Item: [held_item]" + . += "Mode: [a_intent]" /mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) . = ..() @@ -978,7 +978,8 @@ /mob/living/simple_animal/parrot/Poly/ghost name = "The Ghost of Poly" desc = "Doomed to squawk the Earth." - color = "#FFFFFF77" + color = "#FFFFFF" + alpha = 77 speak_chance = 20 status_flags = GODMODE incorporeal_move = INCORPOREAL_MOVE_BASIC diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index be0338a60e..b192182c71 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -345,11 +345,10 @@ remove_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed, multiplicative_slowdown = speed) -/mob/living/simple_animal/Stat() - ..() - if(statpanel("Status")) - stat(null, "Health: [round((health / maxHealth) * 100)]%") - return 1 +/mob/living/simple_animal/get_status_tab_items() + . = ..() + . += "" + . += "Health: [round((health / maxHealth) * 100)]%" /mob/living/simple_animal/proc/drop_loot() if(loot.len) diff --git a/code/modules/mob/living/simple_animal/slime/emote.dm b/code/modules/mob/living/simple_animal/slime/emote.dm index 070cd48a70..9440caf3fc 100644 --- a/code/modules/mob/living/simple_animal/slime/emote.dm +++ b/code/modules/mob/living/simple_animal/slime/emote.dm @@ -1,6 +1,5 @@ /datum/emote/slime mob_type_allowed_typecache = /mob/living/simple_animal/slime - mob_type_blacklist_typecache = list() /datum/emote/slime/bounce key = "bounce" diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 1bdd988694..1f45e57718 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -106,6 +106,7 @@ set_colour(new_colour) . = ..() AddComponent(/datum/component/footstep, FOOTSTEP_MOB_SLIME, 7.5) + set_nutrition(rand(650, 800)) /mob/living/simple_animal/slime/Destroy() for (var/A in actions) @@ -208,21 +209,20 @@ /mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0) return 2 -/mob/living/simple_animal/slime/Stat() - if(..()) - - if(!docile) - stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]") - if(amount_grown >= SLIME_EVOLUTION_THRESHOLD) - if(is_adult) - stat(null, "You can reproduce!") - else - stat(null, "You can evolve!") +/mob/living/simple_animal/slime/get_status_tab_items() + . = ..() + if(!docile) + . += "Nutrition: [nutrition]/[get_max_nutrition()]" + if(amount_grown >= SLIME_EVOLUTION_THRESHOLD) + if(is_adult) + . += "You can reproduce!" + else + . += "You can evolve!" if(stat == UNCONSCIOUS) - stat(null,"You are knocked out by high levels of BZ!") + . += "You are knocked out by high levels of BZ!" else - stat(null,"Power Level: [powerlevel]") + . += "Power Level: [powerlevel]" /mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 31bfb5621f..0d4afd0915 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -50,6 +50,8 @@ var/datum/callback/CB = foo CB.Invoke() + mind?.hide_ckey = client?.prefs?.hide_ckey + log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP) SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 358eff7a47..e4434c0c0e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -586,87 +586,34 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) /mob/proc/is_muzzled() return FALSE -/mob/Stat() - ..() +/// Adds this list to the output to the stat browser +/mob/proc/get_status_tab_items() + . = list() - SSvote?.render_statpanel(src) - - //This is only called from client/Stat(), let's assume client exists. - - if(statpanel("Status")) - var/list/L = list() - L += "Ping: [round(client.lastping,1)]ms (Avg: [round(client.avgping,1)]ms)" - L += SSmapping.stat_map_name - L += "Round ID: [GLOB.round_id || "NULL"]" - L += SStime_track.stat_time_text - L += SSshuttle.emergency_shuttle_stat_text - stat(null, "[L.Join("\n\n")]") - - if(client.holder) - if(statpanel("MC")) - var/turf/T = get_turf(client.eye) - stat("Location:", COORD(T)) - stat("CPU:", "[world.cpu]") - stat("Instances:", "[num2text(world.contents.len, 10)]") - stat("World Time:", "[world.time]") - GLOB.stat_entry() - config.stat_entry() - stat(null) - if(Master) - Master.stat_entry() - else - stat("Master Controller:", "ERROR") - if(Failsafe) - Failsafe.stat_entry() - else - stat("Failsafe Controller:", "ERROR") - if(Master) - stat(null) - for(var/datum/controller/subsystem/SS in Master.statworthy_subsystems) - SS.stat_entry() - GLOB.cameranet.stat_entry() - if(statpanel("Tickets")) - GLOB.ahelp_tickets.stat_entry() - if(length(GLOB.sdql2_queries)) - if(statpanel("SDQL2")) - stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj) - for(var/i in GLOB.sdql2_queries) - var/datum/SDQL2_query/Q = i - Q.generate_stat() - if(listed_turf && client) - if(!TurfAdjacent(listed_turf)) - listed_turf = null - else - statpanel(listed_turf.name, null, listed_turf) - var/list/overrides = list() - for(var/image/I in client.images) - if(I.loc && I.loc.loc == listed_turf && I.override) - overrides += I.loc - for(var/atom/A in listed_turf) - if(!A.mouse_opacity) - continue - if(A.invisibility > see_invisible) - continue - if(overrides.len && (A in overrides)) - continue - statpanel(listed_turf.name, null, A) +/// Gets all relevant proc holders for the browser statpenl +/mob/proc/get_proc_holders() + . = list() if(mind) - add_spells_to_statpanel(mind.spell_list) - var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling) - add_stings_to_statpanel(changeling.purchasedpowers) - add_spells_to_statpanel(mob_spell_list) + . += get_spells_for_statpanel(mind.spell_list) + . += get_spells_for_statpanel(mob_spell_list) -/mob/proc/add_spells_to_statpanel(list/spells) +/** + * Convert a list of spells into a displyable list for the statpanel + * + * Shows charge and other important info + */ +/mob/proc/get_spells_for_statpanel(list/spells) + var/list/L = list() for(var/obj/effect/proc_holder/spell/S in spells) if((!S.mobs_blacklist || !S.mobs_blacklist[src]) && (!S.mobs_whitelist || S.mobs_whitelist[src])) switch(S.charge_type) if("recharge") - statpanel("[S.panel]","[S.charge_counter/10.0]/[S.charge_max/10]",S) + L[++L.len] = list("[S.panel]", "[S.charge_counter/10.0]/[S.charge_max/10]", S.name, REF(S)) if("charges") - statpanel("[S.panel]","[S.charge_counter]/[S.charge_max]",S) + L[++L.len] = list("[S.panel]", "[S.charge_counter]/[S.charge_max]", S.name, REF(S)) if("holdervar") - statpanel("[S.panel]","[S.holder_var_type] [S.holder_var_amount]",S) + L[++L.len] = list("[S.panel]", "[S.holder_var_type] [S.holder_var_amount]", S.name, REF(S)) + return L /mob/proc/add_stings_to_statpanel(list/stings) for(var/obj/effect/proc_holder/changeling/S in stings) @@ -798,6 +745,8 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) if(istype(S, spell)) mob_spell_list -= S qdel(S) + if(client) + client << output(null, "statbrowser:check_spells") /mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE) if(!magic && !holy && !tinfoil) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 52b755d926..aa6635f73d 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -431,7 +431,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp /mob/living/getImplant(type) return locate(type) in implants -/proc/offer_control(mob/M) +/proc/offer_control(mob/M,ignore_category=null) to_chat(M, "Control of your mob has been offered to dead players.") if(usr) log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.") @@ -445,7 +445,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist/) if(A) poll_message = "[poll_message] Status:[A.name]." - var/list/mob/candidates = pollCandidatesForMob(poll_message, ROLE_PAI, null, FALSE, 100, M) + var/list/mob/candidates = pollCandidatesForMob(poll_message, ROLE_PAI, null, FALSE, 100, M, ignore_category) if(LAZYLEN(candidates)) var/mob/C = pick(candidates) diff --git a/code/modules/modular_computers/computers/_modular_computer_shared.dm b/code/modules/modular_computers/computers/_modular_computer_shared.dm index 8ca93e8347..9dde9a0c49 100644 --- a/code/modules/modular_computers/computers/_modular_computer_shared.dm +++ b/code/modules/modular_computers/computers/_modular_computer_shared.dm @@ -44,18 +44,20 @@ . += "It has a slot installed for an intelliCard." var/obj/item/computer_hardware/card_slot/card_slot = get_modular_computer_part(MC_CARD) + var/obj/item/computer_hardware/card_slot/card_slot2 = get_modular_computer_part(MC_CARD2) + var/multiple_slots = istype(card_slot) && istype(card_slot2) if(card_slot) - if(card_slot.stored_card || card_slot.stored_card2) + if(card_slot?.stored_card || card_slot2?.stored_card) var/obj/item/card/id/first_ID = card_slot.stored_card - var/obj/item/card/id/second_ID = card_slot.stored_card2 + var/obj/item/card/id/second_ID = card_slot2.stored_card var/multiple_cards = istype(first_ID) && istype(second_ID) if(user_is_adjacent) - . += "It has two slots for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]." + . += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]." else - . += "It has two slots for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied." + . += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied." . += "Alt-click [src] to eject the identification card[multiple_cards ? "s":""]." else - . += "It has two slots installed for identification cards." + . += "It has [multiple_slots ? "two slots" : "a slot"] installed for identification cards." var/obj/item/computer_hardware/printer/printer_slot = get_modular_computer_part(MC_PRINT) if(printer_slot) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 67c04de13f..63cb1cc5fa 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -4,6 +4,12 @@ /obj/item/modular_computer name = "modular microcomputer" desc = "A small portable microcomputer." + icon = 'icons/obj/computer.dmi' + icon_state = "laptop-open" + var/light_on = FALSE + integrity_failure = 0.5 + max_integrity = 100 + armor = list("melee" = 0, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) var/enabled = 0 // Whether the computer is turned on. var/screen_on = 1 // Whether the computer is active/opened/it's screen is on. @@ -22,8 +28,6 @@ // must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently // If you create a program which is limited to Laptops and Consoles you don't have to add it's icon_state overlay for Tablets too, for example. - icon = 'icons/obj/computer.dmi' - icon_state = "laptop-open" var/icon_state_unpowered = null // Icon state when the computer is turned off. var/icon_state_powered = null // Icon state when the computer is turned on. var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen. @@ -31,20 +35,16 @@ var/max_hardware_size = 0 // Maximal hardware w_class. Tablets/PDAs have 1, laptops 2, consoles 4. var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer. - integrity_failure = 0.5 - max_integrity = 100 - armor = list("melee" = 0, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) - - // Important hardware (must be installed for computer to work) - - // Optional hardware (improves functionality, but is not critical for computer to work) - - var/list/all_components = list() // List of "connection ports" in this computer and the components with which they are plugged + /// List of "connection ports" in this computer and the components with which they are plugged + var/list/all_components = list() + /// Lazy List of extra hardware slots that can be used modularly. + var/list/expansion_bays + /// Number of total expansion bays this computer has available. + var/max_bays = 0 var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with. var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks. var/has_light = FALSE //If the computer has a flashlight/LED light/what-have-you installed - var/light_on = FALSE //If that light is enabled var/comp_light_luminosity = 3 //The brightness of that light var/comp_light_color //The color of that light @@ -71,80 +71,15 @@ physical = null return ..() - -/obj/item/modular_computer/proc/add_verb(var/path) - switch(path) - if(MC_CARD) - verbs += /obj/item/modular_computer/proc/eject_id - if(MC_SDD) - verbs += /obj/item/modular_computer/proc/eject_disk - if(MC_AI) - verbs += /obj/item/modular_computer/proc/eject_card - -/obj/item/modular_computer/proc/remove_verb(path) - switch(path) - if(MC_CARD) - verbs -= /obj/item/modular_computer/proc/eject_id - if(MC_SDD) - verbs -= /obj/item/modular_computer/proc/eject_disk - if(MC_AI) - verbs -= /obj/item/modular_computer/proc/eject_card - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/item/modular_computer/proc/eject_id() - set name = "Eject ID" - set category = "Object" - set src in view(1) - - if(issilicon(usr)) - return - var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - if(usr.canUseTopic(src, BE_CLOSE)) - card_slot.try_eject(null, usr) - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/item/modular_computer/proc/eject_card() - set name = "Eject Intellicard" - set category = "Object" - - if(issilicon(usr)) - return - var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] - if(usr.canUseTopic(src, BE_CLOSE)) - ai_slot.try_eject(null, usr,1) - - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/item/modular_computer/proc/eject_disk() - set name = "Eject Data Disk" - set category = "Object" - - if(issilicon(usr)) - return - - if(usr.canUseTopic(src, BE_CLOSE)) - var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] - if(uninstall_component(portable_drive, usr)) - portable_drive.verb_pickup() - /obj/item/modular_computer/AltClick(mob/user) ..() if(issilicon(user)) return if(user.canUseTopic(src, BE_CLOSE)) + var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2] var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] - var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] - if(portable_drive) - if(uninstall_component(portable_drive, user)) - portable_drive.verb_pickup() - else - if(card_slot && card_slot.try_eject(null, user)) - return - if(ai_slot) - ai_slot.try_eject(null, user) - + return (card_slot2?.try_eject(user) || card_slot?.try_eject(user)) //Try the secondary one first. // Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. /obj/item/modular_computer/GetAccess() @@ -160,19 +95,25 @@ return ..() /obj/item/modular_computer/RemoveID() + var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2] var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - if(!card_slot) - return - return card_slot.RemoveID() + return (card_slot2?.try_eject() || card_slot?.try_eject()) //Try the secondary one first. /obj/item/modular_computer/InsertID(obj/item/inserting_item) var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - if(!card_slot) + var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2] + if(!(card_slot || card_slot2)) + //to_chat(user, "There isn't anywhere you can fit a card into on this computer.") return FALSE + var/obj/item/card/inserting_id = inserting_item.RemoveID() if(!inserting_id) return FALSE - return card_slot.try_insert(inserting_id) + + if((card_slot?.try_insert(inserting_id)) || (card_slot2?.try_insert(inserting_id))) + return TRUE + //to_chat(user, "This computer doesn't have an open card slot.") + return FALSE /obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location) var/mob/M = usr diff --git a/code/modules/modular_computers/computers/item/computer_components.dm b/code/modules/modular_computers/computers/item/computer_components.dm index 3c94a66384..8668b279cf 100644 --- a/code/modules/modular_computers/computers/item/computer_components.dm +++ b/code/modules/modular_computers/computers/item/computer_components.dm @@ -6,6 +6,14 @@ to_chat(user, "This component is too large for \the [src]!") return FALSE + if(H.expansion_hw) + if(LAZYLEN(expansion_bays) >= max_bays) + to_chat(user, "All of the computer's expansion bays are filled.") + return FALSE + if(LAZYACCESS(expansion_bays, H.device_type)) + to_chat(user, "The computer immediately ejects /the [H] and flashes an error: \"Hardware Address Conflict\".") + return FALSE + if(all_components[H.device_type]) to_chat(user, "This computer's hardware slot is already occupied by \the [all_components[H.device_type]].") return FALSE @@ -20,6 +28,8 @@ if(user && !user.transferItemToLoc(H, src)) return FALSE + if(H.expansion_hw) + LAZYSET(expansion_bays, H.device_type, H) all_components[H.device_type] = H to_chat(user, "You install \the [H] into \the [src].") @@ -32,7 +42,9 @@ /obj/item/modular_computer/proc/uninstall_component(obj/item/computer_hardware/H, mob/living/user = null) if(H.holder != src) // Not our component at all. return FALSE + if(H.expansion_hw) + LAZYREMOVE(expansion_bays, H.device_type) all_components.Remove(H.device_type) to_chat(user, "You remove \the [H] from \the [src].") @@ -43,6 +55,7 @@ if(enabled && !use_power()) shutdown_computer() update_icon() + return TRUE // Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index fd017e2b0f..4a985b93c1 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -44,6 +44,33 @@ /obj/item/modular_computer/ui_data(mob/user) var/list/data = get_header_data() data["device_theme"] = device_theme + + data["login"] = list() + var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD] + if(cardholder) + var/obj/item/card/id/stored_card = cardholder.GetID() + if(stored_card) + var/stored_name = stored_card.registered_name + var/stored_title = stored_card.assignment + if(!stored_name) + stored_name = "Unknown" + if(!stored_title) + stored_title = "Unknown" + data["login"] = list( + IDName = stored_name, + IDJob = stored_title, + ) + + data["removable_media"] = list() + if(all_components[MC_SDD]) + data["removable_media"] += "removable storage disk" + var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI] + if(intelliholder?.stored_card) + data["removable_media"] += "intelliCard" + var/obj/item/computer_hardware/card_slot/secondarycardholder = all_components[MC_CARD2] + if(secondarycardholder?.stored_card) + data["removable_media"] += "secondary RFID card" + data["programs"] = list() var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD] for(var/datum/computer_file/program/P in hard_drive.stored_files) @@ -157,6 +184,36 @@ light_color = new_color update_light() return TRUE + + if("PC_Eject_Disk") + var/param = params["name"] + var/mob/user = usr + switch(param) + if("removable storage disk") + var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] + if(!portable_drive) + return + if(uninstall_component(portable_drive, usr)) + user.put_in_hands(portable_drive) + playsound(src, 'sound/machines/card_slide.ogg', 50) + if("intelliCard") + var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI] + if(!intelliholder) + return + if(intelliholder.try_eject(user)) + playsound(src, 'sound/machines/card_slide.ogg', 50) + if("ID") + var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD] + if(!cardholder) + return + cardholder.try_eject(user) + if("secondary RFID card") + var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD2] + if(!cardholder) + return + cardholder.try_eject(user) + + else return diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index 5927d57a0b..ef83140a8f 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -12,6 +12,7 @@ hardware_flag = PROGRAM_LAPTOP max_hardware_size = 2 w_class = WEIGHT_CLASS_NORMAL + max_bays = 4 // No running around with open laptops in hands. item_flags = SLOWS_WHILE_IN_HAND diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm index c79d7a9361..0d7b567877 100644 --- a/code/modules/modular_computers/computers/item/processor.dm +++ b/code/modules/modular_computers/computers/item/processor.dm @@ -8,6 +8,7 @@ icon_state_unpowered = null icon_state_menu = null hardware_flag = 0 + max_bays = 4 var/obj/machinery/modular_computer/machinery_computer = null @@ -18,7 +19,7 @@ machinery_computer = null . = ..() -/obj/item/modular_computer/processor/New(comp) //intentional new probably +/obj/item/modular_computer/processor/New(comp) ..() STOP_PROCESSING(SSobj, src) // Processed by its machine @@ -56,23 +57,5 @@ machinery_computer.update_icon() return -/obj/item/modular_computer/processor/add_verb(path) - switch(path) - if(MC_CARD) - machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_id - if(MC_SDD) - machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_disk - if(MC_AI) - machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_card - -/obj/item/modular_computer/processor/remove_verb(path) - switch(path) - if(MC_CARD) - machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_id - if(MC_SDD) - machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk - if(MC_AI) - machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_card - /obj/item/modular_computer/processor/attack_ghost(mob/user) ui_interact(user) diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index 41a256467f..67e8118c7a 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -5,10 +5,11 @@ icon_state_unpowered = "tablet" icon_state_powered = "tablet" icon_state_menu = "menu" - //worn_icon_state = "tablet" + // worn_icon_state = "tablet" hardware_flag = PROGRAM_TABLET max_hardware_size = 1 w_class = WEIGHT_CLASS_SMALL + max_bays = 3 steel_sheet_cost = 1 slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT has_light = TRUE //LED flashlight! diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm index 7cca8ea5b4..8ac669d2bf 100644 --- a/code/modules/modular_computers/computers/item/tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/tablet_presets.dm @@ -26,11 +26,21 @@ install_component(new /obj/item/computer_hardware/processor_unit/small) install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer)) install_component(hard_drive) + install_component(new /obj/item/computer_hardware/card_slot) install_component(new /obj/item/computer_hardware/network_card) install_component(new /obj/item/computer_hardware/printer/mini) hard_drive.store_file(new /datum/computer_file/program/bounty) //hard_drive.store_file(new /datum/computer_file/program/shipping) +/obj/item/modular_computer/tablet/preset/advanced/atmos/Initialize() //This will be defunct and will be replaced when NtOS PDAs are done + . = ..() + install_component(new /obj/item/computer_hardware/sensorpackage) + +/obj/item/modular_computer/tablet/preset/advanced/command/Initialize() + . = ..() + install_component(new /obj/item/computer_hardware/sensorpackage) + install_component(new /obj/item/computer_hardware/card_slot/secondary) + /// Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink. /obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() . = ..() diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 9d29b23e76..12b2f6d25a 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -1,6 +1,6 @@ /obj/machinery/modular_computer/console/preset // Can be changed to give devices specific hardware - var/_has_id_slot = FALSE + var/_has_second_id_slot = FALSE var/_has_printer = FALSE var/_has_battery = FALSE var/_has_ai = FALSE @@ -11,8 +11,9 @@ return cpu.install_component(new /obj/item/computer_hardware/processor_unit) - if(_has_id_slot) - cpu.install_component(new /obj/item/computer_hardware/card_slot) + cpu.install_component(new /obj/item/computer_hardware/card_slot) + if(_has_second_id_slot) + cpu.install_component(new /obj/item/computer_hardware/card_slot/secondary) if(_has_printer) cpu.install_component(new /obj/item/computer_hardware/printer) if(_has_battery) @@ -59,7 +60,7 @@ console_department = "Command" name = "command console" desc = "A stationary computer. This one comes preloaded with command programs." - _has_id_slot = TRUE + _has_second_id_slot = TRUE _has_printer = TRUE /obj/machinery/modular_computer/console/preset/command/install_programs() @@ -73,7 +74,7 @@ console_department = "Identification" name = "identification console" desc = "A stationary computer. This one comes preloaded with identification modification programs." - _has_id_slot = TRUE + _has_second_id_slot = TRUE _has_printer = TRUE /obj/machinery/modular_computer/console/preset/id/install_programs() diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 6f016ad147..0e6f4d161a 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -75,30 +75,6 @@ add_overlay("bsod") add_overlay("broken") -// Eject ID card from computer, if it has ID slot with card inside. -/obj/machinery/modular_computer/proc/eject_id() - set name = "Eject ID" - set category = "Object" - - if(cpu) - cpu.eject_id() - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/machinery/modular_computer/proc/eject_disk() - set name = "Eject Data Disk" - set category = "Object" - - if(cpu) - cpu.eject_disk() - -/obj/machinery/modular_computer/proc/eject_card() - set name = "Eject Intellicard" - set category = "Object" - set src in view(1) - - if(cpu) - cpu.eject_card() - /obj/machinery/modular_computer/AltClick(mob/user) if(cpu) cpu.AltClick(user) @@ -136,7 +112,7 @@ return . = ..() -/obj/machinery/modular_computer/attackby(var/obj/item/W as obj, mob/user) +/obj/machinery/modular_computer/attackby(obj/item/W as obj, mob/user) if(cpu && !(flags_1 & NODECONSTRUCT_1)) return cpu.attackby(W, user) return ..() @@ -169,5 +145,4 @@ // "Brute" damage mostly damages the casing. /obj/machinery/modular_computer/bullet_act(obj/item/projectile/Proj) if(cpu) - return cpu.bullet_act(Proj) - return ..() + cpu.bullet_act(Proj) diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 12e5ef6e95..6d6a48d567 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -25,8 +25,6 @@ var/ntnet_status = 1 /// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL var/usage_flags = PROGRAM_ALL - /// Optional string that describes what NTNet server/system this program connects to. Used in default logging. - var/network_destination = null /// Whether the program can be downloaded from NTNet. Set to 0 to disable. var/available_on_ntnet = 1 /// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable. @@ -82,10 +80,18 @@ /datum/computer_file/program/proc/process_tick() return 1 -// Check if the user can run program. Only humans can operate computer. Automatically called in run_program() -// User has to wear their ID for ID Scan to work. -// Can also be called manually, with optional parameter being access_to_check to scan the user's ID -/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE) +/** + *Check if the user can run program. Only humans can operate computer. Automatically called in run_program() + *ID must be inserted into a card slot to be read. If the program is not currently installed (as is the case when + *NT Software Hub is checking available software), a list can be given to be used instead. + *Arguments: + *user is a ref of the mob using the device. + *loud is a bool deciding if this proc should use to_chats + *access_to_check is an access level that will be checked against the ID + *transfer, if TRUE and access_to_check is null, will tell this proc to use the program's transfer_access in place of access_to_check + *access can contain a list of access numbers to check against. If access is not empty, it will be used istead of checking any inserted ID. +*/ +/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE, var/list/access) // Defaults to required_access if(!access_to_check) if(transfer && transfer_access) @@ -104,29 +110,24 @@ if(issilicon(user)) return TRUE - if(ishuman(user)) + if(!length(access)) var/obj/item/card/id/D var/obj/item/computer_hardware/card_slot/card_slot - if(computer && card_slot) + if(computer) card_slot = computer.all_components[MC_CARD] - D = card_slot.GetID() - var/mob/living/carbon/human/h = user - var/obj/item/card/id/I = h.get_idcard(TRUE) + D = card_slot?.GetID() - if(!I && !D) + if(!D) if(loud) to_chat(user, "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.") return FALSE + access = D.GetAccess() - if(I) - if(access_to_check in I.GetAccess()) - return TRUE - else if(D) - if(access_to_check in D.GetAccess()) - return TRUE - if(loud) - to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.") - return 0 + if(access_to_check in access) + return TRUE + if(loud) + to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.") + return FALSE // This attempts to retrieve header data for UIs. If implementing completely new device of different type than existing ones // always include the device here in this proc. This proc basically relays the request to whatever is running the program. @@ -139,8 +140,12 @@ // When implementing new program based device, use this to run the program. /datum/computer_file/program/proc/run_program(mob/living/user) if(can_run(user, 1)) - if(requires_ntnet && network_destination) - generate_network_log("Connection opened to [network_destination].") + if(requires_ntnet) + var/obj/item/card/id/ID + var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD] + if(card_holder) + ID = card_holder.GetID() + generate_network_log("Connection opened -- Program ID: [filename] User:[ID?"[ID.registered_name]":"None"]") program_state = PROGRAM_STATE_ACTIVE return 1 return 0 @@ -162,8 +167,12 @@ // Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. /datum/computer_file/program/proc/kill_program(forced = FALSE) program_state = PROGRAM_STATE_KILLED - if(network_destination) - generate_network_log("Connection to [network_destination] closed.") + if(requires_ntnet) + var/obj/item/card/id/ID + var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD] + if(card_holder) + ID = card_holder.GetID() + generate_network_log("Connection closed -- Program ID: [filename] User:[ID?"[ID.registered_name]":"None"]") return 1 /datum/computer_file/program/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm index 3c1daa5af3..1cb74a227b 100644 --- a/code/modules/modular_computers/file_system/program_events.dm +++ b/code/modules/modular_computers/file_system/program_events.dm @@ -2,7 +2,7 @@ // Always include a parent call when overriding an event. // Called when the ID card is removed from computer. ID is removed AFTER this proc. -/datum/computer_file/program/proc/event_idremoved(background, slot) +/datum/computer_file/program/proc/event_idremoved(background) return // Called when the computer fails due to power loss. Override when program wants to specifically react to power loss. diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm index 364ad79737..7ae6dd203a 100644 --- a/code/modules/modular_computers/file_system/programs/airestorer.dm +++ b/code/modules/modular_computers/file_system/programs/airestorer.dm @@ -1,8 +1,8 @@ /datum/computer_file/program/aidiag filename = "aidiag" - filedesc = "AI Integrity Restorer" + filedesc = "NT FRK" program_icon_state = "generic" - extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot." + extended_desc = "Firmware Restoration Kit, capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot." size = 12 requires_ntnet = FALSE usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP @@ -48,7 +48,7 @@ if(computer.all_components[MC_AI]) var/obj/item/computer_hardware/ai_slot/ai_slot = computer.all_components[MC_AI] if(ai_slot && ai_slot.stored_card) - ai_slot.try_eject(0,usr) + ai_slot.try_eject(usr) return TRUE /datum/computer_file/program/aidiag/process_tick() @@ -71,14 +71,19 @@ ai_slot.locked = FALSE restoring = FALSE return - ai_slot.locked =TRUE + ai_slot.locked = TRUE A.adjustOxyLoss(-5, 0)//, FALSE) A.adjustFireLoss(-5, 0)//, FALSE) A.adjustToxLoss(-5, 0) A.adjustBruteLoss(-5, 0) + + // Please don't forget to update health, otherwise the below if statements will probably always fail. A.updatehealth() + if(A.health >= 0 && A.stat == DEAD) A.revive(full_heal = FALSE, admin_revive = FALSE) + cardhold.update_icon() + // Finished restoring if(A.health >= 100) ai_slot.locked = FALSE diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm index 577fad83d0..55dea600e3 100644 --- a/code/modules/modular_computers/file_system/programs/alarm.dm +++ b/code/modules/modular_computers/file_system/programs/alarm.dm @@ -1,11 +1,10 @@ /datum/computer_file/program/alarm_monitor filename = "alarmmonitor" - filedesc = "Alarm Monitor" + filedesc = "Canary" ui_header = "alarm_green.gif" program_icon_state = "alert-green" - extended_desc = "This program provides visual interface for station's alarm system." + extended_desc = "This program provides visual interface for a station's alarm system." requires_ntnet = 1 - network_destination = "alarm monitoring network" size = 5 tgui_id = "NtosStationAlertConsole" var/has_alert = 0 diff --git a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm index 3accb8e02d..aa361d4544 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm @@ -14,7 +14,7 @@ var/assigned = FALSE var/first_load = TRUE -/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user) +/datum/computer_file/program/contract_uplink/run_program(mob/living/user) . = ..(user) /datum/computer_file/program/contract_uplink/ui_act(action, params) diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm index 2ba3d69fe6..4f1c488b9e 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm @@ -10,7 +10,7 @@ tgui_id = "NtosRevelation" var/armed = 0 -/datum/computer_file/program/revelation/run_program(var/mob/living/user) +/datum/computer_file/program/revelation/run_program(mob/living/user) . = ..(user) if(armed) activate() diff --git a/code/modules/modular_computers/file_system/programs/arcade.dm b/code/modules/modular_computers/file_system/programs/arcade.dm index 2503073f9a..87a3f1ec94 100644 --- a/code/modules/modular_computers/file_system/programs/arcade.dm +++ b/code/modules/modular_computers/file_system/programs/arcade.dm @@ -1,10 +1,9 @@ /datum/computer_file/program/arcade - filename = "arcade" - filedesc = "Nanotrasen Micro Arcade" + filename = "dsarcade" + filedesc = "Donksoft Micro Arcade" program_icon_state = "arcade" extended_desc = "This port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets, with thrilling graphics and chilling storytelling." requires_ntnet = FALSE - network_destination = "arcade network" size = 6 tgui_id = "NtosArcade" @@ -25,7 +24,7 @@ /datum/computer_file/program/arcade/proc/game_check(mob/user) sleep(5) - //user?.mind?.adjust_experience(/datum/skill/gaming, 1) No gaming(TM) Yet + // user?.mind?.adjust_experience(/datum/skill/gaming, 1) if(boss_hp <= 0) heads_up = "You have crushed [boss_name]! Rejoice!" playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10) @@ -34,7 +33,7 @@ if(istype(computer)) computer.update_icon() ticket_count += 1 - //user?.mind?.adjust_experience(/datum/skill/gaming, 50) + // user?.mind?.adjust_experience(/datum/skill/gaming, 50) sleep(10) else if(player_hp <= 0 || player_mp <= 0) heads_up = "You have been defeated... how will the station survive?" @@ -43,7 +42,7 @@ program_icon_state = "arcade_off" if(istype(computer)) computer.update_icon() - //user?.mind?.adjust_experience(/datum/skill/gaming, 10) + // user?.mind?.adjust_experience(/datum/skill/gaming, 10) sleep(10) /datum/computer_file/program/arcade/proc/enemy_check(mob/user) @@ -98,8 +97,8 @@ if(computer) printer = computer.all_components[MC_PRINT] - //var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming) - //var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) + // var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming) + // var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) switch(action) if("Attack") var/attackamt = 0 //Spam prevention. @@ -119,8 +118,8 @@ if(pause_state == FALSE) healamt = rand(6,8)// + rand(0, gamerSkill) var/maxPointCost = 3 - //if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN) - // maxPointCost = 2 + // if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN) + // maxPointCost = 2 healcost = rand(1, maxPointCost) pause_state = TRUE heads_up = "You heal for [healamt] damage." diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm index 2df751bebd..c4b9951838 100644 --- a/code/modules/modular_computers/file_system/programs/atmosscan.dm +++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm @@ -1,17 +1,25 @@ /datum/computer_file/program/atmosscan filename = "atmosscan" - filedesc = "Atmospheric Scanner" + filedesc = "AtmoZphere" program_icon_state = "air" extended_desc = "A small built-in sensor reads out the atmospheric conditions around the device." - network_destination = "atmos scan" size = 4 tgui_id = "NtosAtmos" +/datum/computer_file/program/atmosscan/run_program(mob/living/user) + . = ..() + if (!.) + return + if(!computer?.get_modular_computer_part(MC_SENSORS)) //Giving a clue to users why the program is spitting out zeros. + to_chat(user, "\The [computer] flashes an error: \"hardware\\sensorpackage\\startup.bin -- file not found\".") + + /datum/computer_file/program/atmosscan/ui_data(mob/user) var/list/data = get_header_data() var/list/airlist = list() var/turf/T = get_turf(ui_host()) - if(T) + var/obj/item/computer_hardware/sensorpackage/sensors = computer?.get_modular_computer_part(MC_SENSORS) + if(T && sensors?.check_functionality()) var/datum/gas_mixture/environment = T.return_air() var/list/env_gases = environment.get_gases() var/pressure = environment.return_pressure() @@ -24,6 +32,10 @@ if(gas_level > 0) airlist += list(list("name" = "[GLOB.meta_gas_names[id]]", "percentage" = round(gas_level*100, 0.01))) data["AirData"] = airlist + else + data["AirPressure"] = 0 + data["AirTemp"] = 0 + data["AirData"] = list(list()) return data /datum/computer_file/program/atmosscan/ui_act(action, list/params) diff --git a/code/modules/modular_computers/file_system/programs/borg_monitor.dm b/code/modules/modular_computers/file_system/programs/borg_monitor.dm index c2160a0e92..13caab27ef 100644 --- a/code/modules/modular_computers/file_system/programs/borg_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/borg_monitor.dm @@ -1,12 +1,11 @@ /datum/computer_file/program/borg_monitor - filename = "cyborgmonitor" - filedesc = "Cyborg Remote Monitoring" + filename = "siliconnect" + filedesc = "SiliConnect" ui_header = "borg_mon.gif" program_icon_state = "generic" extended_desc = "This program allows for remote monitoring of station cyborgs." requires_ntnet = TRUE transfer_access = ACCESS_ROBOTICS - network_destination = "cyborg remote monitoring" size = 5 tgui_id = "NtosCyborgRemoteMonitor" @@ -32,7 +31,7 @@ var/list/cyborg_data = list( name = R.name, - locked_down = R.lockcharge, + locked_down = R.locked_down, status = R.stat, shell_discon = shell, charge = R.cell ? round(R.cell.percent()) : null, @@ -81,8 +80,8 @@ return ID.registered_name /datum/computer_file/program/borg_monitor/syndicate - filename = "scyborgmonitor" - filedesc = "Mission-Specific Cyborg Remote Monitoring" + filename = "roboverlord" + filedesc = "Roboverlord" ui_header = "borg_mon.gif" program_icon_state = "generic" extended_desc = "This program allows for remote monitoring of mission-assigned cyborgs." @@ -90,7 +89,6 @@ available_on_ntnet = FALSE available_on_syndinet = TRUE transfer_access = null - network_destination = "cyborg remote monitoring" tgui_id = "NtosCyborgRemoteMonitorSyndicate" /datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R) diff --git a/code/modules/modular_computers/file_system/programs/bounty_board.dm b/code/modules/modular_computers/file_system/programs/bounty_board.dm index 46fde84f65..2e7d3cc87f 100644 --- a/code/modules/modular_computers/file_system/programs/bounty_board.dm +++ b/code/modules/modular_computers/file_system/programs/bounty_board.dm @@ -4,7 +4,6 @@ program_icon_state = "bountyboard" extended_desc = "A multi-platform network for placing requests across the station, with payment across the network being possible.." requires_ntnet = TRUE - network_destination = "bounty board interface" size = 10 tgui_id = "NtosRequestKiosk" ///Reference to the currently logged in user. diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index 842d6e2588..6d45914add 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -7,8 +7,8 @@ #define CARDCON_DEPARTMENT_COMMAND "Command" /datum/computer_file/program/card_mod - filename = "cardmod" - filedesc = "ID Card Modification" + filename = "plexagonidwriter" + filedesc = "Plexagon Access Management" program_icon_state = "id" extended_desc = "Program for programming employee ID cards to access parts of the station." transfer_access = ACCESS_HEADS @@ -98,17 +98,19 @@ return TRUE var/obj/item/computer_hardware/card_slot/card_slot + var/obj/item/computer_hardware/card_slot/card_slot2 var/obj/item/computer_hardware/printer/printer if(computer) card_slot = computer.all_components[MC_CARD] + card_slot2 = computer.all_components[MC_CARD2] printer = computer.all_components[MC_PRINT] - if(!card_slot) + if(!card_slot || !card_slot2) return var/mob/user = usr - var/obj/item/card/id/user_id_card = user.get_idcard(FALSE) + var/obj/item/card/id/user_id_card = card_slot.stored_card - var/obj/item/card/id/id_card = card_slot.stored_card + var/obj/item/card/id/target_id_card = card_slot2.stored_card switch(action) if("PRG_authenticate") @@ -129,14 +131,14 @@ return var/contents = {"

    Access Report

    Prepared By: [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]
    - For: [id_card.registered_name ? id_card.registered_name : "Unregistered"]
    + For: [target_id_card.registered_name ? target_id_card.registered_name : "Unregistered"]

    - Assignment: [id_card.assignment]
    + Assignment: [target_id_card.assignment]
    Access:
    "} var/known_access_rights = get_all_accesses() - for(var/A in id_card.access) + for(var/A in target_id_card.access) if(A in known_access_rights) contents += " [get_access_desc(A)]" @@ -148,43 +150,40 @@ computer.visible_message("\The [computer] prints out a paper.") return TRUE if("PRG_eject") - if(!computer || !card_slot) + if(!computer || !card_slot2) return - if(id_card) - GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) - card_slot.try_eject(TRUE, user) + if(target_id_card) + GLOB.data_core.manifest_modify(target_id_card.registered_name, target_id_card.assignment) + return card_slot2.try_eject(user) else var/obj/item/I = user.get_active_held_item() if(istype(I, /obj/item/card/id)) - if(!user.transferItemToLoc(I, computer)) - return - card_slot.stored_card = I - playsound(computer, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - return TRUE + return card_slot2.try_insert(I) + return FALSE if("PRG_terminate") if(!computer || !authenticated) return if(minor) - if(!(id_card.assignment in head_subordinates) && id_card.assignment != "Assistant") + if(!(target_id_card.assignment in head_subordinates) && target_id_card.assignment != "Assistant") return - id_card.access -= get_all_centcom_access() + get_all_accesses() - id_card.assignment = "Unassigned" - id_card.update_label() + target_id_card.access -= get_all_centcom_access() + get_all_accesses() + target_id_card.assignment = "Unassigned" + target_id_card.update_label() playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return TRUE if("PRG_edit") - if(!computer || !authenticated || !id_card) + if(!computer || !authenticated || !target_id_card) return var/new_name = params["name"] if(!new_name) return - id_card.registered_name = new_name - id_card.update_label() + target_id_card.registered_name = new_name + target_id_card.update_label() playsound(computer, "terminal_type", 50, FALSE) return TRUE if("PRG_assign") - if(!computer || !authenticated || !id_card) + if(!computer || !authenticated || !target_id_card) return var/target = params["assign_target"] if(!target) @@ -193,8 +192,8 @@ if(target == "Custom") var/custom_name = params["custom_name"] if(custom_name) - id_card.assignment = custom_name - id_card.update_label() + target_id_card.assignment = custom_name + target_id_card.update_label() else if(minor && !(target in head_subordinates)) return @@ -212,10 +211,10 @@ to_chat(user, "No class exists for this job: [target]") return new_access = job.get_access() - id_card.access -= get_all_centcom_access() + get_all_accesses() - id_card.access |= new_access - id_card.assignment = target - id_card.update_label() + target_id_card.access -= get_all_centcom_access() + get_all_accesses() + target_id_card.access |= new_access + target_id_card.assignment = target + target_id_card.update_label() playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) return TRUE if("PRG_access") @@ -223,22 +222,22 @@ return var/access_type = text2num(params["access_target"]) if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses())) - if(access_type in id_card.access) - id_card.access -= access_type + if(access_type in target_id_card.access) + target_id_card.access -= access_type else - id_card.access |= access_type + target_id_card.access |= access_type playsound(computer, "terminal_type", 50, FALSE) return TRUE if("PRG_grantall") if(!computer || !authenticated || minor) return - id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses()) + target_id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses()) playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) return TRUE if("PRG_denyall") if(!computer || !authenticated || minor) return - id_card.access.Cut() + target_id_card.access.Cut() playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return TRUE if("PRG_grantregion") @@ -247,7 +246,7 @@ var/region = text2num(params["region"]) if(isnull(region)) return - id_card.access |= get_region_accesses(region) + target_id_card.access |= get_region_accesses(region) playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) return TRUE if("PRG_denyregion") @@ -256,7 +255,7 @@ var/region = text2num(params["region"]) if(isnull(region)) return - id_card.access -= get_region_accesses(region) + target_id_card.access -= get_region_accesses(region) playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return TRUE @@ -321,17 +320,17 @@ /datum/computer_file/program/card_mod/ui_data(mob/user) var/list/data = get_header_data() - var/obj/item/computer_hardware/card_slot/card_slot + var/obj/item/computer_hardware/card_slot/card_slot2 var/obj/item/computer_hardware/printer/printer if(computer) - card_slot = computer.all_components[MC_CARD] + card_slot2 = computer.all_components[MC_CARD2] printer = computer.all_components[MC_PRINT] data["station_name"] = station_name() if(computer) - data["have_id_slot"] = !!card_slot + data["have_id_slot"] = !!(card_slot2) data["have_printer"] = !!printer else data["have_id_slot"] = FALSE @@ -340,7 +339,7 @@ data["authenticated"] = authenticated if(computer) - var/obj/item/card/id/id_card = card_slot.stored_card + var/obj/item/card/id/id_card = card_slot2.stored_card data["has_id"] = !!id_card data["id_name"] = id_card ? id_card.name : "-----" if(id_card) diff --git a/code/modules/modular_computers/file_system/programs/cargobounty.dm b/code/modules/modular_computers/file_system/programs/cargobounty.dm index d9bc65c98d..74ac44ade3 100644 --- a/code/modules/modular_computers/file_system/programs/cargobounty.dm +++ b/code/modules/modular_computers/file_system/programs/cargobounty.dm @@ -5,7 +5,6 @@ extended_desc = "A basic interface for supply personnel to check and claim bounties." requires_ntnet = TRUE transfer_access = ACCESS_CARGO - network_destination = "cargo claims interface" size = 10 tgui_id = "NtosBountyConsole" ///cooldown var for printing paper sheets. diff --git a/code/modules/modular_computers/file_system/programs/cargoship.dm b/code/modules/modular_computers/file_system/programs/cargoship.dm index 3ba08a3719..db8d6d9f82 100644 --- a/code/modules/modular_computers/file_system/programs/cargoship.dm +++ b/code/modules/modular_computers/file_system/programs/cargoship.dm @@ -1,9 +1,8 @@ /datum/computer_file/program/shipping filename = "shipping" - filedesc = "Nanotrasen Shipping Scanner" + filedesc = "GrandArk Exporter" program_icon_state = "shipping" extended_desc = "A combination printer/scanner app that enables modular computers to print barcodes for easy scanning and shipping." - network_destination = "ship scanner" size = 6 tgui_id = "NtosShipping" ///Account used for creating barcodes. diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm index a1503ce3a8..4f2688d8f1 100644 --- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm +++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm @@ -1,10 +1,10 @@ /datum/computer_file/program/crew_manifest - filename = "crewmani" - filedesc = "Crew Manifest" + filename = "plexagoncrew" + filedesc = "Plexagon Crew List" program_icon_state = "id" extended_desc = "Program for viewing and printing the current crew manifest" transfer_access = ACCESS_HEADS - requires_ntnet = FALSE + requires_ntnet = TRUE size = 4 tgui_id = "NtosCrewManifest" diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm index bccc6e4dbe..b88b793b66 100644 --- a/code/modules/modular_computers/file_system/programs/jobmanagement.dm +++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm @@ -1,10 +1,10 @@ /datum/computer_file/program/job_management - filename = "job_manage" - filedesc = "Job Manager" + filename = "plexagoncore" + filedesc = "Plexagon HR Core" program_icon_state = "id" extended_desc = "Program for viewing and changing job slot avalibility." transfer_access = ACCESS_HEADS - requires_ntnet = 0 + requires_ntnet = TRUE size = 4 tgui_id = "NtosJobManager" diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm index 6401d6207f..8fbcfd0b01 100644 --- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm @@ -1,14 +1,14 @@ /datum/computer_file/program/ntnetdownload - filename = "ntndownloader" - filedesc = "Software Download Tool" + filename = "ntsoftwarehub" + filedesc = "NT Software Hub" program_icon_state = "generic" extended_desc = "This program allows downloads of software from official NT repositories" - unsendable = 1 - undeletable = 1 + unsendable = TRUE + undeletable = TRUE size = 4 - requires_ntnet = 1 + requires_ntnet = TRUE requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD - available_on_ntnet = 0 + available_on_ntnet = FALSE ui_header = "downloader_finished.gif" tgui_id = "NtosNetDownloader" @@ -125,6 +125,8 @@ if(!istype(my_computer)) return + var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] + var/list/access = card_slot?.GetAccess() var/list/data = get_header_data() @@ -146,7 +148,7 @@ for(var/A in main_repo) var/datum/computer_file/program/P = A // Only those programs our user can run will show in the list - if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename)) + if(!P.can_run(user,transfer = 1, access = access) || hard_drive.find_file_by_name(P.filename)) continue all_entries.Add(list(list( "filename" = P.filename, diff --git a/code/modules/modular_computers/file_system/programs/ntmonitor.dm b/code/modules/modular_computers/file_system/programs/ntmonitor.dm index 7d6d89f32c..bbbde14780 100644 --- a/code/modules/modular_computers/file_system/programs/ntmonitor.dm +++ b/code/modules/modular_computers/file_system/programs/ntmonitor.dm @@ -1,6 +1,6 @@ /datum/computer_file/program/ntnetmonitor - filename = "ntmonitor" - filedesc = "NTNet Diagnostics and Monitoring" + filename = "wirecarp" + filedesc = "WireCarp" //wireshark. program_icon_state = "comm_monitor" extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes" size = 12 diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm index df9b02d8ec..f03ff3f8fd 100644 --- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm @@ -6,7 +6,6 @@ size = 8 requires_ntnet = 1 requires_ntnet_feature = NTNET_COMMUNICATION - network_destination = "NTNRC server" ui_header = "ntnrc_idle.gif" available_on_ntnet = 1 tgui_id = "NtosNetChat" diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm index bd11474858..e87a731a40 100644 --- a/code/modules/modular_computers/file_system/programs/powermonitor.dm +++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm @@ -1,15 +1,14 @@ //normal computer version is located in code\modules\power\monitor.dm, /obj/machinery/computer/monitor /datum/computer_file/program/power_monitor - filename = "powermonitor" - filedesc = "Power Monitor" + filename = "ampcheck" + filedesc = "AmpCheck" program_icon_state = "power_monitor" extended_desc = "This program connects to sensors around the station to provide information about electrical systems" ui_header = "power_norm.gif" transfer_access = ACCESS_ENGINE usage_flags = PROGRAM_CONSOLE requires_ntnet = 0 - network_destination = "power monitoring system" size = 9 tgui_id = "NtosPowerMonitor" diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm index 9b0e09ef99..216365d6ea 100644 --- a/code/modules/modular_computers/file_system/programs/radar.dm +++ b/code/modules/modular_computers/file_system/programs/radar.dm @@ -7,7 +7,6 @@ transfer_access = null available_on_ntnet = FALSE usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET - network_destination = "tracking program" size = 5 tgui_id = "NtosRadar" ///List of trackable entities. Updated by the scan() proc. @@ -207,7 +206,7 @@ ///A program that tracks crew members via suit sensors /datum/computer_file/program/radar/lifeline - filename = "Lifeline" + filename = "lifeline" filedesc = "Lifeline" extended_desc = "This program allows for tracking of crew members via their suit sensors." requires_ntnet = TRUE @@ -252,9 +251,9 @@ //Nuke Disk Finder App// //////////////////////// -///A program that tracks crew members via suit sensors +///A program that tracks nukes and nuclear accessories /datum/computer_file/program/radar/fission360 - filename = "Fission360" + filename = "fission360" filedesc = "Fission360" program_icon_state = "radarsyndicate" extended_desc = "This program allows for tracking of nuclear authorization disks and warheads." @@ -276,8 +275,6 @@ objects = list() for(var/i in GLOB.nuke_list) var/obj/machinery/nuclearbomb/nuke = i - if(!trackable(nuke)) - continue var/list/nukeinfo = list( ref = REF(nuke), @@ -285,9 +282,8 @@ ) objects += list(nukeinfo) var/obj/item/disk/nuclear/disk = locate() in GLOB.poi_list - if(trackable(disk)) - var/list/nukeinfo = list( - ref = REF(disk), - name = disk.name, - ) - objects += list(nukeinfo) + var/list/nukeinfo = list( + ref = REF(disk), + name = "Nuke Auth. Disk", + ) + objects += list(nukeinfo) diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm index 8644ce09b4..c0b82b9c95 100644 --- a/code/modules/modular_computers/file_system/programs/robocontrol.dm +++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm @@ -1,12 +1,11 @@ /datum/computer_file/program/robocontrol - filename = "robocontrol" - filedesc = "Bot Remote Controller" + filename = "botkeeper" + filedesc = "Botkeeper" program_icon_state = "robot" extended_desc = "A remote controller used for giving basic commands to non-sentient robots." transfer_access = ACCESS_ROBOTICS requires_ntnet = TRUE - network_destination = "robotics control network" size = 12 tgui_id = "NtosRoboControl" ///Number of simple robots on-station. @@ -78,7 +77,7 @@ return if(id_card) GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) - card_slot.try_eject(TRUE, current_user) + card_slot.try_eject(current_user) else playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE) return diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm index 32ad102871..e4cf590930 100644 --- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm @@ -1,12 +1,11 @@ /datum/computer_file/program/supermatter_monitor - filename = "smmonitor" - filedesc = "Supermatter Monitoring" + filename = "ntcims" + filedesc = "NT CIMS" ui_header = "smmon_0.gif" program_icon_state = "smmon_0" - extended_desc = "This program connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." + extended_desc = "Crystal Integrity Monitoring System, connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." requires_ntnet = TRUE transfer_access = ACCESS_CONSTRUCTION - network_destination = "supermatter monitoring system" size = 5 tgui_id = "NtosSupermatterMonitor" var/last_status = SUPERMATTER_INACTIVE diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm index b33442f99b..81555340b2 100644 --- a/code/modules/modular_computers/hardware/_hardware.dm +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -10,9 +10,11 @@ // Computer that holds this hardware, if any. var/power_usage = 0 // If the hardware uses extra power, change this. - var/enabled = 1 // If the hardware is turned off set this to 0. - var/critical = 0 // Prevent disabling for important component, like the CPU. - var/can_install = 1 // Prevents direct installation of removable media. + var/enabled = TRUE // If the hardware is turned off set this to 0. + var/critical = FALSE // Prevent disabling for important component, like the CPU. + var/can_install = TRUE // Prevents direct installation of removable media. + var/expansion_hw = FALSE // Hardware that fits into expansion bays. + var/removable = TRUE // Whether the hardware is removable or not. var/damage = 0 // Current damage level var/max_damage = 100 // Maximal damage level. var/damage_malfunction = 20 // "Malfunction" threshold. When damage exceeds this value the hardware piece will semi-randomly fail and do !!FUN!! things @@ -20,7 +22,7 @@ var/malfunction_probability = 10// Chance of malfunction when the component is damaged var/device_type -/obj/item/computer_hardware/New(var/obj/L) +/obj/item/computer_hardware/New(obj/L) ..() pixel_x = rand(-8, 8) pixel_y = rand(-8, 8) @@ -56,7 +58,7 @@ return TRUE // Called on multitool click, prints diagnostic information to the user. -/obj/item/computer_hardware/proc/diagnostics(var/mob/user) +/obj/item/computer_hardware/proc/diagnostics(mob/user) to_chat(user, "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) [damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]") // Handles damage checks @@ -73,7 +75,7 @@ return TRUE // Good to go. -/obj/item/computer_hardware/examine(var/mob/user) +/obj/item/computer_hardware/examine(mob/user) . = ..() if(damage > damage_failure) . += "It seems to be severely damaged!" diff --git a/code/modules/modular_computers/hardware/ai_slot.dm b/code/modules/modular_computers/hardware/ai_slot.dm index 0ad157afcb..c874d786a0 100644 --- a/code/modules/modular_computers/hardware/ai_slot.dm +++ b/code/modules/modular_computers/hardware/ai_slot.dm @@ -5,6 +5,7 @@ icon_state = "card_mini" w_class = WEIGHT_CLASS_SMALL device_type = MC_AI + expansion_hw = TRUE var/obj/item/aicard/stored_card = null var/locked = FALSE @@ -19,12 +20,6 @@ if(stored_card) . += "There appears to be an intelliCard loaded. There appears to be a pinhole protecting a manual eject button. A screwdriver could probably press it." -/obj/item/computer_hardware/ai_slot/on_install(obj/item/modular_computer/M, mob/living/user = null) - M.add_verb(device_type) - -/obj/item/computer_hardware/ai_slot/on_remove(obj/item/modular_computer/M, mob/living/user = null) - M.remove_verb(device_type) - /obj/item/computer_hardware/ai_slot/try_insert(obj/item/I, mob/living/user = null) if(!holder) return FALSE @@ -44,7 +39,7 @@ return TRUE -/obj/item/computer_hardware/ai_slot/try_eject(slot=0,mob/living/user = null,forced = 0) +/obj/item/computer_hardware/ai_slot/try_eject(mob/living/user = null,forced = FALSE) if(!stored_card) to_chat(user, "There is no card in \the [src].") return FALSE diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm index 6e3193abfd..0668248315 100644 --- a/code/modules/modular_computers/hardware/battery_module.dm +++ b/code/modules/modular_computers/hardware/battery_module.dm @@ -21,7 +21,7 @@ /obj/item/computer_hardware/battery/handle_atom_del(atom/A) if(A == battery) - try_eject(0, null, TRUE) + try_eject(forced = TRUE) . = ..() /obj/item/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null) @@ -48,7 +48,7 @@ return TRUE -/obj/item/computer_hardware/battery/try_eject(slot=0, mob/living/user = null, forced = 0) +/obj/item/computer_hardware/battery/try_eject(mob/living/user = null, forced = FALSE) if(!battery) to_chat(user, "There is no power cell connected to \the [src].") return FALSE diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm index 18b423a42e..c243bf7db1 100644 --- a/code/modules/modular_computers/hardware/card_slot.dm +++ b/code/modules/modular_computers/hardware/card_slot.dm @@ -7,13 +7,10 @@ device_type = MC_CARD var/obj/item/card/id/stored_card = null - var/obj/item/card/id/stored_card2 = null /obj/item/computer_hardware/card_slot/handle_atom_del(atom/A) if(A == stored_card) - try_eject(1, null, TRUE) - if(A == stored_card2) - try_eject(2, null, TRUE) + try_eject(null, TRUE) . = ..() /obj/item/computer_hardware/card_slot/Destroy() @@ -21,37 +18,25 @@ return ..() /obj/item/computer_hardware/card_slot/GetAccess() - if(stored_card && stored_card2) // Best of both worlds - return (stored_card.GetAccess() | stored_card2.GetAccess()) - else if(stored_card) - return stored_card.GetAccess() - else if(stored_card2) - return stored_card2.GetAccess() - return ..() + var/list/total_access + if(stored_card) + total_access = stored_card.GetAccess() + var/obj/item/computer_hardware/card_slot/card_slot2 = holder?.all_components[MC_CARD2] //Best of both worlds + if(card_slot2?.stored_card) + total_access |= card_slot2.stored_card.GetAccess() + return total_access /obj/item/computer_hardware/card_slot/GetID() if(stored_card) return stored_card - else if(stored_card2) - return stored_card2 return ..() /obj/item/computer_hardware/card_slot/RemoveID() if(stored_card) . = stored_card - if(!try_eject(1)) + if(!try_eject()) return null return - if(stored_card2) - . = stored_card2 - if(!try_eject(2)) - return null - -/obj/item/computer_hardware/card_slot/on_install(obj/item/modular_computer/M, mob/living/user = null) - M.add_verb(device_type) - -/obj/item/computer_hardware/card_slot/on_remove(obj/item/modular_computer/M, mob/living/user = null) - M.remove_verb(device_type) /obj/item/computer_hardware/card_slot/try_insert(obj/item/I, mob/living/user = null) if(!holder) @@ -60,8 +45,7 @@ if(!istype(I, /obj/item/card/id)) return FALSE - if(stored_card && stored_card2) - to_chat(user, "You try to insert \the [I] into \the [src], but its slots are occupied.") + if(stored_card) return FALSE if(user) if(!user.transferItemToLoc(I, src)) @@ -69,11 +53,8 @@ else I.forceMove(src) - if(!stored_card) - stored_card = I - else - stored_card2 = I - to_chat(user, "You insert \the [I] into \the [src].") + stored_card = I + to_chat(user, "You insert \the [I] into \the [expansion_hw ? "secondary":"primary"] [src].") playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) if(ishuman(user)) var/mob/living/carbon/human/H = user @@ -82,53 +63,58 @@ return TRUE -/obj/item/computer_hardware/card_slot/try_eject(slot=0, mob/living/user = null, forced = 0) - if(!stored_card && !stored_card2) +/obj/item/computer_hardware/card_slot/try_eject(mob/living/user = null, forced = FALSE) + if(!stored_card) to_chat(user, "There are no cards in \the [src].") return FALSE - var/ejected = 0 - if(stored_card && (!slot || slot == 1)) - if(user) - user.put_in_hands(stored_card) - else - stored_card.forceMove(drop_location()) - stored_card = null - ejected++ + if(user) + user.put_in_hands(stored_card) + else + stored_card.forceMove(drop_location()) + stored_card = null - if(stored_card2 && (!slot || slot == 2)) - if(user) - user.put_in_hands(stored_card2) - else - stored_card2.forceMove(drop_location()) - stored_card2 = null - ejected++ + if(holder) + if(holder.active_program) + holder.active_program.event_idremoved(0) - if(ejected) - if(holder) - if(holder.active_program) - holder.active_program.event_idremoved(0, slot) - - for(var/I in holder.idle_threads) - var/datum/computer_file/program/P = I - P.event_idremoved(1, slot) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.sec_hud_set_ID() - to_chat(user, "You remove the card[ejected>1 ? "s" : ""] from \the [src].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - return TRUE - return FALSE + for(var/p in holder.idle_threads) + var/datum/computer_file/program/computer_program = p + computer_program.event_idremoved(1) + if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + human_user.sec_hud_set_ID() + to_chat(user, "You remove the card from \the [src].") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + return TRUE /obj/item/computer_hardware/card_slot/attackby(obj/item/I, mob/living/user) if(..()) return if(I.tool_behaviour == TOOL_SCREWDRIVER) - to_chat(user, "You press down on the manual eject button with \the [I].") - try_eject(0,user) - return + if(stored_card) + to_chat(user, "You press down on the manual eject button with \the [I].") + try_eject(user) + return + swap_slot() + to_chat(user, "You adjust the connecter to fit into [expansion_hw ? "an expansion bay" : "the primary ID bay"].") + +/** + *Swaps the card_slot hardware between using the dedicated card slot bay on a computer, and using an expansion bay. +*/ +/obj/item/computer_hardware/card_slot/proc/swap_slot() + expansion_hw = !expansion_hw + if(expansion_hw) + device_type = MC_CARD2 + else + device_type = MC_CARD /obj/item/computer_hardware/card_slot/examine(mob/user) . = ..() - if(stored_card || stored_card2) + . += "The connector is set to fit into [expansion_hw ? "an expansion bay" : "a computer's primary ID bay"], but can be adjusted with a screwdriver." + if(stored_card) . += "There appears to be something loaded in the card slots." + +/obj/item/computer_hardware/card_slot/secondary + device_type = MC_CARD2 + expansion_hw = TRUE diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index b8b9624388..e5c133de20 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -22,14 +22,14 @@ . = ..() . += "It has [max_capacity] GQ of storage capacity." -/obj/item/computer_hardware/hard_drive/diagnostics(var/mob/user) +/obj/item/computer_hardware/hard_drive/diagnostics(mob/user) ..() // 999 is a byond limit that is in place. It's unlikely someone will reach that many files anyway, since you would sooner run out of space. to_chat(user, "NT-NFS File Table Status: [stored_files.len]/999") to_chat(user, "Storage capacity: [used_capacity]/[max_capacity]GQ") // Use this proc to add file to the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks. -/obj/item/computer_hardware/hard_drive/proc/store_file(var/datum/computer_file/F) +/obj/item/computer_hardware/hard_drive/proc/store_file(datum/computer_file/F) if(!F || !istype(F)) return 0 @@ -52,7 +52,7 @@ return 1 // Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks. -/obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F) +/obj/item/computer_hardware/hard_drive/proc/remove_file(datum/computer_file/F) if(!F || !istype(F)) return 0 @@ -78,7 +78,7 @@ used_capacity = total_size // Checks whether file can be stored on the hard drive. We can only store unique files, so this checks whether we wouldn't get a duplicity by adding a file. -/obj/item/computer_hardware/hard_drive/proc/can_store_file(var/datum/computer_file/F) +/obj/item/computer_hardware/hard_drive/proc/can_store_file(datum/computer_file/F) if(!F || !istype(F)) return 0 @@ -101,7 +101,7 @@ // Tries to find the file by filename. Returns null on failure -/obj/item/computer_hardware/hard_drive/proc/find_file_by_name(var/filename) +/obj/item/computer_hardware/hard_drive/proc/find_file_by_name(filename) if(!check_functionality()) return null diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm index fe1b1879cb..04bf494fe4 100644 --- a/code/modules/modular_computers/hardware/network_card.dm +++ b/code/modules/modular_computers/hardware/network_card.dm @@ -11,7 +11,7 @@ device_type = MC_NET var/static/ntnet_card_uid = 1 -/obj/item/computer_hardware/network_card/diagnostics(var/mob/user) +/obj/item/computer_hardware/network_card/diagnostics(mob/user) ..() to_chat(user, "NIX Unique ID: [identification_id]") to_chat(user, "NIX User Tag: [identification_string]") @@ -22,7 +22,7 @@ if(ethernet) to_chat(user, "OpenEth (Physical Connection) - Physical network connection port") -/obj/item/computer_hardware/network_card/New(var/l) +/obj/item/computer_hardware/network_card/New(l) ..() identification_id = ntnet_card_uid++ @@ -31,7 +31,7 @@ return "[identification_string] (NID [identification_id])" // 0 - No signal, 1 - Low signal, 2 - High signal. 3 - Wired Connection -/obj/item/computer_hardware/network_card/proc/get_signal(var/specific_action = 0) +/obj/item/computer_hardware/network_card/proc/get_signal(specific_action = 0) if(!holder) // Hardware is not installed in anything. No signal. How did this even get called? return 0 diff --git a/code/modules/modular_computers/hardware/portable_disk.dm b/code/modules/modular_computers/hardware/portable_disk.dm index b5a957be04..89b0382e86 100644 --- a/code/modules/modular_computers/hardware/portable_disk.dm +++ b/code/modules/modular_computers/hardware/portable_disk.dm @@ -8,12 +8,8 @@ max_capacity = 16 device_type = MC_SDD -/obj/item/computer_hardware/hard_drive/portable/on_install(obj/item/modular_computer/M, mob/living/user = null) - M.add_verb(device_type) - -/obj/item/computer_hardware/hard_drive/portable/on_remove(obj/item/modular_computer/M, mob/living/user = null) - ..() - M.remove_verb(device_type) +/obj/item/computer_hardware/hard_drive/portable/on_remove(obj/item/modular_computer/MC, mob/user) + return //this is a floppy disk, let's not shut the computer down when it gets pulled out. /obj/item/computer_hardware/hard_drive/portable/install_default_programs() return // Empty by default diff --git a/code/modules/modular_computers/hardware/printer.dm b/code/modules/modular_computers/hardware/printer.dm index ebe40c1922..3bd5946435 100644 --- a/code/modules/modular_computers/hardware/printer.dm +++ b/code/modules/modular_computers/hardware/printer.dm @@ -5,6 +5,7 @@ icon_state = "printer" w_class = WEIGHT_CLASS_NORMAL device_type = MC_PRINT + expansion_hw = TRUE var/stored_paper = 20 var/max_paper = 30 diff --git a/code/modules/modular_computers/hardware/sensor_package.dm b/code/modules/modular_computers/hardware/sensor_package.dm new file mode 100644 index 0000000000..c0363bc809 --- /dev/null +++ b/code/modules/modular_computers/hardware/sensor_package.dm @@ -0,0 +1,8 @@ +//This item doesn't do much on its own, but is required by apps such as AtmoZphere. +/obj/item/computer_hardware/sensorpackage + name = "sensor package" + desc = "An integrated sensor package allowing a computer to take readings from the environment. Required by certain programs." + icon_state = "servo" + w_class = WEIGHT_CLASS_TINY + device_type = MC_SENSORS + expansion_hw = TRUE diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index a8d30bad21..83bb057d66 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -52,6 +52,7 @@ var/obj/item/computer_hardware/battery/battery_module = null if(fabricate) fabricated_laptop = new /obj/item/modular_computer/laptop/buildable(src) + fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot) fabricated_laptop.install_component(new /obj/item/computer_hardware/battery) battery_module = fabricated_laptop.all_components[MC_CELL] total_price = 99 @@ -107,7 +108,7 @@ if(dev_card) total_price += 199 if(fabricate) - fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot) + fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot/secondary) return total_price else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this. @@ -116,6 +117,7 @@ fabricated_tablet = new(src) fabricated_tablet.install_component(new /obj/item/computer_hardware/battery) fabricated_tablet.install_component(new /obj/item/computer_hardware/processor_unit/small) + fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot) battery_module = fabricated_tablet.all_components[MC_CELL] total_price = 199 switch(dev_battery) @@ -154,11 +156,11 @@ if(dev_printer) total_price += 99 if(fabricate) - fabricated_tablet.install_component(new/obj/item/computer_hardware/printer) + fabricated_tablet.install_component(new/obj/item/computer_hardware/printer/mini) if(dev_card) total_price += 199 if(fabricate) - fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot) + fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot/secondary) return total_price return FALSE @@ -257,7 +259,7 @@ say("Insufficient credits on card to purchase!") return credits += target_credits - say("[target_credits] cr has been deposited from your account.") + say("[target_credits] cr have been withdrawn from your account.") return return ..() diff --git a/code/modules/newscaster/newscaster_machine.dm b/code/modules/newscaster/newscaster_machine.dm index 470b34e82c..7e515bf0f5 100644 --- a/code/modules/newscaster/newscaster_machine.dm +++ b/code/modules/newscaster/newscaster_machine.dm @@ -340,7 +340,6 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="Return" var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[unit_no]", 400, 600) popup.set_content(dat) - popup.set_title_image(human_or_robot_user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/newscaster/Topic(href, href_list) diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm new file mode 100644 index 0000000000..dc8f172069 --- /dev/null +++ b/code/modules/paperwork/carbonpaper.dm @@ -0,0 +1,45 @@ +/obj/item/paper/carbon + name = "sheet of carbon" + icon_state = "paper_stack" + item_state = "paper" + // inhand_icon_state = "paper" + show_written_words = FALSE + var/copied = FALSE + var/iscopy = FALSE + +/obj/item/paper/carbon/update_icon_state() + if(iscopy) + icon_state = "cpaper" + else if(copied) + icon_state = "paper" + else + icon_state = "paper_stack" + if(info) + icon_state = "[icon_state]_words" + +/obj/item/paper/carbon/proc/removecopy(mob/living/user) + if(!copied) + var/obj/item/paper/carbon/C = src + var/copycontents = C.info + var/obj/item/paper/carbon/Copy = new /obj/item/paper/carbon(user.loc) + + if(info) + copycontents = replacetext(copycontents, "" + Copy.name = "Copy - [C.name]" + to_chat(user, "You tear off the carbon-copy!") + C.copied = TRUE + Copy.iscopy = TRUE + Copy.update_icon_state() + C.update_icon_state() + user.put_in_hands(Copy) + else + to_chat(user, "There are no more carbon copies attached to this paper!") + +/obj/item/paper/carbon/on_attack_hand(mob/living/user) + if(loc == user && user.is_holding(src)) + removecopy(user) + return + return ..() diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index 1a93661c76..5b576a2438 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -3,6 +3,8 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "clipboard" item_state = "clipboard" + // inhand_icon_state = "clipboard" + // worn_icon_state = "clipboard" throwforce = 0 w_class = WEIGHT_CLASS_SMALL throw_speed = 3 @@ -34,7 +36,6 @@ . += "clipboard_pen" . += "clipboard_over" - /obj/item/clipboard/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/paper)) if(!user.transferItemToLoc(W, src)) @@ -92,14 +93,14 @@ to_chat(usr, "You slot [W] into [src].") if(href_list["write"]) - var/obj/item/P = locate(href_list["write"]) - if(istype(P) && P.loc == src) + var/obj/item/P = locate(href_list["write"]) in src + if(istype(P)) if(usr.get_active_held_item()) P.attackby(usr.get_active_held_item(), usr) if(href_list["remove"]) - var/obj/item/P = locate(href_list["remove"]) - if(istype(P) && P.loc == src) + var/obj/item/P = locate(href_list["remove"]) in src + if(istype(P)) P.forceMove(usr.loc) usr.put_in_hands(P) if(P == toppaper) @@ -111,13 +112,13 @@ toppaper = null if(href_list["read"]) - var/obj/item/paper/P = locate(href_list["read"]) - if(istype(P) && P.loc == src) + var/obj/item/paper/P = locate(href_list["read"]) in src + if(istype(P)) usr.examinate(P) if(href_list["top"]) - var/obj/item/P = locate(href_list["top"]) - if(istype(P) && P.loc == src) + var/obj/item/P = locate(href_list["top"]) in src + if(istype(P)) toppaper = P to_chat(usr, "You move [P.name] to the top.") diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index b8f2c95762..390cd0cf83 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -35,7 +35,7 @@ . = ..() if(mapload) for(var/obj/item/I in loc) - if(istype(I, /obj/item/paper) || istype(I, /obj/item/folder) || istype(I, /obj/item/photo)) + if(I.w_class < WEIGHT_CLASS_NORMAL) //there probably shouldn't be anything placed ontop of filing cabinets in a map that isn't meant to go in them I.forceMove(src) /obj/structure/filingcabinet/deconstruct(disassembled = TRUE) @@ -46,7 +46,12 @@ qdel(src) /obj/structure/filingcabinet/attackby(obj/item/P, mob/user, params) - if(istype(P, /obj/item/paper) || istype(P, /obj/item/folder) || istype(P, /obj/item/photo) || istype(P, /obj/item/documents)) + if(P.tool_behaviour == TOOL_WRENCH && user.a_intent != INTENT_HELP) + to_chat(user, "You begin to [anchored ? "unwrench" : "wrench"] [src].") + if(P.use_tool(src, user, 20, volume=50)) + to_chat(user, "You successfully [anchored ? "unwrench" : "wrench"] [src].") + anchored = !anchored + else if(P.w_class < WEIGHT_CLASS_NORMAL) if(!user.transferItemToLoc(P, src)) return to_chat(user, "You put [P] in [src].") @@ -54,11 +59,6 @@ sleep(5) icon_state = initial(icon_state) updateUsrDialog() - else if(istype(P, /obj/item/wrench)) - to_chat(user, "You begin to [anchored ? "unwrench" : "wrench"] [src].") - if(P.use_tool(src, user, 20, volume=50)) - to_chat(user, "You successfully [anchored ? "unwrench" : "wrench"] [src].") - anchored = !anchored else if(user.a_intent != INTENT_HARM) to_chat(user, "You can't put [P] in [src]!") else @@ -67,9 +67,6 @@ /obj/structure/filingcabinet/ui_interact(mob/user) . = ..() - if(isobserver(user)) - return - if(contents.len <= 0) to_chat(user, "[src] is empty.") return @@ -100,16 +97,17 @@ to_chat(user, "You find nothing in [src].") /obj/structure/filingcabinet/Topic(href, href_list) + if(!usr.canUseTopic(src, BE_CLOSE, ismonkey(usr))) + return if(href_list["retrieve"]) usr << browse("", "window=filingcabinet") // Close the menu - var/obj/item/P = locate(href_list["retrieve"])//contents[retrieveindex] - if(istype(P) && P.loc == src && in_range(src, usr)) + var/obj/item/P = locate(href_list["retrieve"]) in src //contents[retrieveindex] + if(istype(P) && in_range(src, usr)) usr.put_in_hands(P) updateUsrDialog() icon_state = "[initial(icon_state)]-open" - sleep(5) - icon_state = initial(icon_state) + addtimer(VARSET_CALLBACK(src, icon_state, initial(icon_state)), 5) /* @@ -170,6 +168,7 @@ virgin = 0 //tabbing here is correct- it's possible for people to try and use it //before the records have been generated, so we do this inside the loop. +//ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/filingcabinet/medical/on_attack_hand() populate() . = ..() diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index c32afab342..305099d115 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -33,7 +33,10 @@ if(contents.len) . += "folder_paper" + /obj/item/folder/attackby(obj/item/W, mob/user, params) + if(burn_paper_product_attackby_check(W, user)) + return if(istype(W, /obj/item/paper) || istype(W, /obj/item/photo) || istype(W, /obj/item/documents)) if(!user.transferItemToLoc(W, src)) return @@ -43,11 +46,14 @@ if(!user.is_literate()) to_chat(user, "You scribble illegibly on the cover of [src]!") return + var/inputvalue = stripped_input(user, "What would you like to label the folder?", "Folder Labelling", "", MAX_NAME_LEN) + if(!inputvalue) return + if(user.canUseTopic(src, BE_CLOSE)) - name = "folder - '[inputvalue]'" + name = "folder[(inputvalue ? " - '[inputvalue]'" : null)]" /obj/item/folder/Destroy() @@ -76,14 +82,14 @@ if(usr.contents.Find(src)) if(href_list["remove"]) - var/obj/item/I = locate(href_list["remove"]) - if(istype(I) && I.loc == src) + var/obj/item/I = locate(href_list["remove"]) in src + if(istype(I)) I.forceMove(usr.loc) usr.put_in_hands(I) if(href_list["read"]) - var/obj/item/I = locate(href_list["read"]) - if(istype(I) && I.loc == src) + var/obj/item/I = locate(href_list["read"]) in src + if(istype(I)) usr.examinate(I) //Update everything diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index d054e5ff12..da9fdc4ca4 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -1,9 +1,10 @@ /obj/item/hand_labeler name = "hand labeler" - desc = "A combined label printer and applicator in a portable device, designed to be easy to operate and use." + desc = "A combined label printer, applicator, and remover, all in a single portable device. Designed to be easy to operate and use." icon = 'icons/obj/bureaucracy.dmi' icon_state = "labeler0" item_state = "flight" + // inhand_icon_state = "flight" var/label = null var/labels_left = 30 var/mode = 0 @@ -55,9 +56,10 @@ to_chat(user, "You can't label creatures!") // use a collar return - user.visible_message("[user] labels [A] as [label].", \ - "You label [A] as [label].") - A.name = "[A.name] ([label])" + user.visible_message("[user] labels [A] with \"[label]\".", \ + "You label [A] with \"[label]\".") + A.AddComponent(/datum/component/label, label) + // playsound(A, 'sound/items/handling/component_pickup.ogg', 20, TRUE) labels_left-- @@ -90,7 +92,9 @@ name = "cyborg-hand labeler" /obj/item/hand_labeler/borg/afterattack(atom/A, mob/user, proximity) - . = ..(A, user, proximity) + . = ..() + if(!proximity) + return if(!iscyborg(user)) return @@ -114,6 +118,7 @@ desc = "A roll of paper. Use it on a hand labeler to refill it." icon_state = "labeler_refill" item_state = "electropack" + // inhand_icon_state = "electropack" lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' w_class = WEIGHT_CLASS_TINY diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 5d842ef11a..20ec678e45 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -11,41 +11,6 @@ #define MODE_WRITING 1 #define MODE_STAMPING 2 -/** - * This is a custom ui state. All it really does is keep track of pen - * being used and if they are editing it or not. This way we can keep - * the data with the ui rather than on the paper - */ -/datum/ui_state/default/paper_state - /// What edit mode we are in and who is - /// writing on it right now - var/edit_mode = MODE_READING - /// Setup for writing to a sheet - var/pen_color = "black" - var/pen_font = "" - var/is_crayon = FALSE - /// Setup for stamping a sheet - // Why not the stamp obj? I have no idea - // what happens to states out of scope so - // don't want to put instances in this - var/stamp_icon_state = "" - var/stamp_name = "" - var/stamp_class = "" - -/datum/ui_state/default/paper_state/proc/copy_from(datum/ui_state/default/paper_state/from) - switch(from.edit_mode) - if(MODE_READING) - edit_mode = MODE_READING - if(MODE_WRITING) - edit_mode = MODE_WRITING - pen_color = from.pen_color - pen_font = from.pen_font - is_crayon = from.is_crayon - if(MODE_STAMPING) - edit_mode = MODE_STAMPING - stamp_icon_state = from.stamp_icon_state - stamp_class = from.stamp_class - stamp_name = from.stamp_name /** * Paper is now using markdown (like in github pull notes) for ALL rendering @@ -58,6 +23,9 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "paper" item_state = "paper" + // inhand_icon_state = "paper" + // worn_icon_state = "paper" + // custom_fire_overlay = "paper_onfire_overlay" throwforce = 0 w_class = WEIGHT_CLASS_TINY throw_range = 1 @@ -80,34 +48,19 @@ var/list/stamps /// Positioning for the stamp in tgui var/list/stamped /// Overlay info - /// This REALLY should be a componenet. Basicly used during, april fools - /// to honk at you - var/rigged = 0 - var/spam_flag = 0 - var/contact_poison // Reagent ID to transfer on contact var/contact_poison_volume = 0 - // Ok, so WHY are we caching the ui's? - // Since we are not using autoupdate we - // need some way to update the ui's of - // other people looking at it and if - // its been updated. Yes yes, lame - // but canot be helped. However by - // doing it this way, we can see - // live updates and have multipule - // people look at it - var/list/viewing_ui = list() - /// When the sheet can be "filled out" /// This is an associated list var/list/form_fields = list() var/field_counter = 1 /obj/item/paper/Destroy() - close_all_ui() stamps = null stamped = null + form_fields = null + stamped = null . = ..() /** @@ -162,7 +115,7 @@ set category = "Object" set src in usr - if(usr.incapacitated() || !usr.is_literate()) + if(!usr.can_read(src) || usr.incapacitated(TRUE, TRUE) || (isobserver(usr) && !IsAdminGhost(usr))) return if(ishuman(usr)) var/mob/living/carbon/human/H = usr @@ -180,18 +133,6 @@ user.visible_message("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...") return (BRUTELOSS) -/// ONLY USED FOR APRIL FOOLS -/obj/item/paper/proc/reset_spamflag() - spam_flag = FALSE - -/obj/item/paper/attack_self(mob/user) - if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS])) - if(!spam_flag) - spam_flag = TRUE - playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE) - addtimer(CALLBACK(src, .proc/reset_spamflag), 20) - . = ..() - /obj/item/paper/proc/clearpaper() info = "" stamps = null @@ -199,28 +140,39 @@ cut_overlays() update_icon_state() -/obj/item/paper/examine_more(mob/user) - ui_interact(user) - return list("You try to read [src]...") +/obj/item/paper/examine(mob/user) + . = ..() + if(!in_range(user, src) && !isobserver(user)) + . += "You're too far away to read it!" + return + if(user.can_read(src)) + ui_interact(user) + return + . += "You cannot read it!" + +/obj/item/paper/ui_status(mob/user,/datum/ui_state/state) + // Are we on fire? Hard ot read if so + if(resistance_flags & ON_FIRE) + return UI_CLOSE + if(!in_range(user,src)) + return UI_CLOSE + if(user.incapacitated(TRUE, TRUE) || (isobserver(user) && !IsAdminGhost(user))) + return UI_UPDATE + // Even harder to read if your blind...braile? humm + // .. or if you cannot read + if(!user.can_read(src)) + return UI_CLOSE + if(in_contents_of(/obj/machinery/door/airlock)) + return UI_INTERACTIVE + return ..() + + /obj/item/paper/can_interact(mob/user) - if(!..()) - return FALSE - // Are we on fire? Hard ot read if so - if(resistance_flags & ON_FIRE) - return FALSE - // Even harder to read if your blind...braile? humm - if(user.is_blind()) - return FALSE - // checks if the user can read. - return user.can_read(src) + if(in_contents_of(/obj/machinery/door/airlock)) + return TRUE + return ..() -/** - * This creates the ui, since we are using a custom state but not much else - * just makes it easyer to make it. - */ -/obj/item/paper/proc/create_ui(mob/user, datum/ui_state/default/paper_state/state) - ui_interact(user, state = state) /obj/item/proc/burn_paper_product_attackby_check(obj/item/I, mob/living/user, bypass_clumsy) var/ignition_message = I.ignition_effect(src, user) @@ -244,49 +196,22 @@ /obj/item/paper/attackby(obj/item/P, mob/living/user, params) if(burn_paper_product_attackby_check(P, user)) - close_all_ui() + SStgui.close_uis(src) return if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) if(length(info) >= MAX_PAPER_LENGTH) // Sheet must have less than 1000 charaters to_chat(user, "This sheet of paper is full!") return - - var/datum/ui_state/default/paper_state/state = new - state.edit_mode = MODE_WRITING - // should a crayon be in the same subtype as a pen? How about a brush or charcoal? - // TODO: Convert all writing stuff to one type, /obj/item/art_tool maybe? - state.is_crayon = istype(P, /obj/item/toy/crayon); - if(state.is_crayon) - var/obj/item/toy/crayon/PEN = P - state.pen_font = CRAYON_FONT - state.pen_color = PEN.paint_color - else - var/obj/item/pen/PEN = P - state.pen_font = PEN.font - state.pen_color = PEN.colour - - create_ui(user, state) + ui_interact(user) return else if(istype(P, /obj/item/stamp)) - - var/datum/ui_state/default/paper_state/state = new - state.edit_mode = MODE_STAMPING // we are read only becausse the sheet is full - state.stamp_icon_state = P.icon_state - state.stamp_name = P.name - - var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper) - state.stamp_class = sheet.icon_class_name(P.icon_state) - to_chat(user, "You ready your stamp over the paper! ") - - create_ui(user, state) + ui_interact(user) return /// Normaly you just stamp, you don't need to read the thing else // cut paper? the sky is the limit! - var/datum/ui_state/default/paper_state/state = new - state.edit_mode = MODE_READING - create_ui(user, state) // The other ui will be created with just read mode outside of this + ui_interact(user) // The other ui will be created with just read mode outside of this return ..() @@ -301,68 +226,64 @@ get_asset_datum(/datum/asset/spritesheet/simple/paper), ) -/obj/item/paper/ui_interact(mob/user, datum/tgui/ui, - datum/ui_state/default/paper_state/state) - // Update the state - ui = ui || SStgui.get_open_ui(user, src) - if(ui && state) - var/datum/ui_state/default/paper_state/current_state = ui.state - current_state.copy_from(state) +/obj/item/paper/ui_interact(mob/user, datum/tgui/ui) // Update the UI ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "PaperSheet", name) - state = new - ui.set_state(state) - ui.set_autoupdate(FALSE) - viewing_ui[user] = ui ui.open() -/obj/item/paper/ui_close(mob/user) - /// close the editing window and change the mode - viewing_ui[user] = null - . = ..() -// Again, we have to do this as autoupdate is off -/obj/item/paper/proc/update_all_ui() - for(var/datum/tgui/ui in viewing_ui) - ui.process(force = TRUE) +/obj/item/paper/ui_static_data(mob/user) + . = list() + .["text"] = info + .["max_length"] = MAX_PAPER_LENGTH + .["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set + .["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling? + .["stamps"] = stamps + -// Again, we have to do this as autoupdate is off -/obj/item/paper/proc/close_all_ui() - for(var/datum/tgui/ui in viewing_ui) - ui.close() - viewing_ui = list() /obj/item/paper/ui_data(mob/user) var/list/data = list() - - var/datum/tgui/ui = viewing_ui[user] - var/datum/ui_state/default/paper_state/state = ui.state - - // Should all this go in static data and just do a forced update? - data["text"] = info - data["max_length"] = MAX_PAPER_LENGTH - data["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling? - data["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set - data["stamps"] = stamps - - data["edit_mode"] = state.edit_mode - data["edit_usr"] = "[ui.user]"; - - // pen info for editing - data["is_crayon"] = state.is_crayon - data["pen_font"] = state.pen_font - data["pen_color"] = state.pen_color - // stamping info for..stamping - data["stamp_class"] = state.stamp_class - + var/obj/O = user.get_active_held_item() + if(istype(O, /obj/item/toy/crayon)) + var/obj/item/toy/crayon/PEN = O + data["pen_font"] = CRAYON_FONT + data["pen_color"] = PEN.paint_color + data["edit_mode"] = MODE_WRITING + data["is_crayon"] = TRUE + data["stamp_class"] = "FAKE" + data["stamp_icon_state"] = "FAKE" + else if(istype(O, /obj/item/pen)) + var/obj/item/pen/PEN = O + data["pen_font"] = PEN.font + data["pen_color"] = PEN.colour + data["edit_mode"] = MODE_WRITING + data["is_crayon"] = FALSE + data["stamp_class"] = "FAKE" + data["stamp_icon_state"] = "FAKE" + else if(istype(O, /obj/item/stamp)) + var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper) + data["stamp_icon_state"] = O.icon_state + data["stamp_class"] = sheet.icon_class_name(O.icon_state) + data["edit_mode"] = MODE_STAMPING + data["pen_font"] = "FAKE" + data["pen_color"] = "FAKE" + data["is_crayon"] = FALSE + else + data["edit_mode"] = MODE_READING + data["pen_font"] = "FAKE" + data["pen_color"] = "FAKE" + data["is_crayon"] = FALSE + data["stamp_icon_state"] = "FAKE" + data["stamp_class"] = "FAKE" data["field_counter"] = field_counter data["form_fields"] = form_fields return data -/obj/item/paper/ui_act(action, params, datum/tgui/ui, datum/ui_state/default/paper_state/state) +/obj/item/paper/ui_act(action, params,datum/tgui/ui) if(..()) return switch(action) @@ -370,34 +291,33 @@ var/stamp_x = text2num(params["x"]) var/stamp_y = text2num(params["y"]) var/stamp_r = text2num(params["r"]) // rotation in degrees - + var/stamp_icon_state = params["stamp_icon_state"] + var/stamp_class = params["stamp_class"] if (isnull(stamps)) - stamps = new/list() + stamps = list() if(stamps.len < MAX_PAPER_STAMPS) // I hate byond when dealing with freaking lists - stamps += list(list(state.stamp_class, stamp_x, stamp_y,stamp_r)) /// WHHHHY + stamps[++stamps.len] = list(stamp_class, stamp_x, stamp_y, stamp_r) /// WHHHHY /// This does the overlay stuff if (isnull(stamped)) - stamped = new/list() + stamped = list() if(stamped.len < MAX_PAPER_STAMPS_OVERLAYS) - var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[state.stamp_icon_state]") + var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[stamp_icon_state]") stampoverlay.pixel_x = rand(-2, 2) stampoverlay.pixel_y = rand(-3, 2) add_overlay(stampoverlay) - LAZYADD(stamped, state.stamp_icon_state) + LAZYADD(stamped, stamp_icon_state) - ui.user.visible_message("[ui.user] stamps [src] with [state.stamp_name]!", "You stamp [src] with [state.stamp_name]!") + update_static_data(usr,ui) + ui.user.visible_message("[ui.user] stamps [src] with [stamp_class]!", "You stamp [src] with [stamp_class]!") else to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!")) - - update_all_ui() . = TRUE if("save") var/in_paper = params["text"] var/paper_len = length(in_paper) - var/list/fields = params["form_fields"] field_counter = params["field_counter"] ? text2num(params["field_counter"]) : field_counter if(paper_len > MAX_PAPER_LENGTH) @@ -413,14 +333,10 @@ if(info != in_paper) to_chat(ui.user, "You have added to your paper masterpiece!"); info = in_paper - - for(var/key in fields) - form_fields[key] = fields[key]; + update_static_data(usr,ui) - update_all_ui() update_icon() - . = TRUE /** diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm index 3937720f74..a3b9b23141 100644 --- a/code/modules/paperwork/paper_cutter.dm +++ b/code/modules/paperwork/paper_cutter.dm @@ -26,11 +26,11 @@ var/obj/item/bodypart/BP = C.get_bodypart(BODY_ZONE_HEAD) if(BP) BP.drop_limb() - playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + playsound(loc, pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg'),50, TRUE, -1) return (BRUTELOSS) else user.visible_message("[user] repeatedly bashes [src.name] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) + playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1) return (BRUTELOSS) @@ -42,11 +42,12 @@ if(storedpaper) . += "paper" + /obj/item/papercutter/attackby(obj/item/P, mob/user, params) if(istype(P, /obj/item/paper) && !storedpaper) if(!user.transferItemToLoc(P, src)) return - playsound(loc, "pageturn", 60, 1) + playsound(loc, "pageturn", 60, TRUE) to_chat(user, "You place [P] in [src].") storedpaper = P update_icon() @@ -59,17 +60,17 @@ storedcutter = P update_icon() return - if(istype(P, /obj/item/screwdriver) && storedcutter) + if(P.tool_behaviour == TOOL_SCREWDRIVER && storedcutter) P.play_tool_sound(src) to_chat(user, "[storedcutter] has been [cuttersecured ? "unsecured" : "secured"].") cuttersecured = !cuttersecured return ..() -/obj/item/papercutter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) +/obj/item/papercutter/on_attack_hand(mob/user) add_fingerprint(user) if(!storedcutter) - to_chat(user, "The cutting blade is gone! You can't use [src] now.") + to_chat(user, "The cutting blade is gone! You can't use [src] now.") return if(!cuttersecured) @@ -79,7 +80,7 @@ update_icon() if(storedpaper) - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1) + playsound(src.loc, 'sound/weapons/slash.ogg', 50, TRUE) to_chat(user, "You neatly cut [storedpaper].") storedpaper = null qdel(storedpaper) @@ -88,6 +89,7 @@ update_icon() /obj/item/papercutter/MouseDrop(atom/over_object) + . = ..() var/mob/M = usr if(M.incapacitated() || !Adjacent(M)) return @@ -98,10 +100,6 @@ else if(istype(over_object, /obj/screen/inventory/hand)) var/obj/screen/inventory/hand/H = over_object M.putItemFromInventoryInHandIfPossible(src, H.held_index) - - else - . = ..() - add_fingerprint(M) /obj/item/paperslip @@ -112,6 +110,12 @@ resistance_flags = FLAMMABLE max_integrity = 50 +/obj/item/paperslip/attackby(obj/item/I, mob/living/user, params) + if(burn_paper_product_attackby_check(I, user)) + return + return ..() + + /obj/item/paperslip/Initialize() . = ..() pixel_x = rand(-5, 5) @@ -124,5 +128,6 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "cutterblade" item_state = "knife" + // inhand_icon_state = "knife" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi' diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm index 392eba5f56..5d6d3d45e8 100644 --- a/code/modules/paperwork/paper_premade.dm +++ b/code/modules/paperwork/paper_premade.dm @@ -4,53 +4,22 @@ /obj/item/paper/fluff/sop name = "paper- 'Standard Operating Procedure'" - info = {" -Alert Levels: -* Blue - Emergency - * Caused by fire - * Caused by manual interaction - * Action: Close all fire doors. These can only be opened by resetting the alarm -* Red- Ejection/Self Destruct - * Caused by module operating computer. - * Action: After the specified time the module will eject completely. -Engine Maintenance Instructions: -1. Shut off ignition systems: -2. Activate internal power -3. Activate orbital balance matrix -4. Remove volatile liquids from area -5. Wear a fire suit -6. After Decontaminate Visit medical examiner -Toxin Laboratory Procedure: -1. Wear a gas mask regardless -2. Get an oxygen tank. -3. Activate internal atmosphere -4. After Decontaminate Visit medical examiner -Disaster Procedure: -Fire: -1. Activate sector fire alarm. -2. Move to a safe area. -3. Get a fire suit -* After: - 1. Assess Damage - 2. Repair damages - 3. If needed, Evacuate -Meteor Shower: -1. Activate fire alarm -2. Move to the back of ship -* After - 1. Repair damage - 2. If needed, Evacuate -Accidental Reentry: -1. Activate fire alarms in front of ship. -2. Move volatile matter to a fire proof area! -3. Get a fire suit. -4. Stay secure until an emergency ship arrives. -5. If ship does not arrive-Evacuate to a nearby safe area! -"}; + info = "Alert Levels:
    \nBlue- Emergency
    \n\t1. Caused by fire
    \n\t2. Caused by manual interaction
    \n\tAction:
    \n\t\tClose all fire doors. These can only be opened by resetting the alarm
    \nRed- Ejection/Self-Destruct
    \n\t1. Caused by module operating computer.
    \n\tAction:
    \n\t\tAfter the specified time the module will eject completely.
    \n
    \nEngine Maintenance Instructions:
    \n\tShut off ignition systems:
    \n\tActivate internal power
    \n\tActivate orbital balance matrix
    \n\tRemove volatile liquids from area
    \n\tWear a fire suit
    \n
    \n\tAfter
    \n\t\tDecontaminate
    \n\t\tVisit medical examiner
    \n
    \nToxin Laboratory Procedure:
    \n\tWear a gas mask regardless
    \n\tGet an oxygen tank.
    \n\tActivate internal atmosphere
    \n
    \n\tAfter
    \n\t\tDecontaminate
    \n\t\tVisit medical examiner
    \n
    \nDisaster Procedure:
    \n\tFire:
    \n\t\tActivate sector fire alarm.
    \n\t\tMove to a safe area.
    \n\t\tGet a fire suit
    \n\t\tAfter:
    \n\t\t\tAssess Damage
    \n\t\t\tRepair damages
    \n\t\t\tIf needed, Evacuate
    \n\tMeteor Shower:
    \n\t\tActivate fire alarm
    \n\t\tMove to the back of ship
    \n\t\tAfter
    \n\t\t\tRepair damage
    \n\t\t\tIf needed, Evacuate
    \n\tAccidental Reentry:
    \n\t\tActivate fire alarms in front of ship.
    \n\t\tMove volatile matter to a fire proof area!
    \n\t\tGet a fire suit.
    \n\t\tStay secure until an emergency ship arrives.
    \n
    \n\t\tIf ship does not arrive-
    \n\t\t\tEvacuate to a nearby safe area!" /obj/item/paper/fluff/shuttles/daniel info = "i love daniel
    daniel is my best friend

    you are tearing me apart elise" +/obj/item/paper/fluff/jobs/prisoner/letter + name = "letter from home" + info = {"Dearest sweetheart, +
    It is truly saddening you must spend your time locked up in an awful prison on that dangerous station. I have spoken to your lawyer who will attempt to appeal to the judge so your sentence may hopefully be reduced. +
    Regardless, I just want you to understand that all of us out here still love you, and want to see you released safely some day! I know that prison can be a very vicious place, so please promise us you'll avoid getting into any fights or trouble, okay? +
    We all care for your safety deeply, and could not live with ourselves if you ended up getting hurt. We've scheduled a visit to see you, and with any luck, hopefully our request will be granted soon. +
    Anyways, please do your best to make it by in that place, and never forget we'll be always here for you, no matter if we're separated. +
    +
    Please stay safe, +
    -Love, Your Dearest"} + //////////// Job guides n' fluff @@ -90,9 +59,42 @@ Accidental Reentry: name = "paper- 'Chemical Information'" info = "Known Onboard Toxins:
    \n\tGrade A Semi-Liquid Plasma:
    \n\t\tHighly poisonous. You cannot sustain concentrations above 15 units.
    \n\t\tA gas mask fails to filter plasma after 50 units.
    \n\t\tWill attempt to diffuse like a gas.
    \n\t\tFiltered by scrubbers.
    \n\t\tThere is a bottled version which is very different
    \n\t\t\tfrom the version found in canisters!
    \n
    \n\t\tWARNING: Highly Flammable. Keep away from heat sources
    \n\t\texcept in an enclosed fire area!
    \n\t\tWARNING: It is a crime to use this without authorization.
    \nKnown Onboard Anti-Toxin:
    \n\tAnti-Toxin Type 01P: Works against Grade A Plasma.
    \n\t\tBest if injected directly into bloodstream.
    \n\t\tA full injection is in every regular Med-Kit.
    \n\t\tSpecial toxin Kits hold around 7.
    \n
    \nKnown Onboard Chemicals (other):
    \n\tRejuvenation T#001:
    \n\t\tEven 1 unit injected directly into the bloodstream
    \n\t\t\twill cure unconscious and sleep toxins.
    \n\t\tIf administered to a dying patient it will prevent
    \n\t\t\tfurther damage for about units*3 seconds.
    \n\t\t\tit will not cure them or allow them to be cured.
    \n\t\tIt can be administered to a non-dying patient
    \n\t\t\tbut the chemicals disappear just as fast.
    \n\tMorphine T#054:
    \n\t\t5 units will induce precisely 1 minute of sleep.
    \n\t\t\tThe effect are cumulative.
    \n\t\tWARNING: It is a crime to use this without authorization" +/obj/item/paper/fluff/jobs/medical/hippocratic + name = "paper- 'Hippocratic Oath'" + info = {"I swear to fulfill, to the best of my ability and judgment, this covenant: +
    + I will respect the hard-won scientific gains of those physicians in whose steps I walk, + and gladly share such knowledge as is mine with those who are to follow. +
    + I will apply, for the benefit of the sick, all measures that are required, + avoiding those twin traps of overtreatment and therapeutic nihilism. +
    + I will remember that there is art to medicine as well as science, + and that warmth, sympathy, and understanding may outweigh the surgeon's knife or the chemist's drug. +
    + I will not be ashamed to say "I know not," + nor will I fail to call in my colleagues when the skills of another are needed for a patient's recovery. +
    + I will respect the privacy of my patients, for their problems are not disclosed to me that the world may know. Most especially must I tread with care in matters of life and death. + If it is given me to save a life, all thanks. But it may also be within my power to take a life; + this awesome responsibility must be faced with great humbleness and awareness of my own frailty. Above all, I must not play at God. +
    + I will remember that I do not treat a fever chart, a cancerous growth, but a sick human being, whose illness may affect the person's family and economic stability. + My responsibility includes these related problems, if I am to care adequately for the sick. +
    + I will prevent disease whenever I can, for prevention is preferable to cure. +
    + I will remember that I remain a member of society, with special obligations to all my fellow human beings, + those sound of mind and body as well as the infirm. +
    + If I do not violate this oath, may I enjoy life and art, respected while I live and remembered with affection thereafter. + May I always act so as to preserve the finest traditions of my calling and may I long experience the joy of healing those who seek my help. +
    "} + /* * Stations */ +////////// cogstation. /obj/item/paper/guides/cogstation/job_changes name = "MEMO: Job Changes" diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 28cb5ffae9..b8bbd0a30e 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "paper_bin1" item_state = "sheet-metal" + // inhand_icon_state = "sheet-metal" lefthand_file = 'icons/mob/inhands/misc/sheets_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/sheets_righthand.dmi' throwforce = 0 @@ -43,6 +44,7 @@ ..() /obj/item/paper_bin/MouseDrop(atom/over_object) + . = ..() var/mob/living/M = usr if(!istype(M) || M.incapacitated() || !Adjacent(M)) return @@ -54,17 +56,18 @@ var/obj/screen/inventory/hand/H = over_object M.putItemFromInventoryInHandIfPossible(src, H.held_index) - else - . = ..() - add_fingerprint(M) /obj/item/paper_bin/attack_paw(mob/user) return attack_hand(user) -/obj/item/paper_bin/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) - if(user.lying) - return +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/item/paper_bin/on_attack_hand(mob/user) + if(isliving(user)) + var/mob/living/L = user + if(!(L.mobility_flags & MOBILITY_PICKUP)) + return + // user.changeNext_move(CLICK_CD_MELEE) if(bin_pen) var/obj/item/pen/P = bin_pen P.add_fingerprint(user) @@ -85,8 +88,8 @@ P = new papertype(src) if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS]) if(prob(30)) - P.info = "*HONK HONK HONK HONK HONK HONK HONK
    HOOOOOOOOOOOOOOOOOOOOOONK*\n*APRIL FOOLS*\n" - P.rigged = 1 + P.info = "HONK HONK HONK HONK HONK HONK HONK
    HOOOOOOOOOOOOOOOOOOOOOONK
    APRIL FOOLS
    " + P.AddComponent(/datum/component/honkspam) P.add_fingerprint(user) P.forceMove(user.loc) @@ -148,8 +151,7 @@ papertype = /obj/item/paper/natural resistance_flags = FLAMMABLE -/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) - ..() +/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user) if(total_paper < 1) qdel(src) @@ -173,3 +175,9 @@ qdel(src) else ..() + +/obj/item/paper_bin/carbon + name = "carbon paper bin" + desc = "Contains all the paper you'll ever need, in duplicate!" + icon_state = "paper_bin_carbon" + papertype = /obj/item/paper/carbon diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index c6a1ee1389..53fe886d65 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -1,9 +1,9 @@ - /obj/item/paperplane name = "paper plane" desc = "Paper, folded in the shape of a plane." icon = 'icons/obj/bureaucracy.dmi' icon_state = "paperplane" + // custom_fire_overlay = "paperplane_onfire" throw_range = 7 throw_speed = 1 throwforce = 0 @@ -11,7 +11,7 @@ resistance_flags = FLAMMABLE max_integrity = 50 - var/hit_probability = 2//% + var/hit_probability = 2 //% var/obj/item/paper/internalPaper /obj/item/paperplane/origami @@ -41,6 +41,13 @@ qdel(src) return ..() +/obj/item/paperplane/Exited(atom/movable/AM, atom/newLoc) + . = ..() + if (AM == internalPaper) + internalPaper = null + if(!QDELETED(src)) + qdel(src) + /obj/item/paperplane/Destroy() QDEL_NULL(internalPaper) return ..() @@ -71,31 +78,19 @@ user.put_in_hands(internal_paper_tmp) /obj/item/paperplane/attackby(obj/item/P, mob/living/carbon/human/user, params) - ..() + if(burn_paper_product_attackby_check(P, user)) + return if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) - to_chat(user, "You should unfold [src] before changing it.") + to_chat(user, "You should unfold [src] before changing it!") return else if(istype(P, /obj/item/stamp)) //we don't randomize stamps on a paperplane internalPaper.attackby(P, user) //spoofed attack to update internal paper. update_icon() + add_fingerprint(user) + return - else if(P.get_temperature()) - if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10)) - user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ - "You miss [src] and accidentally light yourself on fire!") - user.dropItemToGround(P) - user.adjust_fire_stacks(1) - user.IgniteMob() - return - - if(!(in_range(user, src))) //to prevent issues as a result of telepathically lighting a paper - return - user.dropItemToGround(src) - user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!") - fire_act() - - add_fingerprint(user) + return ..() /obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback) @@ -112,26 +107,28 @@ if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman return var/mob/living/carbon/human/H = hit_atom + var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) if(prob(hit_probability)) if(H.is_eyes_covered()) return - var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) - visible_message("\The [src] hits [H] in the eye!") + visible_message("\The [src] hits [H] in the eye[eyes ? "" : " socket"]!") H.adjust_blurriness(6) - if(eyes) - eyes.applyOrganDamage(rand(6,8)) + eyes?.applyOrganDamage(rand(6,8)) H.DefaultCombatKnockdown(40) H.emote("scream") - /obj/item/paper/examine(mob/user) . = ..() . += "Alt-click [src] to fold it into a paper plane." /obj/item/paper/AltClick(mob/living/carbon/user, obj/item/I) - . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user), NO_TK)) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return + if(istype(src, /obj/item/paper/carbon)) + var/obj/item/paper/carbon/Carbon = src + if(!Carbon.iscopy && !Carbon.copied) + to_chat(user, "Take off the carbon copy first.") + return to_chat(user, "You fold [src] into the shape of a plane!") user.temporarilyRemoveItemFromInventory(src) var/obj/item/paperplane/plane_type = /obj/item/paperplane @@ -142,4 +139,3 @@ I = new plane_type(user, src) user.put_in_hands(I) - return TRUE diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 91b8a6719b..13890ae69e 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -16,6 +16,8 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "pen" item_state = "pen" + // inhand_icon_state = "pen" + // worn_icon_state = "pen" slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_EARS throwforce = 0 w_class = WEIGHT_CLASS_TINY @@ -76,6 +78,22 @@ icon_state = "pen-fountain" font = FOUNTAIN_PEN_FONT +/obj/item/pen/charcoal + name = "charcoal stylus" + desc = "It's just a wooden stick with some compressed ash on the end. At least it can write." + icon_state = "pen-charcoal" + colour = "dimgray" + font = CHARCOAL_FONT + custom_materials = null + grind_results = list(/datum/reagent/ash = 5, /datum/reagent/cellulose = 10) + +/datum/crafting_recipe/charcoal_stylus + name = "Charcoal Stylus" + result = /obj/item/pen/charcoal + reqs = list(/obj/item/stack/sheet/mineral/wood = 1, /datum/reagent/ash = 30) + time = 30 + category = CAT_PRIMAL + /obj/item/pen/fountain/captain name = "captain's fountain pen" desc = "It's an expensive Oak fountain pen. The nib is quite sharp." @@ -93,6 +111,7 @@ "Black and Silver" = "pen-fountain-b", "Command Blue" = "pen-fountain-cb" ) + embedding = list("embed_chance" = 75) /obj/item/pen/fountain/captain/Initialize() . = ..() @@ -139,20 +158,18 @@ if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE)) return if(oldname == input) - to_chat(user, "You changed \the [O.name] to... well... \the [O.name].") + to_chat(user, "You changed \the [O.name] to... well... \the [O.name].") else O.name = input - to_chat(user, "\The [oldname] has been successfully been renamed to \the [input].") + to_chat(user, "\The [oldname] has been successfully been renamed to \the [input].") O.renamedByPlayer = TRUE - log_game("[user] [key_name(user)] has renamed [O] to [input]") if(penchoice == "Change description") - var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 2048) + var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 100) if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE)) return O.desc = input - to_chat(user, "You have successfully changed \the [O.name]'s description.") - log_game("[user] [key_name(user)] has changed [O]'s description to to [input]") + to_chat(user, "You have successfully changed \the [O.name]'s description.") /* * Sleepypens @@ -181,9 +198,10 @@ */ /obj/item/pen/edagger attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off + // attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") //these won't show up if the pen is off + // attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") sharpness = SHARP_EDGED var/on = FALSE - embedding = list(embed_chance = EMBED_CHANCE) /obj/item/pen/edagger/ComponentInitialize() . = ..() @@ -193,29 +211,38 @@ /obj/item/pen/edagger/get_sharpness() return on * sharpness +/obj/item/pen/edagger/suicide_act(mob/user) + . = BRUTELOSS + if(on) + user.visible_message("[user] forcefully rams the pen into their mouth!") + else + user.visible_message("[user] is holding a pen up to their mouth! It looks like [user.p_theyre()] trying to commit suicide!") + attack_self(user) + /obj/item/pen/edagger/attack_self(mob/living/user) if(on) on = FALSE force = initial(force) + throw_speed = initial(throw_speed) w_class = initial(w_class) name = initial(name) hitsound = initial(hitsound) - embedding = null + embedding = list(embed_chance = EMBED_CHANCE) throwforce = initial(throwforce) - playsound(user, 'sound/weapons/saberoff.ogg', 5, 1) + playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE) to_chat(user, "[src] can now be concealed.") - updateEmbedding() else on = TRUE force = 18 + throw_speed = 4 w_class = WEIGHT_CLASS_NORMAL name = "energy dagger" hitsound = 'sound/weapons/blade1.ogg' - embedding = list(embed_chance = 100, fall_chance = 0) //rule of cool + embedding = list(embed_chance = 100) //rule of cool throwforce = 35 - playsound(user, 'sound/weapons/saberon.ogg', 5, 1) + playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE) to_chat(user, "[src] is now active.") - updateEmbedding() + updateEmbedding() update_icon() /obj/item/pen/edagger/update_icon_state() @@ -235,6 +262,8 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "digging_pen" item_state = "pen" + // inhand_icon_state = "pen" + // worn_icon_state = "pen" force = 3 w_class = WEIGHT_CLASS_TINY custom_materials = list(/datum/material/iron=10, /datum/material/diamond=100, /datum/material/titanium = 10) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 0b1f3bb01d..25a9cf0043 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -1,12 +1,20 @@ -/* Photocopiers! - * Contains: - * Photocopier - * Toner Cartridge - */ -/* - * Photocopier - */ +/// For use with the `color_mode` var. Photos will be printed in greyscale while the var has this value. +#define PHOTO_GREYSCALE "Greyscale" +/// For use with the `color_mode` var. Photos will be printed in full color while the var has this value. +#define PHOTO_COLOR "Color" + +/// How much toner is used for making a copy of a paper. +#define PAPER_TONER_USE 0.125 +/// How much toner is used for making a copy of a photo. +#define PHOTO_TONER_USE 0.625 +/// How much toner is used for making a copy of a document. +#define DOCUMENT_TONER_USE 0.75 +/// How much toner is used for making a copy of an ass. +#define ASS_TONER_USE 0.625 +/// The maximum amount of copies you can make with one press of the copy button. +#define MAX_COPIES_AT_ONCE 10 + /obj/machinery/photocopier name = "photocopier" desc = "Used to copy important documents and anatomy studies." @@ -19,183 +27,317 @@ power_channel = EQUIP max_integrity = 300 integrity_failure = 0.33 - var/obj/item/paper/copy = null //what's in the copier! - var/obj/item/photo/photocopy = null - var/obj/item/documents/doccopy = null - var/copies = 1 //how many copies to print! - var/toner = 40 //how much toner is left! woooooo~ - var/maxcopies = 10 //how many copies can be copied at once- idea shamelessly stolen from bs12's copier! - var/greytoggle = "Greyscale" - var/mob/living/ass //i can't believe i didn't write a stupid-ass comment about this var when i first coded asscopy. + /// A reference to an `/obj/item/paper` inside the copier, if one is inserted. Otherwise null. + var/obj/item/paper/paper_copy + /// A reference to an `/obj/item/photo` inside the copier, if one is inserted. Otherwise null. + var/obj/item/photo/photo_copy + /// A reference to an `/obj/item/documents` inside the copier, if one is inserted. Otherwise null. + var/obj/item/documents/document_copy + /// A reference to a mob on top of the photocopier trying to copy their ass. Null if there is no mob. + var/mob/living/ass + /// A reference to the toner cartridge that's inserted into the copier. Null if there is no cartridge. + var/obj/item/toner/toner_cartridge + /// How many copies will be printed with one click of the "copy" button. + var/num_copies = 1 + /// Used with photos. Determines if the copied photo will be in greyscale or color. + var/color_mode = PHOTO_COLOR + /// Indicates whether the printer is currently busy copying or not. var/busy = FALSE -/obj/machinery/photocopier/ui_interact(mob/user) +/obj/machinery/photocopier/Initialize() . = ..() - var/list/dat = list("Photocopier

    ") - if(copy || photocopy || doccopy || (ass && (ass.loc == src.loc))) - dat += "Remove Paper
    " - if(toner) - dat += "Copy
    " - dat += "Printing: [copies] copies." - dat += "- " - dat += "+

    " - if(photocopy) - dat += "Printing in [greytoggle]

    " - else if(toner) - dat += "Please insert paper to copy.

    " - if(isAI(user)) - dat += "Print photo from database

    " - dat += "Current toner level: [toner]" - if(!toner) - dat +="
    Please insert a new toner cartridge!" - user << browse(dat.Join(""), "window=copier") - onclose(user, "copier") + //AddComponent(/datum/component/payment, 5, SSeconomy.get_dep_account(ACCOUNT_CIV), PAYMENT_CLINICAL) + toner_cartridge = new(src) -/obj/machinery/photocopier/Topic(href, href_list) +/obj/machinery/photocopier/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Photocopier") + ui.open() + +/obj/machinery/photocopier/ui_data(mob/user) + var/list/data = list() + data["has_item"] = !copier_empty() + data["num_copies"] = num_copies + + if(photo_copy) + data["is_photo"] = TRUE + data["color_mode"] = color_mode + + if(isAI(user)) + data["isAI"] = TRUE + data["can_AI_print"] = toner_cartridge ? toner_cartridge.charges >= PHOTO_TONER_USE : FALSE + else + data["isAI"] = FALSE + + if(toner_cartridge) + data["has_toner"] = TRUE + data["current_toner"] = toner_cartridge.charges + data["max_toner"] = toner_cartridge.max_charges + data["has_enough_toner"] = has_enough_toner() + else + data["has_toner"] = FALSE + data["has_enough_toner"] = FALSE + + return data + +/obj/machinery/photocopier/ui_act(action, list/params) if(..()) return - if(href_list["copy"]) - if(copy) - for(var/i = 0, i < copies, i++) - if(toner > 0 && !busy && copy) - var/copy_as_paper = 1 - if(istype(copy, /obj/item/paper/contract/employment)) - var/obj/item/paper/contract/employment/E = copy - var/obj/item/paper/contract/employment/C = new /obj/item/paper/contract/employment (loc, E.target.current) - if(C) - copy_as_paper = 0 - if(copy_as_paper) - var/obj/item/paper/c = new /obj/item/paper (loc) - if(length(copy.info) > 0) //Only print and add content if the copied doc has words on it - if(toner > 10) //lots of toner, make it dark - c.info = "" - else //no toner? shitty copies for you! - c.info = "" - var/copied = copy.info - copied = replacetext(copied, "" - c.name = copy.name - c.update_icon() - c.stamps = copy.stamps - if(copy.stamped) - c.stamped = copy.stamped.Copy() - c.copy_overlays(copy, TRUE) - toner-- - busy = TRUE - addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) - else - break - updateUsrDialog() - else if(photocopy) - for(var/i = 0, i < copies, i++) - if(toner >= 5 && !busy && photocopy) //Was set to = 0, but if there was say 3 toner left and this ran, you would get -2 which would be weird for ink - new /obj/item/photo (loc, photocopy.picture.Copy(greytoggle == "Greyscale"? TRUE : FALSE)) - busy = TRUE - addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) - else - break - else if(doccopy) - for(var/i = 0, i < copies, i++) - if(toner > 5 && !busy && doccopy) - new /obj/item/documents/photocopy(loc, doccopy) - toner-= 6 // the sprite shows 6 papers, yes I checked - busy = TRUE - addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) - else - break - updateUsrDialog() - else if(ass) //ASS COPY. By Miauw - for(var/i = 0, i < copies, i++) - var/icon/temp_img - if(ishuman(ass) && (ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING))) - to_chat(usr, "You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on." ) - break - else if(toner >= 5 && !busy && check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on. - if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro. - temp_img = icon('icons/ass/assalien.png') - else if(ishuman(ass)) //Suit checks are in check_ass - temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png') - else if(isdrone(ass)) //Drones are hot - temp_img = icon('icons/ass/assdrone.png') - else - break - busy = TRUE - sleep(15) - var/obj/item/photo/p = new /obj/item/photo (loc) - var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img) - p.pixel_x = rand(-10, 10) - p.pixel_y = rand(-10, 10) - toEmbed.psize_x = 128 - toEmbed.psize_y = 128 - p.set_picture(toEmbed, TRUE, TRUE) - toner -= 5 - busy = FALSE - else - break - updateUsrDialog() - else if(href_list["remove"]) - if(copy) - remove_photocopy(copy, usr) - copy = null - else if(photocopy) - remove_photocopy(photocopy, usr) - photocopy = null - else if(doccopy) - remove_photocopy(doccopy, usr) - doccopy = null - else if(check_ass()) - to_chat(ass, "You feel a slight pressure on your ass.") - updateUsrDialog() - else if(href_list["min"]) - if(copies > 1) - copies-- - updateUsrDialog() - else if(href_list["add"]) - if(copies < maxcopies) - copies++ - updateUsrDialog() - else if(href_list["aipic"]) - if(!isAI(usr)) - return - if(toner >= 5 && !busy) + + switch(action) + // Copying paper, photos, documents and asses. + if("make_copy") + if(busy) + to_chat(usr, "[src] is currently busy copying something. Please wait until it is finished.") + return FALSE + if(paper_copy) + if(!length(paper_copy.info)) + to_chat(usr, "An error message flashes across [src]'s screen: \"The supplied paper is blank. Aborting.\"") + return FALSE + // Basic paper + if(istype(paper_copy, /obj/item/paper)) + do_copy_loop(CALLBACK(src, .proc/make_paper_copy), usr) + return TRUE + // Devil contract paper. + if(istype(paper_copy, /obj/item/paper/contract/employment)) + do_copy_loop(CALLBACK(src, .proc/make_devil_paper_copy), usr) + return TRUE + // Copying photo. + if(photo_copy) + do_copy_loop(CALLBACK(src, .proc/make_photo_copy), usr) + return TRUE + // Copying Documents. + if(document_copy) + do_copy_loop(CALLBACK(src, .proc/make_document_copy), usr) + return TRUE + // ASS COPY. By Miauw + if(ass) + do_copy_loop(CALLBACK(src, .proc/make_ass_copy), usr) + return TRUE + + // Remove the paper/photo/document from the photocopier. + if("remove") + if(paper_copy) + remove_photocopy(paper_copy, usr) + paper_copy = null + else if(photo_copy) + remove_photocopy(photo_copy, usr) + photo_copy = null + else if(document_copy) + remove_photocopy(document_copy, usr) + document_copy = null + else if(check_ass()) + to_chat(ass, "You feel a slight pressure on your ass.") + return TRUE + + // AI printing photos from their saved images. + if("ai_photo") + if(busy) + to_chat(usr, "[src] is currently busy copying something. Please wait until it is finished.") + return FALSE var/mob/living/silicon/ai/tempAI = usr - if(tempAI.aicamera.stored.len == 0) - to_chat(usr, "No images saved") + if(!length(tempAI.aicamera.stored)) + to_chat(usr, "No images saved.") return var/datum/picture/selection = tempAI.aicamera.selectpicture(usr) - var/obj/item/photo/photo = new(loc, selection) - photo.pixel_x = rand(-10, 10) - photo.pixel_y = rand(-10, 10) - toner -= 5 //AI prints color pictures only, thus they can do it more efficiently - busy = TRUE - addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) - updateUsrDialog() - else if(href_list["colortoggle"]) - if(greytoggle == "Greyscale") - greytoggle = "Color" - else - greytoggle = "Greyscale" - updateUsrDialog() + var/obj/item/photo/photo = new(loc, selection) // AI prints color photos only. + give_pixel_offset(photo) + toner_cartridge.charges -= PHOTO_TONER_USE + return TRUE + // Switch between greyscale and color photos + if("color_mode") + if(params["mode"] in list(PHOTO_GREYSCALE, PHOTO_COLOR)) + color_mode = params["mode"] + return TRUE + + // Remove the toner cartridge from the copier. + if("remove_toner") + if(issilicon(usr) || (ishuman(usr) && !usr.put_in_hands(toner_cartridge))) + toner_cartridge.forceMove(drop_location()) + toner_cartridge = null + return TRUE + + // Set the number of copies to be printed with 1 click of the "copy" button. + if("set_copies") + num_copies = clamp(text2num(params["num_copies"]), 1, MAX_COPIES_AT_ONCE) + return TRUE + +/** + * Determines if the photocopier has enough toner to create `num_copies` amount of copies of the currently inserted item. + */ +/obj/machinery/photocopier/proc/has_enough_toner() + if(paper_copy) + return toner_cartridge.charges >= (PAPER_TONER_USE * num_copies) + else if(document_copy) + return toner_cartridge.charges >= (DOCUMENT_TONER_USE * num_copies) + else if(photo_copy) + return toner_cartridge.charges >= (PHOTO_TONER_USE * num_copies) + else if(ass) + return toner_cartridge.charges >= (ASS_TONER_USE * num_copies) + return FALSE + +/** + * Will invoke the passed in `copy_cb` callback in 1 second intervals, and charge the user 5 credits for each copy made. + * + * Arguments: + * * copy_cb - a callback for which proc to call. Should only be one of the `make_x_copy()` procs, such as `make_paper_copy()`. + * * user - the mob who clicked copy. + */ +/obj/machinery/photocopier/proc/do_copy_loop(datum/callback/copy_cb, mob/user) + busy = TRUE + var/num_loops + for(var/i in 1 to num_copies) + //if(attempt_charge(src, user) & COMPONENT_OBJ_CANCEL_CHARGE) + // break + addtimer(copy_cb, i SECONDS) + num_loops++ + addtimer(CALLBACK(src, .proc/reset_busy), num_loops SECONDS) + +/** + * Sets busy to `FALSE`. Created as a proc so it can be used in callbacks. + */ /obj/machinery/photocopier/proc/reset_busy() busy = FALSE - updateUsrDialog() -/obj/machinery/photocopier/proc/do_insertion(obj/item/O, mob/user) - O.forceMove(src) - to_chat(user, "You insert [O] into [src].") +/** + * Gives items a random x and y pixel offset, between -10 and 10 for each. + * + * This is done that when someone prints multiple papers, we dont have them all appear to be stacked in the same exact location. + * + * Arguments: + * * copied_item - The paper, document, or photo that was just spawned on top of the printer. + */ +/obj/machinery/photocopier/proc/give_pixel_offset(obj/item/copied_item) + copied_item.pixel_x = rand(-10, 10) + copied_item.pixel_y = rand(-10, 10) + +/** + * Handles the copying of devil contract paper. Transfers all the text, stamps and so on from the old paper, to the copy. + * + * Checks first if `paper_copy` exists. Since this proc is called from a timer, it's possible that it was removed. + * Does not check if it has enough toner because devil contracts cost no toner to print. + */ +/obj/machinery/photocopier/proc/make_devil_paper_copy() + if(!paper_copy) + return + var/obj/item/paper/contract/employment/E = paper_copy + var/obj/item/paper/contract/employment/C = new(loc, E.target.current) + give_pixel_offset(C) + +/** + * Handles the copying of paper. Transfers all the text, stamps and so on from the old paper, to the copy. + * + * Checks first if `paper_copy` exists. Since this proc is called from a timer, it's possible that it was removed. + */ +/obj/machinery/photocopier/proc/make_paper_copy() + if(!paper_copy) + return + var/obj/item/paper/copied_paper = new(loc) + give_pixel_offset(copied_paper) + if(toner_cartridge.charges > 10) // Lots of toner, make it dark. + copied_paper.info = "" + else // No toner? shitty copies for you! + copied_paper.info = "" + + var/copied_info = paper_copy.info + copied_info = replacetext(copied_info, "" + copied_paper.name = paper_copy.name + copied_paper.update_icon() + copied_paper.stamps = paper_copy.stamps + if(paper_copy.stamped) + copied_paper.stamped = paper_copy.stamped.Copy() + copied_paper.copy_overlays(paper_copy, TRUE) + toner_cartridge.charges -= PAPER_TONER_USE + +/** + * Handles the copying of photos, which can be printed in either color or greyscale. + * + * Checks first if `photo_copy` exists. Since this proc is called from a timer, it's possible that it was removed. + */ +/obj/machinery/photocopier/proc/make_photo_copy() + if(!photo_copy) + return + var/obj/item/photo/copied_pic = new(loc, photo_copy.picture.Copy(color_mode == PHOTO_GREYSCALE ? TRUE : FALSE)) + give_pixel_offset(copied_pic) + toner_cartridge.charges -= PHOTO_TONER_USE + +/** + * Handles the copying of documents. + * + * Checks first if `document_copy` exists. Since this proc is called from a timer, it's possible that it was removed. + */ +/obj/machinery/photocopier/proc/make_document_copy() + if(!document_copy) + return + var/obj/item/documents/photocopy/copied_doc = new(loc, document_copy) + give_pixel_offset(copied_doc) + toner_cartridge.charges -= DOCUMENT_TONER_USE + +/** + * Handles the copying of an ass photo. + * + * Calls `check_ass()` first to make sure that `ass` exists, among other conditions. Since this proc is called from a timer, it's possible that it was removed. + * Additionally checks that the mob has their clothes off. + */ +/obj/machinery/photocopier/proc/make_ass_copy() + if(!check_ass()) + return + if(ishuman(ass)) //(ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING))) + var/mob/living/carbon/C = ass //have to typecast to this, is_groin_exposed is carbon level + if(C.is_groin_exposed()) + to_chat(usr, "You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on." ) + return + + var/icon/temp_img + if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro. + temp_img = icon('icons/ass/assalien.png') + else if(ishuman(ass)) //Suit checks are after check_ass + temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png') + else if(isdrone(ass)) //Drones are hot + temp_img = icon('icons/ass/assdrone.png') + + var/obj/item/photo/copied_ass = new /obj/item/photo(loc) + var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img) + give_pixel_offset(copied_ass) + toEmbed.psize_x = 128 + toEmbed.psize_y = 128 + copied_ass.set_picture(toEmbed, TRUE, TRUE) + toner_cartridge.charges -= ASS_TONER_USE + +/** + * Inserts the item into the copier. Called in `attackby()` after a human mob clicked on the copier with a paper, photo, or document. + * + * Arugments: + * * object - the object that got inserted. + * * user - the mob that inserted the object. + */ +/obj/machinery/photocopier/proc/do_insertion(obj/item/object, mob/user) + object.forceMove(src) + to_chat(user, "You insert [object] into [src].") flick("photocopier1", src) - updateUsrDialog() -/obj/machinery/photocopier/proc/remove_photocopy(obj/item/O, mob/user) +/** + * Called when someone hits the "remove item" button on the copier UI. + * + * If the user is a silicon, it drops the object at the location of the copier. If the user is not a silicon, it tries to put the object in their hands first. + * Sets `busy` to `FALSE` because if the inserted item is removed, the copier should halt copying. + * + * Arguments: + * * object - the item we're trying to remove. + * * user - the user removing the item. + */ +/obj/machinery/photocopier/proc/remove_photocopy(obj/item/object, mob/user) if(!issilicon(user)) //surprised this check didn't exist before, putting stuff in AI's hand is bad - O.forceMove(user.loc) - user.put_in_hands(O) + object.forceMove(user.loc) + user.put_in_hands(object) else - O.forceMove(drop_location()) - to_chat(user, "You take [O] out of [src].") + object.forceMove(drop_location()) + to_chat(user, "You take [object] out of [src]. [busy ? "The [src] comes to a halt." : ""]") /obj/machinery/photocopier/attackby(obj/item/O, mob/user, params) if(default_unfasten_wrench(user, O)) @@ -210,7 +352,7 @@ else if(!user.temporarilyRemoveItemFromInventory(O)) return - copy = O + paper_copy = O do_insertion(O, user) else to_chat(user, "There is already something in [src]!") @@ -219,7 +361,7 @@ if(copier_empty()) if(!user.temporarilyRemoveItemFromInventory(O)) return - photocopy = O + photo_copy = O do_insertion(O, user) else to_chat(user, "There is already something in [src]!") @@ -228,38 +370,35 @@ if(copier_empty()) if(!user.temporarilyRemoveItemFromInventory(O)) return - doccopy = O + document_copy = O do_insertion(O, user) else to_chat(user, "There is already something in [src]!") else if(istype(O, /obj/item/toner)) - if(toner <= 0) - if(!user.temporarilyRemoveItemFromInventory(O)) - return - qdel(O) - toner = 40 - to_chat(user, "You insert [O] into [src].") - updateUsrDialog() - else - to_chat(user, "This cartridge is not yet ready for replacement! Use up the rest of the toner.") + if(toner_cartridge) + to_chat(user, "[src] already has a toner cartridge inserted. Remove that one first.") + return + O.forceMove(src) + toner_cartridge = O + to_chat(user, "You insert [O] into [src].") else if(istype(O, /obj/item/areaeditor/blueprints)) - to_chat(user, "The Blueprint is too large to put into the copier. You need to find something else to record the document") + to_chat(user, "The Blueprint is too large to put into the copier. You need to find something else to record the document.") else return ..() /obj/machinery/photocopier/obj_break(damage_flag) . = ..() - if(. && toner > 0) + if(. && toner_cartridge.charges) new /obj/effect/decal/cleanable/oil(get_turf(src)) - toner = 0 + toner_cartridge.charges = 0 /obj/machinery/photocopier/MouseDrop_T(mob/target, mob/user) check_ass() //Just to make sure that you can re-drag somebody onto it after they moved off. - if (!istype(target) || target.anchored || target.buckled || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE) || target == ass || copier_blocked()) + if(!istype(target) || target.anchored || target.buckled || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE) || target == ass || copier_blocked()) return - src.add_fingerprint(user) + add_fingerprint(user) if(target == user) user.visible_message("[user] starts climbing onto the photocopier!", "You start climbing onto the photocopier...") else @@ -277,49 +416,63 @@ target.forceMove(drop_location()) ass = target - if(photocopy) - photocopy.forceMove(drop_location()) - visible_message("[photocopy] is shoved out of the way by [ass]!") - photocopy = null + if(photo_copy) + photo_copy.forceMove(drop_location()) + visible_message("[photo_copy] is shoved out of the way by [ass]!") + photo_copy = null - else if(copy) - copy.forceMove(drop_location()) - visible_message("[copy] is shoved out of the way by [ass]!") - copy = null - updateUsrDialog() + else if(paper_copy) + paper_copy.forceMove(drop_location()) + visible_message("[paper_copy] is shoved out of the way by [ass]!") + paper_copy = null + else if(document_copy) + document_copy.forceMove(drop_location()) + visible_message("[document_copy] is shoved out of the way by [ass]!") + document_copy = null + +/obj/machinery/photocopier/Exited(atom/movable/AM, atom/newloc) + check_ass() // There was potentially a person sitting on the copier, check if they're still there. + return ..() + +/** + * Checks the living mob `ass` exists and its location is the same as the photocopier. + * + * Returns FALSE if `ass` doesn't exist or is not at the copier's location. Returns TRUE otherwise. + */ /obj/machinery/photocopier/proc/check_ass() //I'm not sure wether I made this proc because it's good form or because of the name. if(!ass) - return 0 - if(ass.loc != src.loc) + return FALSE + if(ass.loc != loc) ass = null - updateUsrDialog() - return 0 - else if(ishuman(ass)) - if(!ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) && !ass.get_item_by_slot(ITEM_SLOT_OCLOTHING)) - return 1 - else - return 0 - else - return 1 + return FALSE + return TRUE +/** + * Checks if the copier is deleted, or has something dense at its location. Called in `MouseDrop_T()` + */ /obj/machinery/photocopier/proc/copier_blocked() if(QDELETED(src)) return if(loc.density) - return 1 + return TRUE for(var/atom/movable/AM in loc) if(AM == src) continue if(AM.density) - return 1 - return 0 + return TRUE + return FALSE +/** + * Checks if there is an item inserted into the copier or a mob sitting on top of it. + * + * Return `FALSE` is the copier has something inside of it. Returns `TRUE` if it doesn't. + */ /obj/machinery/photocopier/proc/copier_empty() - if(copy || photocopy || check_ass()) - return 0 + if(paper_copy || photo_copy || document_copy || check_ass()) + return FALSE else - return 1 + return TRUE /* * Toner cartridge @@ -343,3 +496,11 @@ desc = "Why would ANYONE need THIS MUCH TONER?" charges = 200 max_charges = 200 + +#undef PHOTO_GREYSCALE +#undef PHOTO_COLOR +#undef PAPER_TONER_USE +#undef PHOTO_TONER_USE +#undef DOCUMENT_TONER_USE +#undef ASS_TONER_USE +#undef MAX_COPIES_AT_ONCE diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm index 241dde13a8..104f70bfdf 100644 --- a/code/modules/paperwork/stamps.dm +++ b/code/modules/paperwork/stamps.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "stamp-ok" item_state = "stamp" + // inhand_icon_state = "stamp" throwforce = 0 w_class = WEIGHT_CLASS_TINY throw_speed = 3 @@ -11,6 +12,8 @@ custom_materials = list(/datum/material/iron=60) pressure_resistance = 2 attack_verb = list("stamped") + // attack_verb_continuous = list("stamps") + // attack_verb_simple = list("stamp") /obj/item/stamp/suicide_act(mob/user) user.visible_message("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead.") @@ -66,5 +69,25 @@ icon_state = "stamp-clown" dye_color = DYE_CLOWN +/obj/item/stamp/mime + name = "mime's rubber stamp" + icon_state = "stamp-mime" + dye_color = DYE_MIME + +/obj/item/stamp/chap + name = "chaplain's rubber stamp" + icon_state = "stamp-chap" + dye_color = DYE_CHAP + +/obj/item/stamp/centcom + name = "CentCom rubber stamp" + icon_state = "stamp-centcom" + dye_color = DYE_CENTCOM + +/obj/item/stamp/syndicate + name = "Syndicate rubber stamp" + icon_state = "stamp-syndicate" + dye_color = DYE_SYNDICATE + /obj/item/stamp/attack_paw(mob/user) return attack_hand(user) diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm new file mode 100644 index 0000000000..0e553ced35 --- /dev/null +++ b/code/modules/paperwork/ticketmachine.dm @@ -0,0 +1,234 @@ +//Bureaucracy machine! +//Simply set this up in the hopline and you can serve people based on ticket numbers + +/obj/machinery/ticket_machine + name = "ticket machine" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "ticketmachine" + desc = "A marvel of bureaucratic engineering encased in an efficient plastic shell. It can be refilled with a hand labeler refill roll and linked to buttons with a multitool." + density = FALSE + maptext_height = 26 + maptext_width = 32 + maptext_x = 7 + maptext_y = 10 + layer = HIGH_OBJ_LAYER + var/ticket_number = 0 //Increment the ticket number whenever the HOP presses his button + var/current_number = 0 //What ticket number are we currently serving? + var/max_number = 100 //At this point, you need to refill it. + var/cooldown = 50 + var/ready = TRUE + var/id = "ticket_machine_default" //For buttons + var/list/ticket_holders = list() + var/list/obj/item/ticket_machine_ticket/tickets = list() + +/obj/machinery/ticket_machine/multitool_act(mob/living/user, obj/item/I) + if(!multitool_check_buffer(user, I)) //make sure it has a data buffer + return + var/obj/item/multitool/M = I + M.buffer = src + to_chat(user, "You store linkage information in [I]'s buffer.") + return TRUE + +/obj/machinery/ticket_machine/emag_act(mob/user) //Emag the ticket machine to dispense burning tickets, as well as randomize its number to destroy the HoP's mind. + if(obj_flags & EMAGGED) + return + to_chat(user, "You overload [src]'s bureaucratic logic circuitry to its MAXIMUM setting.") + ticket_number = rand(0,max_number) + current_number = ticket_number + obj_flags |= EMAGGED + if(tickets.len) + for(var/obj/item/ticket_machine_ticket/ticket in tickets) + ticket.audible_message("\the [ticket] disperses!") + qdel(ticket) + tickets.Cut() + update_icon() + +/obj/machinery/ticket_machine/Initialize() + . = ..() + update_icon() + +/obj/machinery/ticket_machine/proc/increment() + if(current_number > ticket_number) + return + if(current_number && !(obj_flags & EMAGGED) && tickets[current_number]) + tickets[current_number].audible_message("\the [tickets[current_number]] disperses!") + qdel(tickets[current_number]) + if(current_number < ticket_number) + current_number ++ //Increment the one we're serving. + playsound(src, 'sound/misc/announce_dig.ogg', 50, FALSE) + say("Now serving ticket #[current_number]!") + if(!(obj_flags & EMAGGED) && tickets[current_number]) + tickets[current_number].audible_message("\the [tickets[current_number]] vibrates!") + update_icon() //Update our icon here rather than when they take a ticket to show the current ticket number being served + +/obj/machinery/button/ticket_machine + name = "increment ticket counter" + desc = "Use this button after you've served someone to tell the next person to come forward." + device_type = /obj/item/assembly/control/ticket_machine + req_access = list() + id = "ticket_machine_default" + +/obj/machinery/button/ticket_machine/Initialize() + . = ..() + if(device) + var/obj/item/assembly/control/ticket_machine/ours = device + ours.id = id + +/obj/machinery/button/ticket_machine/multitool_act(mob/living/user, obj/item/I) + . = ..() + if(I.tool_behaviour == TOOL_MULTITOOL) + var/obj/item/multitool/M = I + if(M.buffer && !istype(M.buffer, /obj/machinery/ticket_machine)) + return + var/obj/item/assembly/control/ticket_machine/controller = device + controller.linked = M.buffer + id = null + controller.id = null + to_chat(user, "You've linked [src] to [controller.linked].") + +/obj/item/assembly/control/ticket_machine + name = "ticket machine controller" + desc = "A remote controller for the HoP's ticket machine." + var/obj/machinery/ticket_machine/linked //To whom are we linked? + +/obj/item/assembly/control/ticket_machine/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/assembly/control/ticket_machine/LateInitialize() + find_machine() + +/obj/item/assembly/control/ticket_machine/proc/find_machine() //Locate the one to which we're linked + for(var/obj/machinery/ticket_machine/ticketsplease in GLOB.machines) + if(ticketsplease.id == id) + linked = ticketsplease + if(linked) + return TRUE + else + return FALSE + +/obj/item/assembly/control/ticket_machine/activate() + if(cooldown) + return + if(!linked) + return + cooldown = TRUE + linked.increment() + addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10) + +/obj/machinery/ticket_machine/update_icon() + switch(ticket_number) //Gives you an idea of how many tickets are left + if(0 to 49) + icon_state = "ticketmachine_100" + if(50 to 99) + icon_state = "ticketmachine_50" + if(100) + icon_state = "ticketmachine_0" + handle_maptext() + +/obj/machinery/ticket_machine/proc/handle_maptext() + switch(ticket_number) //This is here to handle maptext offsets so that the numbers align. + if(0 to 9) + maptext_x = 13 + if(10 to 99) + maptext_x = 10 + if(100) + maptext_x = 8 + maptext = "[current_number]" //Finally, apply the maptext + +/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/hand_labeler_refill)) + if(!(ticket_number >= max_number)) + to_chat(user, "[src] refuses [I]! There [max_number-ticket_number==1 ? "is" : "are"] still [max_number-ticket_number] ticket\s left!") + return + to_chat(user, "You start to refill [src]'s ticket holder (doing this will reset its ticket count!).") + if(do_after(user, 30, target = src)) + to_chat(user, "You insert [I] into [src] as it whirs nondescriptly.") + qdel(I) + ticket_number = 0 + current_number = 0 + if(tickets.len) + for(var/obj/item/ticket_machine_ticket/ticket in tickets) + ticket.audible_message("\the [ticket] disperses!") + qdel(ticket) + tickets.Cut() + max_number = initial(max_number) + update_icon() + return + +/obj/machinery/ticket_machine/proc/reset_cooldown() + ready = TRUE + +/obj/machinery/ticket_machine/attack_hand(mob/living/carbon/user) + . = ..() + INVOKE_ASYNC(src, .proc/attempt_ticket, user) + +/obj/machinery/ticket_machine/proc/attempt_ticket(mob/living/carbon/user) + if(!ready) + to_chat(user,"You press the button, but nothing happens...") + return + if(ticket_number >= max_number) + to_chat(user,"Ticket supply depleted, please refill this unit with a hand labeller refill cartridge!") + return + if((user in ticket_holders) && !(obj_flags & EMAGGED)) + to_chat(user, "You already have a ticket!") + return + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE) + ticket_number ++ + to_chat(user, "You take a ticket from [src], looks like you're ticket number #[ticket_number]...") + var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src)) + theirticket.name = "Ticket #[ticket_number]" + theirticket.maptext = "[ticket_number]" + theirticket.saved_maptext = "[ticket_number]" + theirticket.ticket_number = ticket_number + theirticket.source = src + theirticket.owner = user + user.put_in_hands(theirticket) + ticket_holders += user + tickets += theirticket + if(obj_flags & EMAGGED) //Emag the machine to destroy the HOP's life. + ready = FALSE + addtimer(CALLBACK(src, .proc/reset_cooldown), cooldown)//Small cooldown to prevent piles of flaming tickets + theirticket.fire_act() + user.dropItemToGround(theirticket) + user.adjust_fire_stacks(1) + user.IgniteMob() + return + +/obj/item/ticket_machine_ticket + name = "Ticket" + desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper®. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "ticket" + maptext_x = 7 + maptext_y = 10 + w_class = WEIGHT_CLASS_TINY + resistance_flags = FLAMMABLE + max_integrity = 50 + var/saved_maptext = null + var/mob/living/carbon/owner + var/obj/machinery/ticket_machine/source + var/ticket_number + +/obj/item/ticket_machine_ticket/attack_hand(mob/user) + . = ..() + maptext = saved_maptext //For some reason, storage code removes all maptext off objs, this stops its number from being wiped off when taken out of storage. + +/obj/item/ticket_machine_ticket/attackby(obj/item/P, mob/living/carbon/human/user, params) //Stolen from papercode + if(burn_paper_product_attackby_check(P, user)) + return + + return ..() + +/obj/item/paper/extinguish() + ..() + update_icon() + +/obj/item/ticket_machine_ticket/Destroy() + if(owner && source) + source.ticket_holders -= owner + source.tickets[ticket_number] = null + owner = null + source = null + return ..() diff --git a/code/modules/photography/_pictures.dm b/code/modules/photography/_pictures.dm index f667e18f47..6f85cdb3a6 100644 --- a/code/modules/photography/_pictures.dm +++ b/code/modules/photography/_pictures.dm @@ -30,16 +30,16 @@ if(autogenerate_icon && !picture_icon && picture_image) regenerate_small_icon() -/datum/picture/proc/get_small_icon() +/datum/picture/proc/get_small_icon(iconstate) if(!picture_icon) - regenerate_small_icon() + regenerate_small_icon(iconstate) return picture_icon -/datum/picture/proc/regenerate_small_icon() +/datum/picture/proc/regenerate_small_icon(iconstate) if(!picture_image) return var/icon/small_img = icon(picture_image) - var/icon/ic = icon('icons/obj/items_and_weapons.dmi', "photo") + var/icon/ic = icon('icons/obj/items_and_weapons.dmi', iconstate ? iconstate :"photo") small_img.Scale(8, 8) ic.Blend(small_img,ICON_OVERLAY, 13, 13) picture_icon = ic diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index 5c78709e9b..c363c549de 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -35,23 +35,23 @@ /obj/item/photo/update_icon_state() if(!istype(picture) || !picture.picture_image) return - var/icon/I = picture.get_small_icon() + var/icon/I = picture.get_small_icon(initial(icon_state)) if(I) icon = I /obj/item/photo/suicide_act(mob/living/carbon/user) user.visible_message("[user] is taking one last look at \the [src]! It looks like [user.p_theyre()] giving in to death!")//when you wanna look at photo of waifu one last time before you die... if (user.gender == MALE) - playsound(user, 'sound/voice/human/manlaugh1.ogg', 50, 1)//EVERY TIME I DO IT MAKES ME LAUGH + playsound(user, 'sound/voice/human/manlaugh1.ogg', 50, TRUE)//EVERY TIME I DO IT MAKES ME LAUGH else if (user.gender == FEMALE) - playsound(user, 'sound/voice/human/womanlaugh.ogg', 50, 1) + playsound(user, 'sound/voice/human/womanlaugh.ogg', 50, TRUE) return OXYLOSS /obj/item/photo/attack_self(mob/user) user.examinate(src) /obj/item/photo/attackby(obj/item/P, mob/user, params) - if(try_burn(P, user)) + if(burn_paper_product_attackby_check(P, user)) return if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) if(!user.is_literate()) @@ -60,31 +60,13 @@ var/txt = stripped_input(user, "What would you like to write on the back?", "Photo Writing", "", 128) if(txt && user.canUseTopic(src, BE_CLOSE)) scribble = txt - ..() - -/obj/item/photo/proc/try_burn(obj/item/I, mob/living/user) - var/ignition_message = I.ignition_effect(src, user) - if(!ignition_message) - return - . = TRUE - if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user)) - user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ - "You miss [src] and accidentally light yourself on fire!") - if(user.is_holding(I)) //checking if they're holding it in case TK is involved - user.dropItemToGround(I) - user.adjust_fire_stacks(1) - user.IgniteMob() - return - - if(user.is_holding(src)) //no TK shit here. - user.dropItemToGround(src) - user.visible_message(ignition_message) - add_fingerprint(user) - fire_act(I.get_temperature()) + else + return ..() /obj/item/photo/examine(mob/user) . = ..() - if(in_range(src, user)) + + if(in_range(src, user) || isobserver(user)) show(user) else . += "You need to get closer to get a good look at this photo!" diff --git a/code/modules/plumbing/plumbers/pill_press.dm b/code/modules/plumbing/plumbers/pill_press.dm index 56510fac87..88f56f111d 100644 --- a/code/modules/plumbing/plumbers/pill_press.dm +++ b/code/modules/plumbing/plumbers/pill_press.dm @@ -42,7 +42,7 @@ for (var/x in 1 to PILL_STYLE_COUNT) var/list/SL = list() SL["id"] = x - SL["htmltag"] = assets.icon_tag("pill[x]") + SL["class_name"] = assets.icon_class_name("pill[x]") pill_styles += list(SL) diff --git a/code/modules/pool/pool_controller.dm b/code/modules/pool/pool_controller.dm index c9bc6be3e5..17faa7a3e3 100644 --- a/code/modules/pool/pool_controller.dm +++ b/code/modules/pool/pool_controller.dm @@ -210,7 +210,7 @@ for(var/datum/reagent/R in reagents.reagent_list) if(R.reagent_state == SOLID) R.reagent_state = LIQUID - if(!swimee.reagents.has_reagent(POOL_NO_OVERDOSE_MEDICINE_MAX)) + if(!swimee.reagents.has_reagent(R.type,POOL_NO_OVERDOSE_MEDICINE_MAX)) swimee.reagents.add_reagent(R.type, 0.5) //osmosis reagents.reaction(swimee, VAPOR, 0.03) //3 percent. Need to find a way to prevent this from stacking chems at some point like the above. for(var/obj/objects in W) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2480288484..1045786917 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1161,7 +1161,7 @@ occupier.eyeobj.name = "[occupier.name] (AI Eye)" if(malf.parent) qdel(malf) - occupier.verbs += /mob/living/silicon/ai/proc/corereturn + add_verb(occupier, /mob/living/silicon/ai/proc/corereturn) occupier.cancel_camera() @@ -1173,7 +1173,7 @@ occupier.parent.shunted = 0 occupier.parent.setOxyLoss(occupier.getOxyLoss()) occupier.parent.cancel_camera() - occupier.parent.verbs -= /mob/living/silicon/ai/proc/corereturn + remove_verb(occupier.parent, /mob/living/silicon/ai/proc/corereturn) qdel(occupier) else to_chat(occupier, "Primary core damaged, unable to return core processes.") diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 54b1362518..bc921b5b26 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -66,7 +66,7 @@ var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity) var/heat = energy_transfer*(1-efficiency) - lastgen += LOGISTIC_FUNCTION(1000000,0.0034,delta_temperature,2000) + lastgen += LOGISTIC_FUNCTION(500000,0.0009,delta_temperature,10000) hot_air.set_temperature(hot_air.return_temperature() - energy_transfer/hot_air_heat_capacity) cold_air.set_temperature(cold_air.return_temperature() + heat/cold_air_heat_capacity) @@ -139,7 +139,6 @@ . = ..() var/datum/browser/popup = new(user, "teg", "Thermo-Electric Generator", 460, 300) popup.set_content(get_menu()) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/power/generator/Topic(href, href_list) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index fd8f900552..e3fdbd3654 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -639,7 +639,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(produces_gas) env.merge(removed) air_update_turf() - + /********* END CITADEL CHANGES *********/ @@ -985,6 +985,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) layer = ABOVE_MOB_LAYER moveable = TRUE +/obj/machinery/power/supermatter_crystal/shard/examine(mob/user) + . = ..() + if(anchored) + . += "[src] is anchored to the floor." + else + . += "[src] is unanchored, but can be bolted down." + /obj/machinery/power/supermatter_crystal/shard/engine name = "anchored supermatter shard" is_main_engine = TRUE @@ -1026,12 +1033,12 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(L) switch(type) if(FLUX_ANOMALY) - var/obj/effect/anomaly/flux/A = new(L, 300, FALSE) + var/obj/effect/anomaly/flux/A = new(L, 300, SUPERMATTER_ANOMALY_DROP_CHANCE) A.explosive = FALSE if(GRAVITATIONAL_ANOMALY) - new /obj/effect/anomaly/grav(L, 250, FALSE) + new /obj/effect/anomaly/grav(L, 250, SUPERMATTER_ANOMALY_DROP_CHANCE) if(PYRO_ANOMALY) - new /obj/effect/anomaly/pyro(L, 200, FALSE) + new /obj/effect/anomaly/pyro(L, 200, SUPERMATTER_ANOMALY_DROP_CHANCE) /obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list()) if(QDELETED(zapstart)) diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index eb80548441..be24ea0fef 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -160,6 +160,14 @@ buckle_lying = FALSE buckle_requires_restraints = TRUE +/obj/machinery/power/grounding_rod/Initialize() + GLOB.grounding_rods |= src + return ..() + +/obj/machinery/power/grounding_rod/Destroy() + GLOB.grounding_rods.Remove(src) + return ..() + /obj/machinery/power/grounding_rod/default_unfasten_wrench(mob/user, obj/item/I, time = 20) . = ..() if(. == SUCCESSFUL_UNFASTEN) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 06e5d27f6d..89c5aa3316 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -31,6 +31,7 @@ var/produced_power var/energy_to_raise = 32 var/energy_to_lower = -20 + var/obj/machinery/power/grounding_rod/rodtarget /obj/singularity/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE) miniball = is_miniball @@ -60,11 +61,12 @@ return //don't annnounce miniballs ..() - /obj/singularity/energy_ball/process() if(!orbiting) handle_energy() + determine_containment() + move_the_basket_ball(4 + orbiting_balls.len * 1.5) playsound(src.loc, 'sound/magic/lightningbolt.ogg', 100, TRUE, extrarange = 30) @@ -87,12 +89,19 @@ if(orbiting_balls.len) . += "There are [orbiting_balls.len] mini-balls orbiting it." - /obj/singularity/energy_ball/proc/move_the_basket_ball(var/move_amount) //we face the last thing we zapped, so this lets us favor that direction a bit var/move_bias = pick(GLOB.alldirs) + var/move_dir + for(var/rod in GLOB.grounding_rods) // grounding rods pull the tesla ball, picks the nearest one + if(!rodtarget || get_dist(src,rod)= energy_to_raise) @@ -121,6 +144,10 @@ else if(orbiting_balls.len) dissipate() //sing code has a much better system. + if(energy<=0) + investigate_log("fizzled.", INVESTIGATE_SINGULO) + qdel(src) + /obj/singularity/energy_ball/proc/new_mini_ball() if(!loc) return @@ -134,7 +161,6 @@ EB.orbit(src, orbitsize, pick(FALSE, TRUE), rand(10, 25), pick(3, 4, 5, 6, 36)) - /obj/singularity/energy_ball/Bump(atom/A) dust_mobs(A) @@ -166,7 +192,6 @@ if (!QDELETED(src)) qdel(src) - /obj/singularity/energy_ball/proc/dust_mobs(atom/A) if(isliving(A)) var/mob/living/L = A @@ -329,6 +354,12 @@ else power = closest_atom.zap_act(power, zap_flags, shocked_targets) + + var/obj/singularity/energy_ball/tesla = source + if(istype(tesla)) + if(istype(closest_atom,/obj/machinery/power/grounding_rod) && tesla.energy>13 && !tesla.contained) + qdel(closest_atom) // each rod deletes two miniballs, + tesla.energy = round(tesla.energy/1.5625) // if there are no miniballs the rod stays and continues to pull the ball in if(prob(20))//I know I know tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) diff --git a/code/modules/projectiles/ammunition/special/magic.dm b/code/modules/projectiles/ammunition/special/magic.dm index cc039c5f2b..8380bf82e9 100644 --- a/code/modules/projectiles/ammunition/special/magic.dm +++ b/code/modules/projectiles/ammunition/special/magic.dm @@ -43,3 +43,17 @@ /obj/item/ammo_casing/magic/locker projectile_type = /obj/item/projectile/magic/locker + +//Spell book ammo casing +/obj/item/ammo_casing/magic/book + projectile_type = /obj/item/projectile/magic/spellcard/book + +/obj/item/ammo_casing/magic/book/spark + projectile_type = /obj/item/projectile/magic/spellcard/book/spark + +/obj/item/ammo_casing/magic/book/heal + projectile_type = /obj/item/projectile/magic/spellcard/book/heal + harmful = FALSE + +/obj/item/ammo_casing/magic/book/shock + projectile_type = /obj/item/projectile/magic/spellcard/book/shock diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 78ca6e9280..9ea030da99 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -20,7 +20,6 @@ var/caliber var/multiload = 1 var/start_empty = 0 - var/load_delay = 0 //how long do we take to load (deciseconds) var/list/bullet_cost var/list/base_cost// override this one as well if you override bullet_cost @@ -76,19 +75,12 @@ return 1 /obj/item/ammo_box/attackby(obj/item/A, mob/user, params, silent = FALSE, replace_spent = 0) - if(INTERACTING_WITH(user, src) || INTERACTING_WITH(user, A)) - to_chat(user, "You're already doing that!") - return FALSE var/num_loaded = 0 if(!can_load(user)) return if(istype(A, /obj/item/ammo_box)) var/obj/item/ammo_box/AM = A for(var/obj/item/ammo_casing/AC in AM.stored_ammo) - if(load_delay || AM.load_delay) - var/loadtime = max(AM.load_delay, load_delay) - if(!do_after(user, loadtime, target = src)) - return FALSE var/did_load = give_round(AC, replace_spent) if(did_load) AM.stored_ammo -= AC diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index 8cd49bdf16..70058801f8 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -156,8 +156,6 @@ max_ammo = 4 var/pixeloffsetx = 4 start_empty = TRUE - multiload = FALSE - load_delay = 6 //6ds /obj/item/ammo_box/shotgun/update_overlays() . = ..() diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 1aefa51a51..fa8099a257 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -53,8 +53,6 @@ ..() if (istype(A, /obj/item/ammo_box/magazine)) var/obj/item/ammo_box/magazine/AM = A - if(AM.load_delay && !do_after(user, AM.load_delay, target = src)) - return FALSE if (!magazine && istype(AM, mag_type)) if(user.transferItemToLoc(AM, src)) magazine = AM diff --git a/code/modules/projectiles/guns/ballistic/magweapon.dm b/code/modules/projectiles/guns/ballistic/magweapon.dm index 4e27a73300..c01a2fb74a 100644 --- a/code/modules/projectiles/guns/ballistic/magweapon.dm +++ b/code/modules/projectiles/guns/ballistic/magweapon.dm @@ -51,11 +51,6 @@ cell.use(shot.energy_cost) . = ..() -/obj/item/gun/ballistic/automatic/magrifle/emp_act(severity) - . = ..() - if(!(. & EMP_PROTECT_CONTENTS)) - cell.use(round(cell.charge / severity)) - /obj/item/gun/ballistic/automatic/magrifle/get_cell() return cell diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 6f1fb96af5..a26f05d553 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -8,7 +8,7 @@ /obj/item/gun/ballistic/revolver/Initialize() . = ..() if(!istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder)) - verbs -= /obj/item/gun/ballistic/revolver/verb/spin + verbs += /obj/item/gun/ballistic/revolver/verb/spin /obj/item/gun/ballistic/revolver/chamber_round(spin = 1) if(spin) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 17dcfa96e6..0a587e8eba 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -268,7 +268,7 @@ for(var/i = ratio, i >= 1, i--) charge_overlay.pixel_x = ammo_x_offset * (i - 1) charge_overlay.pixel_y = ammo_y_offset * (i - 1) - . += charge_overlay + . += new /mutable_appearance(charge_overlay) else . += "[icon_state]_charge[ratio]" diff --git a/code/modules/projectiles/guns/magic/spell_book.dm b/code/modules/projectiles/guns/magic/spell_book.dm new file mode 100644 index 0000000000..752a6ae5ac --- /dev/null +++ b/code/modules/projectiles/guns/magic/spell_book.dm @@ -0,0 +1,66 @@ +/obj/item/gun/magic/wand/book + name = "blank spellbook" + desc = "It's not just a book, it's a SPELL book!" + ammo_type = /obj/item/ammo_casing/magic + icon = 'icons/obj/library.dmi' + icon_state = "book" + w_class = WEIGHT_CLASS_NORMAL + charges = 10 //We start with max pages + max_charges = 10 + variable_charges = FALSE + +/obj/item/gun/magic/wand/book/zap_self(mob/living/user) + to_chat(user, "The book has [charges] pages\s remaining.
    ") + +/obj/item/gun/magic/wand/book/attackby(obj/item/S, mob/living/user, params) + if(!istype(S, /obj/item/paper)) + return ..() + if(charges < max_charges) + charges++ + recharge_newshot() + to_chat(user, "You add a new page to [src].") + qdel(S) + update_icon() + process() + else + to_chat(user, "The [src] has no more room for pages!") + +////////////////////// +//Spell Book - SPARK// +////////////////////// + +/obj/item/gun/magic/wand/book/spark + name = "Spell Book of Spark" + desc = "A spell book that fires burn pages to set the target ablaze!" + ammo_type = /obj/item/ammo_casing/magic/book/spark + icon_state = "spellbook_spark" + +////////////////////// +//Spell Book - PAGE/// +////////////////////// + +/obj/item/gun/magic/wand/book/page + name = "Spell Book of Throw" + desc = "A spell book that throws pages at its target!" + ammo_type = /obj/item/ammo_casing/magic/book + icon_state = "spellbook_page" + +////////////////////// +//Spell Book - SHOCK// +////////////////////// + +/obj/item/gun/magic/wand/book/shock + name = "Spell Book of Shock" + desc = "A spell book that uses its pages to capture energy in the air and send it in a bolt at its target!" + ammo_type = /obj/item/ammo_casing/magic/book/shock + icon_state = "spellbook_shock" + +//////////////////////// +//Spell Book - HEALING// +//////////////////////// + +/obj/item/gun/magic/wand/book/healing + name = "Spell Book of Mending" + desc = "A spell book that uses its pages to heal and repair the target! The back of the book lists what it works on, and it seems to only be of flesh and of metal beings..." + ammo_type = /obj/item/ammo_casing/magic/book/heal + icon_state = "spellbook_healing" diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 99a0bedc4d..4e81c5aeb6 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -460,6 +460,7 @@ return TRUE //Bullets don't drift in space /obj/item/projectile/process(wait) + set waitfor = FALSE if(!loc || !fired || !trajectory) fired = FALSE return PROCESS_KILL diff --git a/code/modules/projectiles/projectile/magic/spellcard.dm b/code/modules/projectiles/projectile/magic/spellcard.dm index 1b8f326573..5015a97e78 100644 --- a/code/modules/projectiles/projectile/magic/spellcard.dm +++ b/code/modules/projectiles/projectile/magic/spellcard.dm @@ -4,3 +4,60 @@ icon_state = "spellcard" damage_type = BURN damage = 2 + +/obj/item/projectile/magic/spellcard/book + nodamage = FALSE + name = "enchanted page" + desc = "A piece of paper enchanted to give it extreme durability and stiffness, along with a very hot burn to anyone unfortunate enough to get hit by a charged one." + icon_state = "spellcard" + damage_type = BURN + damage = 12 + flag = "magic" + +/obj/item/projectile/magic/spellcard/book/spark + damage = 4 + var/fire_stacks = 4 + +/obj/item/projectile/magic/spellcard/book/spark/on_hit(atom/target, blocked = FALSE) + . = ..() + var/mob/living/carbon/M = target + if(ismob(target)) + if(M.anti_magic_check()) + M.visible_message("[src] vanishes on contact with [target]!") + return BULLET_ACT_BLOCK + + if(iscarbon(target)) + M.adjust_fire_stacks(fire_stacks) + M.IgniteMob() + return + else + damage = 20 //If we are a simplemob we deal 5x damage + +/obj/item/projectile/magic/spellcard/book/shock + damage = 0 + stamina = 11 + stutter = 5 + jitter = 20 + knockdown = 10 + +/obj/item/projectile/magic/spellcard/book/heal + damage = 0 + nodamage = TRUE + +/obj/item/projectile/magic/spellcard/book/heal/on_hit(atom/target, blocked = FALSE) + . = ..() + var/mob/living/carbon/M = target + if(ismob(target)) + if(M.anti_magic_check()) + M.visible_message("[src] vanishes on contact with [target]!") + return BULLET_ACT_BLOCK + if(iscarbon(target)) + M.visible_message("[src] mends [target]!") + M.adjustBruteLoss(-5) //HEALS + M.adjustOxyLoss(-5) + M.adjustBruteLoss(-5) + M.adjustFireLoss(-5) + M.adjustToxLoss(-5, TRUE) //heals TOXINLOVERs + M.adjustCloneLoss(-5) + M.adjustStaminaLoss(-5) + return diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 4034759c72..289b92f06d 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -2280,6 +2280,7 @@ All effects don't start immediately, but rather get worse over time; the rate is quality = RACE_DRINK else C.adjust_disgust(disgust) + return ..() /datum/reagent/consumable/ethanol/species_drink/coldscales name = "Coldscales" @@ -2289,7 +2290,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "coldscales" glass_name = "glass of Coldscales" glass_desc = "A soft green drink that looks inviting!" - species_required = "lizard" /datum/reagent/consumable/ethanol/species_drink/oil_drum @@ -2301,7 +2301,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "oil_drum" glass_name = "Drum of oil" glass_desc = "A gray can of booze and oil..." - species_required = "robot" /datum/reagent/consumable/ethanol/species_drink/nord_king @@ -2312,7 +2311,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "nord_king" glass_name = "Keg of Nord King" glass_desc = "A dripping keg of red mead." - species_required = "basic" /datum/reagent/consumable/ethanol/species_drink/velvet_kiss @@ -2324,7 +2322,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "velvet_kiss" glass_name = "glass of Velvet Kiss" glass_desc = "Red and white drink for the upper classes or undead." - species_required = "undead" /datum/reagent/consumable/ethanol/species_drink/abduction_fruit @@ -2336,7 +2333,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "abduction_fruit" glass_name = "glass of Abduction Fruit" glass_desc = "Mixed fruits that were never meant to be mixed..." - species_required = "alien" /datum/reagent/consumable/ethanol/species_drink/bug_zapper @@ -2348,7 +2344,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "bug_zapper" glass_name = "glass of Bug Zapper" glass_desc = "An odd mix of copper, lemon juice and power meant for non-human consumption." - species_required = "bug" /datum/reagent/consumable/ethanol/species_drink/mush_crush @@ -2360,7 +2355,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "mush_crush" glass_name = "glass of Mush Crush" glass_desc = "Popular among people that want to grow their own food rather than drink the soil." - species_required = "plant" /datum/reagent/consumable/ethanol/species_drink/darkbrew @@ -2372,7 +2366,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "darkbrew" glass_name = "glass of Darkbrew" glass_desc = "A pitch black drink that's commonly confused with a type of coffee." - species_required = "shadow" /datum/reagent/consumable/ethanol/species_drink/hollow_bone @@ -2384,7 +2377,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "hollow_bone" glass_name = "skull of Hollow Bone" glass_desc = "Mixing of milk and bone hurting juice for the enjoyment of rather skinny people." - species_required = "skeleton" /datum/reagent/consumable/ethanol/species_drink/frisky_kitty @@ -2396,7 +2388,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "frisky_kitty" glass_name = "cup of Drisky Kitty" glass_desc = "Warm milk and some catnip." - species_required = "furry" /datum/reagent/consumable/ethanol/species_drink/jell_wyrm @@ -2408,7 +2399,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "jell_wyrm" glass_name = "glass of Jell Wyrm" glass_desc = "A bubbly drink that is rather inviting to those that don't know who it's meant for." - species_required = "jelly" /datum/reagent/consumable/ethanol/species_drink/laval_spit //Yes Laval @@ -2420,7 +2410,6 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "laval_spit" glass_name = "glass of Laval Spit" glass_desc = "Piping hot drink for those who can stomach the heat of lava." - species_required = "golem" /////////////// diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index e1433eb64e..3675efa283 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -329,7 +329,7 @@ color = "#101000" // rgb: 16, 16, 0 nutriment_factor = 0 taste_description = "sweet red tea" - glass_icon_state = "teaglass" + glass_icon_state = "tea_red" glass_name = "glass of red tea" glass_desc = "A piping hot tea that helps with the digestion of food." @@ -340,6 +340,7 @@ M.drowsyness = max(0,M.drowsyness-1) M.jitteriness = max(0,M.jitteriness-3) M.adjust_bodytemperature(23 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + ..() . = 1 /datum/reagent/consumable/tea/green @@ -348,7 +349,7 @@ color = "#101000" // rgb: 16, 16, 0 nutriment_factor = 0 taste_description = "tart green tea" - glass_icon_state = "teaglass" + glass_icon_state = "tea_green" glass_name = "glass of tea" glass_desc = "A calming glass of green tea to help get you through the day." @@ -358,6 +359,7 @@ M.drowsyness = max(0,M.drowsyness-1) M.jitteriness = max(0,M.jitteriness-3) M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + ..() . = 1 /datum/reagent/consumable/tea/forest @@ -367,7 +369,7 @@ nutriment_factor = 0 quality = DRINK_NICE taste_description = "sweet tea" - glass_icon_state = "teaglass" + glass_icon_state = "tea_forest" glass_name = "glass of forest tea" glass_desc = "A lovely glass of tea and honey." @@ -379,6 +381,7 @@ M.drowsyness = max(0,M.drowsyness-1) M.jitteriness = max(0,M.jitteriness-3) M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + ..() . = 1 /datum/reagent/consumable/tea/mush @@ -388,7 +391,7 @@ nutriment_factor = 0 quality = DRINK_NICE taste_description = "fungal infections" - glass_icon_state = "teaglass" + glass_icon_state = "tea_mush" glass_name = "glass of mush tea" glass_desc = "A cold merky brown tea." @@ -398,6 +401,7 @@ M.Dizzy(10) if(prob(10)) M.disgust = 0 + ..() . = 1 /datum/reagent/consumable/lemonade diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5c01fd8cf6..86f8b341d9 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2220,6 +2220,7 @@ color = "#f7685e" metabolization_rate = REAGENTS_METABOLISM * 0.25 + /datum/reagent/wittel name = "Wittel" description = "An extremely rare metallic-white substance only found on demon-class planets." @@ -2281,6 +2282,7 @@ /datum/reagent/gravitum/on_mob_end_metabolize(mob/living/L) L.RemoveElement(/datum/element/forced_gravity, 0) + //body bluids /datum/reagent/consumable/semen name = "Semen" @@ -2457,3 +2459,56 @@ datum/reagent/eldritch return ..() +/datum/reagent/red_ichor + name = "Red Ichor" + can_synth = FALSE + description = "A unknown red liquid, linked to healing of most moral wounds." + color = "#c10000" + metabolization_rate = REAGENTS_METABOLISM * 2.5 + +/datum/reagent/red_ichor/on_mob_life(mob/living/carbon/M) + M.adjustBruteLoss(-50) + M.adjustOxyLoss(-50) + M.adjustBruteLoss(-50) + M.adjustFireLoss(-50) + M.adjustToxLoss(-50, TRUE) //heals TOXINLOVERs + M.adjustCloneLoss(-50) + M.adjustStaminaLoss(-50) + ..() + +/datum/reagent/green_ichor + name = "Green Ichor" + can_synth = FALSE + description = "A unknown green liquid, linked to healing of most internal wounds." + color = "#158c00" + metabolization_rate = REAGENTS_METABOLISM * 2.5 + +/datum/reagent/green_ichor/on_mob_life(mob/living/carbon/M) + M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -100) + M.adjustOrganLoss(ORGAN_SLOT_HEART, -100) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, -100) + M.adjustOrganLoss(ORGAN_SLOT_EARS, -100) + M.adjustOrganLoss(ORGAN_SLOT_STOMACH, -100) + M.adjustOrganLoss(ORGAN_SLOT_TONGUE, -100) + M.adjustOrganLoss(ORGAN_SLOT_EYES, -100) + ..() + +/datum/reagent/blue_ichor + name = "Blue Ichor" + can_synth = FALSE + description = "A unknown blue liquid, linked to healing the mind." + color = "#0914e0" + metabolization_rate = REAGENTS_METABOLISM * 2.5 + +/datum/reagent/blue_ichor/on_mob_life(mob/living/carbon/M) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -100) + M.cure_all_traumas(TRAUMA_RESILIENCE_MAGIC) + M.hallucination = 0 + M.dizziness = 0 + M.disgust = 0 + M.drowsyness = 0 + M.stuttering = 0 + M.confused = 0 + M.SetSleeping(0, 0) + ..() + diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index b71584982c..be631513bd 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -70,7 +70,6 @@ return /obj/item/reagent_containers/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) - . = ..() if(user.a_intent == INTENT_HARM) return ..() diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index 20abcf847f..2cd0a76a4b 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -416,3 +416,20 @@ /obj/item/reagent_containers/glass/bottle/bromine name = "bromine bottle" list_reagents = list(/datum/reagent/bromine = 30) + +//Ichors +/obj/item/reagent_containers/glass/bottle/ichor + possible_transfer_amounts = list(1) + volume = 1 + +/obj/item/reagent_containers/glass/bottle/ichor/red + name = "healing potion" + list_reagents = list(/datum/reagent/red_ichor = 1) + +/obj/item/reagent_containers/glass/bottle/ichor/blue + name = "blue potion" + list_reagents = list(/datum/reagent/blue_ichor = 1) + +/obj/item/reagent_containers/glass/bottle/ichor/green + name = "green potion" + list_reagents = list(/datum/reagent/green_ichor = 1) \ No newline at end of file diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index c8da9ab5e3..b106005a15 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -263,7 +263,7 @@ . = ..() if(.) return - for(var/obj/item/I in src_object) + for(var/obj/item/I in src_object.contents()) if(user.active_storage != src_object) if(I.on_found(user)) return diff --git a/code/modules/research/anomaly/explosive_compressor.dm b/code/modules/research/anomaly/explosive_compressor.dm new file mode 100644 index 0000000000..23983e31dc --- /dev/null +++ b/code/modules/research/anomaly/explosive_compressor.dm @@ -0,0 +1,152 @@ +#define MAX_RADIUS_REQUIRED 8000 //tritbomb +#define MIN_RADIUS_REQUIRED 20 //maxcap +/** + * # Explosive compressor machines + * + * The explosive compressor machine used in anomaly core production. + * + * Uses the standard toxins/tank explosion scaling to compress raw anomaly cores into completed ones. The required explosion radius increases as more cores of that type are created. + */ +/obj/machinery/research/explosive_compressor + name = "implosion compressor" + desc = "An advanced machine capable of implosion-compressing raw anomaly cores into finished artifacts." + icon = 'icons/obj/machines/research.dmi' + icon_state = "explosive_compressor" + density = TRUE + circuit = /obj/item/circuitboard/machine/explosive_compressor + + /// The raw core inserted in the machine. + var/obj/item/raw_anomaly_core/inserted_core + /// The TTV inserted in the machine. + var/obj/item/transfer_valve/inserted_bomb + /// The last time we did say_requirements(), because someone will inevitably click spam this. + var/last_requirements_say = 0 + +/obj/machinery/research/explosive_compressor/examine(mob/user) + . = ..() + . += "Ctrl-Click to remove an inserted core." + . += "Click with an empty hand to gather information about the required radius of an inserted core. Insert a ready TTV to start the implosion process if a core is inserted." + +/obj/machinery/research/explosive_compressor/attack_hand(mob/living/user) + . = ..() + if(.) + return + if(!inserted_core) + to_chat(user, "There is no core inserted.") + return + if(last_requirements_say + 3 SECONDS > world.time) + return + last_requirements_say = world.time + say_requirements(inserted_core) + +/obj/machinery/research/explosive_compressor/CtrlClick(mob/living/user) + . = ..() + if(!istype(user) || !user.Adjacent(src) || !(user.mobility_flags & MOBILITY_USE)) + return + if(!inserted_core) + to_chat(user, "There is no core inserted.") + return + inserted_core.forceMove(get_turf(user)) + to_chat(user, "You remove [inserted_core] from [src].") + user.put_in_hands(inserted_core) + inserted_core = null + +/** + * Says (no, literally) the data of required explosive power for a certain anomaly type. + */ +/obj/machinery/research/explosive_compressor/proc/say_requirements(obj/item/raw_anomaly_core/C) + var/required = get_required_radius(C.anomaly_type) + if(isnull(required)) + say("Unfortunately, due to diminishing supplies of condensed anomalous matter, [C] and any cores of its type are no longer of a sufficient quality level to be compressed into a working core.") + else + say("[C] requires a minimum of a theoretical radius of [required] to successfully implode into a charged anomaly core.") + +/** + * Determines how much explosive power (last value, so light impact theoretical radius) is required to make a certain anomaly type. + * + * Returns null if the max amount has already been reached. + * + * Arguments: + * * anomaly_type - anomaly type define + */ +/obj/machinery/research/explosive_compressor/proc/get_required_radius(anomaly_type) + var/already_made = SSresearch.created_anomaly_types[anomaly_type] + var/hard_limit = SSresearch.anomaly_hard_limit_by_type[anomaly_type] + if(already_made >= hard_limit) + return //return null + // my crappy autoscale formula + // linear scaling. + var/radius_span = MAX_RADIUS_REQUIRED - MIN_RADIUS_REQUIRED + var/radius_increase_per_core = radius_span / hard_limit + var/radius = clamp(round(MIN_RADIUS_REQUIRED + radius_increase_per_core * already_made, 1), MIN_RADIUS_REQUIRED, MAX_RADIUS_REQUIRED) + return radius + +/obj/machinery/research/explosive_compressor/attackby(obj/item/I, mob/living/user, params) + if(default_unfasten_wrench(user, I)) + return + if(default_deconstruction_screwdriver(user, "explosive_compressor", "explosive_compressor", I)) + return + if(default_deconstruction_crowbar(I)) + return + . = ..() + if(istype(I, /obj/item/raw_anomaly_core)) + if(inserted_core) + to_chat(user, "There is already a core in [src].") + return + if(!user.transferItemToLoc(I, src)) + to_chat(user, "[I] is stuck to your hand.") + return + inserted_core = I + to_chat(user, "You insert [I] into [src].") + return + if(istype(I, /obj/item/transfer_valve)) + // If they don't have a bomb core inserted, don't let them insert this. If they do, insert and do implosion. + if(!inserted_core) + to_chat(user, "There is no core inserted in [src]. What would be the point of detonating an implosion without a core?") + return + var/obj/item/transfer_valve/valve = I + if(!valve.ready()) + to_chat(user, "[valve] is incomplete.") + return + if(!user.transferItemToLoc(I, src)) + to_chat(user, "[I] is stuck to your hand.") + return + inserted_bomb = I + to_chat(user, "You insert [I] and press the start button.") + do_implosion() + +/** + * The ""explosion"" proc. + */ +/obj/machinery/research/explosive_compressor/proc/do_implosion() + var/required_radius = get_required_radius(inserted_core.anomaly_type) + // By now, we should be sure that we have a core, a TTV, and that the TTV has both tanks in place. + var/datum/gas_mixture/mix1 = inserted_bomb.tank_one.air_contents + var/datum/gas_mixture/mix2 = inserted_bomb.tank_two.air_contents + // Snowflaked tank explosion + var/datum/gas_mixture/mix = new(70) // Standard tank volume, 70L + mix.merge(mix1) + mix.merge(mix2) + mix.react() + if(mix.return_pressure() < TANK_FRAGMENT_PRESSURE) + // They failed so miserably we're going to give them their bomb back. + inserted_bomb.forceMove(drop_location()) + inserted_bomb = null + inserted_core.forceMove(drop_location()) + inserted_core = null + say("Transfer valve resulted in negligible explosive power. Items ejected.") + return + mix.react() // build more pressure + var/pressure = mix.return_pressure() + var/range = (pressure - TANK_FRAGMENT_PRESSURE) / TANK_FRAGMENT_SCALE + QDEL_NULL(inserted_bomb) // bomb goes poof + if(range < required_radius) + inserted_bomb.forceMove(src) + say("Resultant detonation failed to produce enough implosive power to compress [inserted_core]. Core ejected.") + return + inserted_core.create_core(drop_location(), TRUE, TRUE) + inserted_core = null + say("Success. Resultant detonation has theoretical range of [range]. Required radius was [required_radius]. Core production complete.") + +#undef MAX_RADIUS_REQUIRED +#undef MIN_RADIUS_REQUIRED diff --git a/code/modules/research/anomaly/raw_anomaly.dm b/code/modules/research/anomaly/raw_anomaly.dm new file mode 100644 index 0000000000..2342edd28f --- /dev/null +++ b/code/modules/research/anomaly/raw_anomaly.dm @@ -0,0 +1,73 @@ +/** + * # Raw Anomaly Cores + * + * The current precursor to anomaly cores, these are manufactured into 'finished' anomaly cores for use in research, items, and more. + * + * The current amounts created is stored in SSresearch.created_anomaly_types[ANOMALY_CORE_TYPE_DEFINE] = amount + * The hard limits are in code/__DEFINES/anomalies.dm + */ +/obj/item/raw_anomaly_core + name = "raw anomaly core" + desc = "You shouldn't be seeing this. Someone screwed up." + icon = 'icons/obj/assemblies/new_assemblies.dmi' + icon_state = "broken_state" + + /// Anomaly type + var/anomaly_type + +/obj/item/raw_anomaly_core/bluespace + name = "raw bluespace core" + desc = "The raw core of a bluespace anomaly, glowing and full of potential." + anomaly_type = /obj/item/assembly/signaler/anomaly/bluespace + icon_state = "rawcore_bluespace" + +/obj/item/raw_anomaly_core/vortex + name = "raw vortex core" + desc = "The raw core of a vortex anomaly. Feels heavy to the touch." + anomaly_type = /obj/item/assembly/signaler/anomaly/vortex + icon_state = "rawcore_vortex" + +/obj/item/raw_anomaly_core/grav + name = "raw gravity core" + desc = "The raw core of a gravity anomaly. The air seems attracted to it." + anomaly_type = /obj/item/assembly/signaler/anomaly/grav + icon_state = "rawcore_grav" + +/obj/item/raw_anomaly_core/pyro + desc = "The raw core of a pyro anomaly. It is warm to the touch." + name = "raw pyro core" + anomaly_type = /obj/item/assembly/signaler/anomaly/pyro + icon_state = "rawcore_pyro" + +/obj/item/raw_anomaly_core/flux + name = "raw flux core" + desc = "The raw core of a flux anomaly, faintly crackling with energy." + anomaly_type = /obj/item/assembly/signaler/anomaly/flux + icon_state = "rawcore_flux" + +/obj/item/raw_anomaly_core/random + name = "random raw core" + desc = "You should not see this!" + icon_state = "rawcore_bluespace" + +/obj/item/raw_anomaly_core/random/Initialize(mapload) + . = ..() + var/path = pick(subtypesof(/obj/item/raw_anomaly_core)) + new path(loc) + return INITIALIZE_HINT_QDEL + +/** + * Created the resulting core after being "made" into it. + * + * Arguments: + * * newloc - Where the new core will be created + * * del_self - should we qdel(src) + * * count_towards_limit - should we increment the amount of created cores on SSresearch + */ +/obj/item/raw_anomaly_core/proc/create_core(newloc, del_self = FALSE, count_towards_limit = FALSE) + . = new anomaly_type(newloc) + if(count_towards_limit) + var/existing = SSresearch.created_anomaly_types[anomaly_type] || 0 + SSresearch.created_anomaly_types[anomaly_type] = existing + 1 + if(del_self) + qdel(src) diff --git a/code/modules/research/designs/computer_part_designs.dm b/code/modules/research/designs/computer_part_designs.dm index ab487b0aaa..db37b13e87 100644 --- a/code/modules/research/designs/computer_part_designs.dm +++ b/code/modules/research/designs/computer_part_designs.dm @@ -143,7 +143,7 @@ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING // APC Link -/datum/design/APClink +/datum/design/apc_link name = "Area Power Connector" id = "APClink" build_type = PROTOLATHE @@ -230,7 +230,7 @@ name = "Photonic Processor Board" id = "pcpu_normal" build_type = IMPRINTER - materials = list(/datum/material/glass= 6400, /datum/material/gold = 2000) + materials = list(/datum/material/glass = 6400, /datum/material/gold = 2000) build_path = /obj/item/computer_hardware/processor_unit/photonic category = list("Computer Parts") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING @@ -243,3 +243,12 @@ build_path = /obj/item/computer_hardware/processor_unit/photonic/small category = list("Computer Parts") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/sensorpackage + name = "Sensor Package" + id = "sensorpackage" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 200, /datum/material/glass = 100, /datum/material/gold = 50, /datum/material/silver = 50) + build_path = /obj/item/computer_hardware/sensorpackage + category = list("Computer Parts") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 0a9fce2e67..7013412e6d 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -354,6 +354,16 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL +/datum/design/portable_chem_mixer + name = "Portable Chemical Mixer" + desc = "A portable device that dispenses and mixes chemicals. Reagents have to be supplied with beakers." + id = "portable_chem_mixer" + build_type = PROTOLATHE + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + materials = list(/datum/material/plastic = 5000, /datum/material/iron = 10000, /datum/material/glass = 3000) + build_path = /obj/item/storage/portable_chem_mixer + category = list("Equipment") + ///////////////////////////////////////// //////////Cybernetic Implants//////////// ///////////////////////////////////////// diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 1b608060ce..a54fe857e9 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -375,7 +375,7 @@ materials = list(/datum/material/iron = 1500, /datum/material/silver = 150, /datum/material/glass = 3000) build_path = /obj/item/lightreplacer category = list("Equipment") - departmental_flags = DEPARTMENTAL_FLAG_SERVICE + departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_ENGINEERING /datum/design/normtrash name = "Trashbag" @@ -469,7 +469,7 @@ build_type = PROTOLATHE materials = list(/datum/material/iron = 5000, /datum/material/glass = 1000, /datum/material/gold = 1000, /datum/material/silver = 1000) build_path = /obj/item/holosign_creator/engineering - category = list("Equipment") + category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING /datum/design/holosignatmos @@ -479,7 +479,7 @@ build_type = PROTOLATHE materials = list(/datum/material/iron = 5000, /datum/material/glass = 1000, /datum/material/gold = 1000, /datum/material/silver = 1000) build_path = /obj/item/holosign_creator/atmos - category = list("Equipment") + category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING /datum/design/holosignfirelock @@ -489,7 +489,7 @@ build_type = PROTOLATHE materials = list(/datum/material/iron = 5000, /datum/material/glass = 1000, /datum/material/gold = 1000, /datum/material/silver = 1000) build_path = /obj/item/holosign_creator/firelock - category = list("Equipment") + category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING /datum/design/holosigncombifan @@ -499,7 +499,7 @@ build_type = PROTOLATHE materials = list(/datum/material/iron = 7500, /datum/material/glass = 2500, /datum/material/silver = 2500, /datum/material/gold = 2500, /datum/material/titanium = 1750) build_path = /obj/item/holosign_creator/combifan - category = list("Equipment") + category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING /datum/design/forcefield_projector @@ -509,7 +509,7 @@ build_type = PROTOLATHE materials = list(/datum/material/iron = 2500, /datum/material/glass = 1000) build_path = /obj/item/forcefield_projector - category = list("Equipment") + category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING /datum/design/holobarrier_med diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index 4fe07cb02f..5ef050efe9 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -97,7 +97,7 @@ desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range." id = "ranged_analyzer" build_type = PROTOLATHE - materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/plastic = 200) + materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/diamond = 50) build_path = /obj/item/analyzer/ranged category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/techweb/nodes/computer_hud_nodes.dm b/code/modules/research/techweb/nodes/computer_hud_nodes.dm index 2835edc52b..2db03861e9 100644 --- a/code/modules/research/techweb/nodes/computer_hud_nodes.dm +++ b/code/modules/research/techweb/nodes/computer_hud_nodes.dm @@ -13,10 +13,10 @@ display_name = "Computer Hardware" description = "How computer hardware are made." prereq_ids = list("comptech") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) //they are really kinda shitty + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) //they are really shitty design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", - "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") + "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small", "sensorpackage") /datum/techweb_node/comp_recordkeeping id = "comp_recordkeeping" diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index d97eae5766..4859fcfca0 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -183,6 +183,13 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) . = ..() promptAndCheckIn(user) +/obj/item/hilbertshotel/ghostdojo/linkTurfs(datum/turf_reservation/currentReservation, currentRoomnumber) + . = ..() + var/area/hilbertshotel/currentArea = get_area(locate(currentReservation.bottom_left_coords[1], currentReservation.bottom_left_coords[2], currentReservation.bottom_left_coords[3])) + for(var/turf/closed/indestructible/hoteldoor/door in currentArea) + door.parentSphere = src + door.desc = "The door to this hotel room. Strange, this door doesnt even seem openable. The doorknob, however, seems to buzz with unusual energy...
    Alt-Click to look through the peephole." + //Template Stuff /datum/map_template/hilbertshotel name = "Hilbert's Hotel Room" diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm index 52fafb81be..99357d802a 100644 --- a/code/modules/security_levels/security_levels.dm +++ b/code/modules/security_levels/security_levels.dm @@ -86,7 +86,7 @@ GLOBAL_LIST_INIT(all_security_levels, list("green", "blue", "amber", "red", "del if(is_station_level(FA.z)) FA.update_icon() for(var/obj/machinery/computer/shuttle/pod/pod in GLOB.machines) - pod.admin_controlled = 0 + pod.admin_controlled = FALSE if(SEC_LEVEL_DELTA) minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!",1) if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) @@ -102,7 +102,7 @@ GLOBAL_LIST_INIT(all_security_levels, list("green", "blue", "amber", "red", "del if(is_station_level(FA.z)) FA.update_icon() for(var/obj/machinery/computer/shuttle/pod/pod in GLOB.machines) - pod.admin_controlled = 0 + pod.admin_controlled = FALSE if(level >= SEC_LEVEL_RED) for(var/obj/machinery/door/D in GLOB.machines) if(D.red_alert_access) diff --git a/code/modules/shielding/helpers.dm b/code/modules/shielding/helpers.dm new file mode 100644 index 0000000000..8995cc3b03 --- /dev/null +++ b/code/modules/shielding/helpers.dm @@ -0,0 +1,65 @@ +//////// HELPER FILE FOR SHIELDING ///////// + +// HULL SHIELD GENERATION HELPERS +/** + * Gets hull exterior adjacent tiles of a certain area + * Area method. + * EXPENSIVE. + * If the area itself is already considered exterior, it'll find all tiles inside it that's next to an interior area. + */ +/proc/hull_shielding_get_tiles_around_area(area/instance, check_tick = FALSE) + var/list/cache = list() + var/area/A + if(instance.considered_hull_exterior) + for(var/turf/potential in instance) + for(var/turf/looking in orange(1, potential)) + A = looking.loc + if(!A.considered_hull_exterior) + cache[potential] = TRUE // we're the exterior area, grab the one that's reaching out + if(check_tick) + CHECK_TICK + else + for(var/turf/potential in instance) + for(var/turf/looking in orange(1, potential)) + A = looking.loc + if(A.considered_hull_exterior) + cache[looking] = TRUE // we're not the exterior area, grab the one that's being reached to + if(check_tick) + CHECK_TICK + . = list() + for(var/i in cache) + . += i // strip assoc value + +/** + * Gets hull adjacent exterior tiles of an entire zlevel + * EXPENSIVE. + * Gets the tiles in the exterior area touching to a non-exterior area + */ +/proc/hull_shielding_get_tiles_in_z(zlevel, check_tick = FALSE, recurse = FALSE, list/outlist = list(), list/scanned_zlevels = list()) + . = outlist + if(zlevel in scanned_zlevels) + return + scanned_zlevels |= zlevel + if(recurse) + var/up = SSmapping.level_trait(zlevel, ZTRAIT_UP) + var/down = SSmapping.level_trait(zlevel, ZTRAIT_DOWN) + if(isnum(up) && (up != 0)) + hull_shielding_get_tiles_in_z(up, check_tick, recurse, outlist, scanned_zlevels) + if(isnum(down) && (down != 0)) + hull_shielding_get_tiles_in_z(down, check_tick, recurse, outlist, scanned_zlevels) + // sigh. why. + var/turf/potential + var/area/p_area + var/area/l_area + for(var/x in 1 to world.maxx) + for(var/y in 1 to world.maxy) + if(check_tick) + CHECK_TICK + potential = locate(x, y, zlevel) + p_area = potential.loc + if(!p_area.considered_hull_exterior) + continue + for(var/turf/looking in orange(1, potential)) + l_area = looking.loc + if(!l_area.considered_hull_exterior) + outlist += potential diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm index 682a7fa14b..4b7e65c0f3 100644 --- a/code/modules/shuttle/computer.dm +++ b/code/modules/shuttle/computer.dm @@ -5,63 +5,109 @@ icon_keyboard = "tech_key" light_color = LIGHT_COLOR_CYAN req_access = list( ) + /// ID of the attached shuttle var/shuttleId + /// Possible destinations of the attached shuttle var/possible_destinations = "" - var/admin_controlled - var/no_destination_swap = 0 + /// Variable dictating if the attached shuttle requires authorization from the admin staff to move + var/admin_controlled = FALSE + /// Variable dictating if the attached shuttle is forbidden to change destinations mid-flight + var/no_destination_swap = FALSE + /// ID of the currently selected destination of the attached shuttle + var/destination + /// Authorization request cooldown to prevent request spam to admin staff + COOLDOWN_DECLARE(request_cooldown) -/obj/machinery/computer/shuttle/ui_interact(mob/user) - . = ..() +/obj/machinery/computer/shuttle/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ShuttleConsole", name) + ui.open() + +/obj/machinery/computer/shuttle/ui_data(mob/user) + var/list/data = list() var/list/options = params2list(possible_destinations) var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) - var/dat = "Status: [M ? M.getStatusText() : "*Missing*"]

    " - if(M) - var/destination_found - for(var/obj/docking_port/stationary/S in SSshuttle.stationary) - if(!options.Find(S.id)) - continue - if(!M.check_dock(S, silent=TRUE)) - continue - destination_found = 1 - dat += "Send to [S.name]
    " - if(!destination_found) - dat += "Shuttle Locked
    " - if(admin_controlled) - dat += "Authorized personnel only
    " - dat += "Request Authorization
    " - dat += "Close" + data["docked_location"] = M ? M.get_status_text_tgui() : "Unknown" + data["locations"] = list() + data["locked"] = FALSE + data["authorization_required"] = admin_controlled + data["timer_str"] = M ? M.getTimerStr() : "00:00" + data["destination"] = destination + if(!M) + data["status"] = "Missing" + return data + if(admin_controlled) + data["status"] = "Unauthorized Access" + else + data["status"] = M.mode == SHUTTLE_IGNITING ? "Igniting" : M.mode != SHUTTLE_IDLE ? "In Transit" : "Idle" + for(var/obj/docking_port/stationary/S in SSshuttle.stationary) + if(!options.Find(S.id)) + continue + if(!M.check_dock(S, silent = TRUE)) + continue + var/list/location_data = list( + id = S.id, + name = S.name + ) + data["locations"] += list(location_data) + if(length(data["locations"]) == 1) + for(var/location in data["locations"]) + destination = location["id"] + data["destination"] = destination + if(!length(data["locations"])) + data["locked"] = TRUE + data["status"] = "Locked" + return data - var/datum/browser/popup = new(user, "computer", M ? M.name : "shuttle", 300, 200) - popup.set_content("
    [dat]
    ") - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/shuttle/Topic(href, href_list) - if(..()) +/obj/machinery/computer/shuttle/ui_act(action, params) + . = ..() + if(.) return - usr.set_machine(src) - src.add_fingerprint(usr) if(!allowed(usr)) to_chat(usr, "Access denied.") return - if(href_list["move"]) - var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) - if(M.launch_status == ENDGAME_LAUNCHED) - to_chat(usr, "You've already escaped. Never going back to that place again!") - return - if(no_destination_swap) - if(M.mode != SHUTTLE_IDLE) - to_chat(usr, "Shuttle already in transit.") + switch(action) + if("move") + var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) + if(M.launch_status == ENDGAME_LAUNCHED) + to_chat(usr, "You've already escaped. Never going back to that place again!") return - switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1)) - if(0) - say("Shuttle departing. Please stand away from the doors.") - log_shuttle("[key_name(usr)] has sent shuttle \"[M]\" towards \"[href_list["move"]]\", using [src].") - if(1) - to_chat(usr, "Invalid shuttle requested.") - else - to_chat(usr, "Unable to comply.") + if(no_destination_swap) + if(M.mode == SHUTTLE_RECHARGING) + to_chat(usr, "Shuttle engines are not ready for use.") + return + if(M.mode != SHUTTLE_IDLE) + to_chat(usr, "Shuttle already in transit.") + return + var/list/options = params2list(possible_destinations) + if(!(params["shuttle_id"] in options)) + log_admin("[usr] attempted to href dock exploit on [src] with target location \"[params["shuttle_id"]]\"") + message_admins("[usr] just attempted to href dock exploit on [src] with target location \"[params["shuttle_id"]]\"") + return + switch(SSshuttle.moveShuttle(shuttleId, params["shuttle_id"], 1)) + if(0) + say("Shuttle departing. Please stand away from the doors.") + log_shuttle("[key_name(usr)] has sent shuttle \"[M]\" towards \"[params["shuttle_id"]]\", using [src].") + return TRUE + if(1) + to_chat(usr, "Invalid shuttle requested.") + else + to_chat(usr, "Unable to comply.") + if("set_destination") + var/target_destination = params["destination"] + if(target_destination) + destination = target_destination + return TRUE + if("request") + if(!COOLDOWN_FINISHED(src, request_cooldown)) + to_chat(usr, "CentCom is still processing last authorization request!") + return + COOLDOWN_START(src, request_cooldown, 1 MINUTES) + to_chat(usr, "Your request has been received by CentCom.") + to_chat(GLOB.admins, "FERRY: [ADMIN_LOOKUPFLW(usr)] (Move Ferry) is requesting to move the transport ferry to CentCom.") + return TRUE /obj/machinery/computer/shuttle/emag_act(mob/user) . = ..() diff --git a/code/modules/shuttle/custom_shuttle.dm b/code/modules/shuttle/custom_shuttle.dm index c71b6ba9a8..8047e972db 100644 --- a/code/modules/shuttle/custom_shuttle.dm +++ b/code/modules/shuttle/custom_shuttle.dm @@ -68,7 +68,6 @@ popup = new(user, "computer", M ? M.name : "shuttle", 350, 450) popup.set_content("
    [dat]
    ") - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/custom_shuttle/Topic(href, href_list) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 810cadcd2c..15f9b31302 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -528,7 +528,7 @@ /obj/machinery/computer/shuttle/pod name = "pod control computer" - admin_controlled = 1 + admin_controlled = TRUE possible_destinations = "pod_asteroid" icon = 'icons/obj/terminals.dmi' icon_state = "dorm_available" diff --git a/code/modules/shuttle/ferry.dm b/code/modules/shuttle/ferry.dm index 39bde5e541..892e135bdf 100644 --- a/code/modules/shuttle/ferry.dm +++ b/code/modules/shuttle/ferry.dm @@ -5,7 +5,6 @@ shuttleId = "ferry" possible_destinations = "ferry_home;ferry_away" req_access = list(ACCESS_CENT_GENERAL) - var/allow_silicons = FALSE var/allow_emag = FALSE @@ -24,17 +23,6 @@ /obj/machinery/computer/shuttle/ferry/request name = "ferry console" circuit = /obj/item/circuitboard/computer/ferry/request - var/last_request //prevents spamming admins - var/cooldown = 600 possible_destinations = "ferry_home;ferry_away" req_access = list(ACCESS_CENT_GENERAL) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - -/obj/machinery/computer/shuttle/ferry/request/Topic(href, href_list) - ..() - if(href_list["request"]) - if(last_request && (last_request + cooldown > world.time)) - return - last_request = world.time - to_chat(usr, "Your request has been received by CentCom.") - to_chat(GLOB.admins, "FERRY: [ADMIN_LOOKUPFLW(usr)] (Move Ferry) is requesting to move the transport ferry to CentCom.") diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index d7a6d4a583..03ff509086 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -711,6 +711,26 @@ else return "00:00" +/** + * Gets shuttle location status in a form of string for tgui interfaces + */ +/obj/docking_port/mobile/proc/get_status_text_tgui() + var/obj/docking_port/stationary/dockedAt = get_docked() + var/docked_at = dockedAt?.name || "Unknown" + if(istype(dockedAt, /obj/docking_port/stationary/transit)) + if(timeLeft() > 1 HOURS) + return "Hyperspace" + else + var/obj/docking_port/stationary/dst + if(mode == SHUTTLE_RECALL) + dst = previous + else + dst = destination + return "In transit to [dst?.name || "unknown location"]" + else if(mode == SHUTTLE_RECHARGING) + return "[docked_at], recharging [getTimerStr()]" + else + return docked_at /obj/docking_port/mobile/proc/getStatusText() var/obj/docking_port/stationary/dockedAt = get_docked() @@ -730,7 +750,6 @@ else return docked_at - /obj/docking_port/mobile/proc/getDbgStatusText() var/obj/docking_port/stationary/dockedAt = get_docked() . = (dockedAt && dockedAt.name) ? dockedAt.name : "unknown" diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 0076f584e9..bdbdc08c6f 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -12,26 +12,34 @@ possible_destinations = "syndicate_away;syndicate_z5;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s;syndicate_custom" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF -/obj/machinery/computer/shuttle/syndicate/recall - name = "syndicate shuttle recall terminal" - desc = "Use this if your friends left you behind." - possible_destinations = "syndicate_away" - - -/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list) - if(href_list["move"]) - var/obj/item/circuitboard/computer/syndicate_shuttle/board = circuit - if(board.challenge && ((world.time - SSticker.round_start_time) < SYNDICATE_CHALLENGE_TIMER)) - to_chat(usr, "You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - (world.time - SSticker.round_start_time))] more to allow them to prepare.") - return 0 - board.moved = TRUE - ..() - /obj/machinery/computer/shuttle/syndicate/allowed(mob/M) if(issilicon(M) && !(ROLE_SYNDICATE in M.faction)) return FALSE return ..() +/obj/machinery/computer/shuttle/syndicate/ui_act(action, params) + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return + + switch(action) + if("move") + if(istype(src, /obj/machinery/computer/shuttle/syndicate/drop_pod)) + if(!is_centcom_level(z)) + to_chat(usr, "Pods are one way!") + return + var/obj/item/circuitboard/computer/syndicate_shuttle/board = circuit + if(board?.challenge && world.time < SYNDICATE_CHALLENGE_TIMER) + to_chat(usr, "You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - world.time)] more to allow them to prepare.") + return + board.moved = TRUE + return ..() + +/obj/machinery/computer/shuttle/syndicate/recall + name = "syndicate shuttle recall terminal" + desc = "Use this if your friends left you behind." + possible_destinations = "syndicate_away" + /obj/machinery/computer/shuttle/syndicate/drop_pod name = "syndicate assault pod control" desc = "Controls the drop pod's launch system." @@ -43,13 +51,6 @@ possible_destinations = null clockwork = TRUE //it'd look weird -/obj/machinery/computer/shuttle/syndicate/drop_pod/Topic(href, href_list) - if(href_list["move"]) - if(!is_centcom_level(z)) - to_chat(usr, "Pods are one way!") - return 0 - ..() - /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate name = "syndicate shuttle navigation computer" desc = "Used to designate a precise transit location for the syndicate shuttle." diff --git a/code/modules/smithing/anvil.dm b/code/modules/smithing/anvil.dm new file mode 100644 index 0000000000..19d48119e6 --- /dev/null +++ b/code/modules/smithing/anvil.dm @@ -0,0 +1,315 @@ +#define WORKPIECE_PRESENT 1 +#define WORKPIECE_INPROGRESS 2 +#define WORKPIECE_FINISHED 3 +#define WORKPIECE_SLAG 5 + +#define RECIPE_SMALLPICK "dbp" //draw bend punch +#define RECIPE_LARGEPICK "ddbp" //draw draw bend punch +#define RECIPE_SHOVEL "dfup" //draw fold upset punch +#define RECIPE_HAMMER "sfp" //shrink fold punch + + +#define RECIPE_SMALLKNIFE "sdd" //shrink draw draw +#define RECIPE_SHORTSWORD "dff" //draw fold fold +#define RECIPE_WAKI "dfsf" //draw fold shrink fold +#define RECIPE_SCIMITAR "dfb" //draw fold bend +#define RECIPE_SABRE "ddsf" //draw draw shrink fold +#define RECIPE_RAPIER "sdfd" //shrink draw fold draw +#define RECIPE_BROADSWORD "dfuf" //draw fold upset fold +#define RECIPE_ZWEIHANDER "udfsf" //upset draw fold shrink fold +#define RECIPE_KATANA "fffff" //fold fold fold fold fold + + +#define RECIPE_SCYTHE "bdf" //bend draw fold +#define RECIPE_COGHEAD "bsf" //bend shrink fold. + + +#define RECIPE_JAVELIN "dbf" //draw bend fold +#define RECIPE_HALBERD "duffp" //draw upset fold fold punch +#define RECIPE_GLAIVE "usfp" //upset shrink fold punch +#define RECIPE_PIKE "ddbf" //draw draw bend fold + +/obj/structure/anvil + name = "anvil" + desc = "Base class of anvil. This shouldn't exist, but is useable." + icon = 'icons/obj/smith.dmi' + icon_state = "anvil" + density = TRUE + anchored = TRUE + var/workpiece_state = FALSE + var/datum/material/workpiece_material + var/anvilquality = 0 + var/currentquality = 0 //lolman? what the fuck do these vars do? + var/currentsteps = 0 //even i don't know + var/outrightfailchance = 1 //todo: document this shit + var/stepsdone = "" + var/rng = FALSE + var/debug = FALSE //vv this if you want an artifact + var/artifactrolled = FALSE + var/itemqualitymax = 20 + var/list/smithrecipes = list(RECIPE_HAMMER = /obj/item/smithing/hammerhead, + RECIPE_SCYTHE = /obj/item/smithing/scytheblade, + RECIPE_SHOVEL = /obj/item/smithing/shovelhead, + RECIPE_COGHEAD = /obj/item/smithing/cogheadclubhead, + RECIPE_JAVELIN = /obj/item/smithing/javelinhead, + RECIPE_LARGEPICK = /obj/item/smithing/pickaxehead, + RECIPE_SMALLPICK = /obj/item/smithing/prospectingpickhead, + RECIPE_SHORTSWORD = /obj/item/smithing/shortswordblade, + RECIPE_SCIMITAR = /obj/item/smithing/scimitarblade, + RECIPE_WAKI = /obj/item/smithing/wakiblade, + RECIPE_RAPIER = /obj/item/smithing/rapierblade, + RECIPE_SABRE = /obj/item/smithing/sabreblade, + RECIPE_SMALLKNIFE = /obj/item/smithing/knifeblade, + RECIPE_BROADSWORD = /obj/item/smithing/broadblade, + RECIPE_ZWEIHANDER = /obj/item/smithing/zweiblade, + RECIPE_KATANA = /obj/item/smithing/katanablade, + RECIPE_HALBERD = /obj/item/smithing/halberdhead, + RECIPE_GLAIVE = /obj/item/smithing/glaivehead, + RECIPE_PIKE = /obj/item/smithing/pikehead) + +/obj/structure/anvil/Initialize() + ..() + currentquality = anvilquality + +/obj/structure/anvil/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/ingot)) + var/obj/item/ingot/notsword = I + if(workpiece_state) + to_chat(user, "There's already a workpiece! Finish it or take it off.") + return FALSE + if(notsword.workability == "shapeable") + workpiece_state = WORKPIECE_PRESENT + workpiece_material = notsword.custom_materials + to_chat(user, "You place the [notsword] on the [src].") + currentquality = anvilquality + var/skillmod = 0 + if(user.mind.skill_holder) + skillmod = user.mind.get_skill_level(/datum/skill/level/dorfy/blacksmithing)/2 + currentquality += skillmod + qdel(notsword) + else + to_chat(user, "The ingot isn't workable yet!") + return FALSE + return + else if(istype(I, /obj/item/melee/smith/hammer)) + var/obj/item/melee/smith/hammer/hammertime = I + if(workpiece_state == WORKPIECE_PRESENT || workpiece_state == WORKPIECE_INPROGRESS) + do_shaping(user, hammertime.qualitymod) + return + else + to_chat(user, "You can't work an empty anvil!") + return FALSE + return ..() + +/obj/structure/anvil/wrench_act(mob/living/user, obj/item/I) + ..() + default_unfasten_wrench(user, I, 5) + return TRUE + + +/obj/structure/anvil/proc/do_shaping(mob/user, var/qualitychange) + currentquality += qualitychange + var/list/shapingsteps = list("weak hit", "strong hit", "heavy hit", "fold", "draw", "shrink", "bend", "punch", "upset") //weak/strong/heavy hit affect strength. All the other steps shape. + workpiece_state = WORKPIECE_INPROGRESS + var/stepdone = input(user, "How would you like to work the metal?") in shapingsteps + var/steptime = 50 + if(user.mind.skill_holder) + var/skillmod = user.mind.get_skill_level(/datum/skill/level/dorfy/blacksmithing)/10 + 1 + steptime = 50 / skillmod + playsound(src, 'sound/effects/clang2.ogg',40, 2) + if(!do_after(user, steptime, target = src)) + return FALSE + switch(stepdone) + if("weak hit") + currentsteps += 1 + outrightfailchance += 5 + currentquality += 1 + if("strong hit") + currentsteps += 2 + outrightfailchance += 9.5 + currentquality += 2 + if("heavy hit") + currentsteps += 3 + outrightfailchance += 12.5 + currentquality += 3 + if("fold") + stepsdone += "f" + currentsteps += 1 + currentquality -= 1 + if("draw") + stepsdone += "d" + currentsteps += 1 + currentquality -= 1 + if("shrink") + stepsdone += "s" + currentsteps += 1 + currentquality -= 1 + if("bend") + stepsdone += "b" + currentsteps += 1 + currentquality -= 1 + if("punch") + stepsdone += "p" + currentsteps += 1 + currentquality -= 1 + if("upset") + stepsdone += "u" + currentsteps += 1 + currentquality -= 1 + user.visible_message("[user] works the metal on the anvil with their hammer with a loud clang!", \ + "You [stepdone] the metal with a loud clang!") + playsound(src, 'sound/effects/clang2.ogg',40, 2) + addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/effects/clang2.ogg', 40, 2), 15) + if(length(stepsdone) >= 3) + tryfinish(user) + +/obj/structure/anvil/proc/tryfinish(mob/user) + var/artifactchance = 0 + if(!artifactrolled) + artifactchance = (1+(user.mind.get_skill_level(/datum/skill/level/dorfy/blacksmithing)/4))/2500 + artifactrolled = TRUE + var/artifact = max(prob(artifactchance), debug) + var/finalfailchance = outrightfailchance + if(user.mind.skill_holder) + var/skillmod = user.mind.get_skill_level(/datum/skill/level/dorfy/blacksmithing)/10 + 1 + finalfailchance = max(0, finalfailchance / skillmod) //lv 2 gives 20% less to fail, 3 30%, etc + if((currentsteps > 10 || (rng && prob(finalfailchance))) && !artifact) + to_chat(user, "You overwork the metal, causing it to turn into useless slag!") + var/turf/T = get_turf(user) + workpiece_state = FALSE + new /obj/item/stack/ore/slag(T) + currentquality = anvilquality + stepsdone = "" + currentsteps = 0 + outrightfailchance = 1 + artifactrolled = FALSE + if(user.mind.skill_holder) + user.mind.auto_gain_experience(/datum/skill/level/dorfy/blacksmithing, 25, 400, silent = FALSE) + for(var/i in smithrecipes) + if(i == stepsdone) + var/turf/T = get_turf(user) + var/obj/item/smithing/create = smithrecipes[stepsdone] + var/obj/item/smithing/finisheditem = new create(T) + to_chat(user, "You finish your [finisheditem]!") + if(artifact) + to_chat(user, "It is an artifact, a creation whose legacy shall live on forevermore.") //todo: SSblackbox + currentquality = max(currentquality, 2) + finisheditem.quality = currentquality * 3//this is insane i know it's 1/2500 for most of the time and 0.8% at best + finisheditem.artifact = TRUE + else + finisheditem.quality = min(currentquality, itemqualitymax) + switch(finisheditem.quality) + if(-1000 to -8) + finisheditem.desc = "It looks to be the most awfully made object you've ever seen." + if(-8) + finisheditem.desc = "It looks to be the second most awfully made object you've ever seen." + if(-8 to 0) + finisheditem.desc = "It looks to be barely passable as... whatever it's trying to pass for." + if(0) + finisheditem.desc = "It looks to be totally average." + if(0 to INFINITY) + finisheditem.desc = "It looks to be better than average." + workpiece_state = FALSE + finisheditem.set_custom_materials(workpiece_material) + currentquality = anvilquality + stepsdone = "" + currentsteps = 0 + outrightfailchance = 1 + artifactrolled = FALSE + if(user.mind.skill_holder) + user.mind.auto_gain_experience(/datum/skill/level/dorfy/blacksmithing, 50, 10000000, silent = FALSE) + break + +/obj/structure/anvil/debugsuper + name = "super ultra epic anvil of debugging." + desc = "WOW. A DEBUG ITEM STRUCTURE. EPIC." + icon_state = "anvil" + anvilquality = 10 + itemqualitymax = 9001 + outrightfailchance = 0 + +/obj/structure/anvil/obtainable + name = "anvil" + desc = "Base class of anvil. This shouldn't exist, but is useable." + anvilquality = 0 + outrightfailchance = 5 + rng = TRUE + +/obj/structure/anvil/obtainable/table + name = "table anvil" + desc = "A slightly reinforced table. Good luck." + icon_state = "tablevil" + anvilquality = -2 + itemqualitymax = 0 + + +/obj/structure/anvil/obtainable/table/do_shaping(mob/user, var/qualitychange) + if(prob(5)) + to_chat(user, "The [src] breaks under the strain!") + take_damage(max_integrity) + return FALSE + else + ..() + +/obj/structure/anvil/obtainable/bronze + name = "slab of bronze" + desc = "A big block of bronze. Useable as an anvil." + custom_materials = list(/datum/material/bronze=8000) + icon_state = "ratvaranvil" + anvilquality = -0.5 + itemqualitymax = 2 + +/obj/structure/anvil/obtainable/sandstone + name = "sandstone brick anvil" + desc = "A big block of sandstone. Useable as an anvil." + custom_materials = list(/datum/material/sandstone=8000) + icon_state = "sandvil" + anvilquality = -1 + itemqualitymax = 2 + +/obj/structure/anvil/obtainable/basalt + name = "basalt brick anvil" + desc = "A big block of basalt. Useable as an anvil, better than sandstone. Igneous!" + icon_state = "sandvilnoir" + anvilquality = -0.5 + itemqualitymax = 4 + +/obj/structure/anvil/obtainable/basic + name = "anvil" + desc = "An anvil. It's got wheels bolted to the bottom." + anvilquality = 0 + itemqualitymax = 6 + +/obj/structure/anvil/obtainable/ratvar + name = "brass anvil" + desc = "A big block of what appears to be brass. Useable as an anvil, if whatever's holding the brass together lets you." + custom_materials = list(/datum/material/bronze=8000) + icon_state = "ratvaranvil" + anvilquality = 1 + itemqualitymax = 8 + +/obj/structure/anvil/obtainable/ratvar/attackby(obj/item/I, mob/user) + if(is_servant_of_ratvar(user)) + return ..() + else + to_chat(user, "KNPXWN, QNJCQNW!") //rot13 then rot22 if anyone wants to decode + +/obj/structure/anvil/obtainable/narsie + name = "runic anvil" + desc = "An anvil made of a strange, runic metal." + custom_materials = list(/datum/material/runedmetal=8000) + icon = 'icons/obj/smith.dmi' + icon_state = "evil" + anvilquality = 1 + itemqualitymax = 8 + +/obj/structure/anvil/obtainable/narsie/attackby(obj/item/I, mob/user) + if(iscultist(user)) + return ..() + else + to_chat(user, "That is not yours to use!") + +#undef WORKPIECE_PRESENT +#undef WORKPIECE_INPROGRESS +#undef WORKPIECE_FINISHED +#undef WORKPIECE_SLAG diff --git a/code/modules/smithing/finished_items.dm b/code/modules/smithing/finished_items.dm new file mode 100644 index 0000000000..5db6b09452 --- /dev/null +++ b/code/modules/smithing/finished_items.dm @@ -0,0 +1,329 @@ + +/obj/item/melee/smith + name = "base class obj/item/melee/smith" //tin. handles overlay and quality and shit. + desc = "cringe" + icon = 'icons/obj/smith.dmi' + icon_state = "claymore" + item_state = "claymore" + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + total_mass = TOTAL_MASS_MEDIEVAL_WEAPON //yeah ok + slot_flags = ITEM_SLOT_BELT + w_class = WEIGHT_CLASS_NORMAL + force = 6 + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + var/quality + var/overlay_state = "stick" + var/mutable_appearance/overlay + var/wielded_mult = 1 + var/wield_force = 15 + +/obj/item/melee/smith/Initialize() + ..() + if(desc == "cringe") + desc = "A handmade [name]." + overlay = mutable_appearance(icon, overlay_state) + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + if(force < 0) + force = 0 + + +/obj/item/melee/smith/twohand + item_flags = NEEDS_PERMIT //it's a bigass sword/spear. beepsky is going to give you shit for it. + sharpness = SHARP_EDGED + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + force = 10 + wielded_mult = 1.75 + w_class = WEIGHT_CLASS_BULKY + +/obj/item/melee/smith/twohand/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 70) //decent in a pinch, but pretty bad. + AddElement(/datum/element/sword_point) + + + +/////////////////////////// +// Mining // +/////////////////////////// +/obj/item/mining_scanner/prospector + name = "prospector's pickaxe" + desc = "A pickaxe that can sound rocks to find mineral deposits and stop gibtonite detonations." + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + icon = 'icons/obj/smith.dmi' + icon_state = "minipick" //todo:sprite + sharpness = SHARP_POINTY//it doesnt have a blade it has a point + +/obj/item/mining_scanner/prospector/Initialize() + ..() + var/mutable_appearance/overlay + desc = "A handmade [name]." + overlay = mutable_appearance(icon, "minihandle") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + if(force < 0) + force = 0 + +/obj/item/pickaxe/smithed + name = "pickaxe" + desc = "A pickaxe." + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + icon = 'icons/obj/smith.dmi' + icon_state = "pickaxe" + sharpness = SHARP_POINTY + +/obj/item/pickaxe/smithed/Initialize() + ..() + desc = "A handmade [name]." + var/mutable_appearance/overlay + overlay = mutable_appearance(icon, "stick") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + if(force < 0) + force = 0 + +/obj/item/pickaxe/smithed/attack_self(mob/user) + to_chat(user, "Tool does not have a configureable dig range.") + +/obj/item/shovel/smithed + name = "shovel" + desc = "A shovel." + icon = 'icons/obj/smith.dmi' + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + icon_state = "shovel" + sharpness = SHARP_EDGED //it cuts through the earth + +/obj/item/shovel/smithed/Initialize() + ..() + desc = "A handmade [name]." + var/mutable_appearance/overlay + overlay = mutable_appearance(icon, "shovelhandle") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + if(force < 0) + force = 0 + + +/////////////////////////// +// Spears // +/////////////////////////// + + +/obj/item/melee/smith/twohand/halberd + name = "halberd" + icon_state = "halberd" + w_class = WEIGHT_CLASS_HUGE + overlay_state = "spearhandle" + slot_flags = ITEM_SLOT_BACK + wielded_mult = 2.5 + +/obj/item/melee/smith/twohand/halberd/ComponentInitialize() + . = ..() + AddComponent(/datum/component/jousting) + +/obj/item/melee/smith/twohand/javelin + name = "javelin" + icon_state = "javelin" + overlay_state = "longhandle" + wielded_mult = 1.5 + slot_flags = ITEM_SLOT_BACK + sharpness = SHARP_POINTY + + +/obj/item/melee/smith/twohand/javelin/ComponentInitialize() + . = ..() + AddComponent(/datum/component/jousting) + +/obj/item/melee/smith/twohand/glaive + name = "glaive" + icon_state = "glaive" + overlay_state = "longhandle" + slot_flags = ITEM_SLOT_BACK + wielded_mult = 2 + +/obj/item/melee/smith/twohand/glaive/ComponentInitialize() + . = ..() + AddComponent(/datum/component/jousting) + + +/obj/item/melee/smith/twohand/pike + name = "pike" + icon_state = "pike" + w_class = WEIGHT_CLASS_HUGE + overlay_state = "longhandle" + reach = 2 //yeah ok + slot_flags = ITEM_SLOT_BACK + sharpness = SHARP_POINTY + +////////////////////////// +// Other Melee // +/////////////////////////// + + +/obj/item/melee/smith/hammer//blacksmithing, not warhammer. + name = "hammer" + icon_state = "hammer" + overlay_state = "hammerhandle" + var/qualitymod = 0 + +/obj/item/scythe/smithed //we need to inherit scythecode, but that's about it. + material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + + +/obj/item/melee/smith/cogheadclub + name = "coghead club" + icon_state = "coghead" + item_flags = NEEDS_PERMIT + overlay_state = "stick" + +/obj/item/melee/smith/shortsword + name = "gladius" + force = 9 + item_flags = NEEDS_PERMIT + sharpness = SHARP_EDGED + icon_state = "gladius" + overlay_state = "gladiushilt" + +/obj/item/melee/smith/shortsword/scimitar + name = "scimitar" + sharpness = SHARP_EDGED + icon_state = "scimitar" + overlay_state = "scimitarhilt" + +/obj/item/melee/smith/wakizashi + name = "wakizashi" + sharpness = SHARP_EDGED + force = 7 + item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY + obj_flags = UNIQUE_RENAME + icon_state = "waki" + overlay_state = "wakihilt" + block_parry_data = /datum/block_parry_data/waki + +/datum/block_parry_data/waki //like longbokken but worse reflect + parry_stamina_cost = 6 + parry_time_windup = 0 + parry_time_active = 15 //decent window + parry_time_spindown = 0 + parry_time_perfect = 2 + parry_time_perfect_leeway = 0.75 + parry_imperfect_falloff_percent = 7.5 + parry_efficiency_to_counterattack = 100 + parry_efficiency_considered_successful = 80 + parry_efficiency_perfect = 120 + parry_failed_stagger_duration = 3 SECONDS + parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 1.9) + +/obj/item/melee/smith/twohand/broadsword + name = "broadsword" + icon_state = "broadsword" + overlay_state = "broadhilt" + wielded_mult = 1.8 + +/obj/item/melee/smith/twohand/zweihander + name = "zweihander" + icon_state = "zwei" + overlay_state = "zweihilt" + total_mass = TOTAL_MASS_MEDIEVAL_WEAPON * 2 + force = 4 + wielded_mult = 3 //affected more by quality. a -1 is 25% less damage, a +1 is 25% more. These bonuses are tripled when wielded. + +/obj/item/melee/smith/twohand/katana + name = "katana" + icon_state = "katana" + overlay_state = "katanahilt" + force = 7 + wielded_mult = 2 + item_flags = ITEM_CAN_PARRY | NEEDS_PERMIT //want to name your katana "DEMON BLADE" or some shit? go ahead, idiot. + obj_flags = UNIQUE_RENAME + block_parry_data = /datum/block_parry_data/captain_saber //todo + +/obj/item/melee/smith/sabre + name = "sabre" + icon_state = "sabre" + sharpness = SHARP_EDGED + overlay_state = "sabrehilt" + armour_penetration = 15 + force = 9 + hitsound = 'sound/weapons/rapierhit.ogg' + item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY + block_parry_data = /datum/block_parry_data/captain_saber //yeah this is fine i guess + +/obj/item/melee/smith/sabre/rapier + name = "rapier" + icon_state = "rapier" + sharpness = SHARP_EDGED + overlay_state = "rapierhilt" + force = 6 //less force, stronger parry + sharpness = SHARP_POINTY + armour_penetration = 30 + block_parry_data = /datum/block_parry_data/smithrapier + +/datum/block_parry_data/smithrapier //parry into riposte. i am pretty sure this is going to be nearly fucking impossible to land. + parry_stamina_cost = 12 //dont miss + parry_time_active = 4 + parry_time_perfect = 2 + parry_time_perfect_leeway = 2 + parry_failed_stagger_duration = 3 SECONDS + parry_failed_clickcd_duration = 3 SECONDS + parry_time_windup = 0 + parry_time_spindown = 0 + parry_imperfect_falloff_percent = 0 + parry_efficiency_to_counterattack = 100 + parry_efficiency_considered_successful = 120 + parry_efficiency_perfect = 120 + parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 4) + +//unique hammers +/obj/item/melee/smith/hammer/toolbox + name = "toolbox hammer" + desc = "A metal filled toolbox on a stick. Useable as a really shitty hammer." + w_class = WEIGHT_CLASS_BULKY + icon_state = "toolbox" + overlay_state = "hammerhandle" + qualitymod = -2 + +/obj/item/melee/smith/hammer/narsie + name = "runemetal hammer" + custom_materials = list(/datum/material/runedmetal = 12000) + desc = "A metal hammer inscribed with geometeric runes." + qualitymod = 1 + +/obj/item/melee/smith/hammer/narsie/attack(mob/living/target, mob/living/carbon/human/user) + if(!iscultist(user)) + user.DefaultCombatKnockdown(100) + user.dropItemToGround(src, TRUE) + user.visible_message("A powerful force shoves [user] away from [target]!", \ + "\"You shouldn't be touching tools that aren't yours.\"") + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(rand(force/2, force), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + else + user.adjustBruteLoss(rand(force/2,force)) + return + ..() + +/obj/item/melee/smith/hammer/ratvar + name = "brass hammer" + custom_materials = list(/datum/material/bronze = 12000) + desc = "A brass hammer inscribed with... writing? You can't read it." + qualitymod = 1 + +/obj/item/melee/smith/hammer/ratvar/attack(mob/living/target, mob/living/carbon/human/user) + if(!is_servant_of_ratvar(user)) + user.DefaultCombatKnockdown(100) + user.dropItemToGround(src, TRUE) + user.visible_message("A powerful force shoves [user] away from [target]!", "\"You shouldn't be touching tools that aren't yours.\"") + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(rand(force/2, force), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + else + user.adjustBruteLoss(rand(force/2,force)) + return + ..() + +/obj/item/melee/smith/hammer/debug + name = "debugging hammer" + desc = "A DEBUGGING HAMMER!! EPIC!!." + qualitymod = 10 diff --git a/code/modules/smithing/furnace.dm b/code/modules/smithing/furnace.dm new file mode 100644 index 0000000000..ee1d6a1b93 --- /dev/null +++ b/code/modules/smithing/furnace.dm @@ -0,0 +1,75 @@ +/obj/structure/furnace + name = "furnace" + desc = "A furnace." + icon = 'icons/obj/smith.dmi' + icon_state = "furnace0" + density = TRUE + anchored = TRUE + var/debug = FALSE //debugging only + var/working = TRUE + var/fueluse = 1 + + +/obj/structure/furnace/Initialize() + ..() + create_reagents(250, TRANSPARENT) + START_PROCESSING(SSobj, src) + +/obj/structure/furnace/Destroy() + ..() + STOP_PROCESSING(SSobj, src) + +/obj/structure/furnace/process() + if(debug) + reagents.add_reagent(/datum/reagent/fuel, 1) + return TRUE + if(reagents.remove_reagent(/datum/reagent/fuel, fueluse)) + working = TRUE + if(icon_state == "furnace0") + icon_state = "furnace1" + else + working = FALSE + icon_state = "furnace0" + +/obj/structure/furnace/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/ingot)) + var/obj/item/ingot/notsword = I + if(working) + to_chat(user, "You heat the [notsword] in the [src].") + notsword.workability = "shapeable" + else + to_chat(user, "The furnace isn't working!.") + else + ..() + +/obj/structure/furnace/wrench_act(mob/living/user, obj/item/I) + ..() + default_unfasten_wrench(user, I, 5) + return TRUE + +/obj/structure/furnace/attackby(obj/item/W, mob/user, params) + if(W.reagents) + W.reagents.trans_to(src, 250) + else + return ..() + +/obj/structure/furnace/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) + to_chat(user, "You start furiously plunging [name].") + if(do_after(user, 30, target = src)) + to_chat(user, "You finish plunging the [name].") + reagents.reaction(get_turf(src), TOUCH) //splash on the floor + reagents.clear_reagents() + +/obj/structure/furnace/infinite + name = "fuelless furnace" + debug = TRUE + icon_state = "ratfurnace" + + +/obj/structure/furnace/infinite/ratvar + name = "brass furnace" + desc = "A brass furnace. Powered by... something, but seems otherwise safe." //todo:sprites they're safe for noncultists because you're just putting ingots in them. also there';s a reason to steal them ig + +/obj/structure/furnace/infinite/narsie + name = "rune furnace" + desc = "A runed furnace. Powered by... something, but seems otherwise safe." diff --git a/code/modules/smithing/smithed_items.dm b/code/modules/smithing/smithed_items.dm new file mode 100644 index 0000000000..6d10d33a75 --- /dev/null +++ b/code/modules/smithing/smithed_items.dm @@ -0,0 +1,419 @@ +/obj/item/basaltblock + name = "basalt block" + desc = "A block of basalt." + icon = 'icons/obj/smith.dmi' + icon_state = "sandvilnoir" + + +/obj/item/smithing + name = "base class /obj/item/smithing" + icon = 'icons/obj/smith.dmi' + icon_state = "unfinished" + material_flags = MATERIAL_COLOR | MATERIAL_ADD_PREFIX + var/quality = 0 //quality. Changed by the smithing process. + var/obj/item/finishingitem = /obj/item/stick //What this item needs to be hit by to create finalitem + var/obj/item/finalitem + var/artifact = FALSE + +/obj/item/ingot + name = "ingot" + icon = 'icons/obj/smith.dmi' + icon_state = "ingot" + material_flags = MATERIAL_COLOR | MATERIAL_ADD_PREFIX + var/workability = 0 + + +/obj/item/ingot/on_attack_hand(mob/user) + var/mob/living/carbon/human/H + if(workability != "shapeable") + return ..() + var/prot = 0 + if(ishuman(user)) + H = user + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(G.max_heat_protection_temperature) + prot = (G.max_heat_protection_temperature > 360) + else + prot = 1 + if(prot > 0 || HAS_TRAIT(user, TRAIT_RESISTHEAT) || HAS_TRAIT(user, TRAIT_RESISTHEATHANDS)) + to_chat(user, "You pick up the [src].") + return ..() + else + to_chat(user, "You try to move the [src], but you burn your hand on it!") + if(H) + var/obj/item/bodypart/affecting = H.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") + if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage + H.update_damage_overlays() + +/obj/item/ingot/iron + custom_materials = list(/datum/material/iron=12000) + +/obj/item/ingot/diamond + custom_materials = list(/datum/material/diamond=12000) //yeah ok + +/obj/item/ingot/uranium + custom_materials = list(/datum/material/uranium=12000) + +/obj/item/ingot/plasma + custom_materials = list(/datum/material/plasma=12000)//yeah ok + +/obj/item/ingot/gold + custom_materials = list(/datum/material/gold=12000) + +/obj/item/ingot/silver + custom_materials = list(/datum/material/silver=12000) + +/obj/item/ingot/bananium + custom_materials = list(/datum/material/bananium=12000) + +/obj/item/ingot/titanium + custom_materials = list(/datum/material/titanium=12000) + +/obj/item/ingot/adamantine + custom_materials = list(/datum/material/adamantine=12000) + +/obj/item/ingot/cult + custom_materials = list(/datum/material/runedmetal=12000) + +/obj/item/ingot/bronze + custom_materials = list(/datum/material/bronze=12000) + +/obj/item/ingot/ratvar + custom_materials = list(/datum/material/brass=12000) + desc = "On closer inspection, what appears to be wholly-unsuitable-for-smithing brass is actually primarily replicant alloy. Nezbere must have switched it while you weren't looking." + + +/obj/item/smithing/attackby(obj/item/I, mob/user) + if(istype(I, finishingitem)) + qdel(I) + startfinish() + else + return ..() + +/obj/item/smithing/proc/startfinish() + dofinish() + +/obj/item/smithing/proc/dofinish() + var/qualname + switch(quality) + if(-1000 to -5) + qualname = "awful" + if(-1000 to -2) + qualname = "shoddy" + if(-1000 to -1) + qualname = "poor" + if(-1 to 1) + qualname = "normal" + if(10 to INFINITY) + qualname = "legendary" + if(7.5 to 10) + qualname = "masterwork" + if(5.5 to 7.5) + qualname = "excellent" + if(3.5 to 5.5) + qualname = "good" + if(0 to 3.5) + qualname = "above-average" + var/datum/material/mat = custom_materials[1] + finalitem.set_custom_materials(custom_materials) + mat = mat.name + if(artifact) + dwarfyartifact(finalitem, mat) + else + finalitem.name = "[qualname] [mat] [initial(finalitem.name)]" + finalitem.desc = "A [qualname] [initial(finalitem.name)]. Its quality is [quality]." + finalitem.forceMove(get_turf(src)) + qdel(src) + + +/obj/item/smithing/proc/dwarfyartifact(var/obj/item/finalitem, var/mat) + var/finaldesc = "A [initial(finalitem.name)] made of [mat], all craftsmanship is of the highest quality. It " + switch(pick(1,2,3,4,5)) + if(1) + finaldesc += "is encrusted with [pick("","synthetic ","multi-faceted ","magical ","sparkling ") + pick("rubies","emeralds","jade","opals","lapiz lazuli")]." + if(2) + finaldesc += "is laced with studs of [pick("gold","silver","aluminium","titanium")]." + if(3) + finaldesc += "is encircled with bands of [pick("durasteel","metallic hydrogen","ferritic-alloy","plasteel","duranium")]." + if(4) + finaldesc += "menaces with spikes of [pick("ytterbium","uranium","white pearl","black steel")]." + if(5) + finaldesc += "is encrusted with [pick("","synthetic ","multi-faceted ","magical ","sparkling ") + pick("rubies","emeralds","jade","opals","lapis lazuli")],laced with studs of [pick("gold","silver","aluminium","titanium")], encircled with bands of [pick("durasteel","metallic hydrogen","ferritic-alloy","plasteel","duranium")] and menaces with spikes of [pick("ytterbium","uranium","white pearl","black steel")]." + finalitem.desc = finaldesc + finalitem.name = pick("Delersibnir", "Nekolangrir", "Zanoreshik","Öntakrítin", "Nogzatan", "Vunomam", "Nazushagsaldôbar", "Sergeb", "Zafaldastot", "Vudnis", "Dostust", "Shotom", "Mugshith", "Angzak", "Oltud", "Deleratîs", "Nökornomal") //one of these is literally BLOOD POOL CREATE.iirc its Nazushagsaldôbar. + +/obj/item/smithing/hammerhead + name = "smithed hammer head" + finalitem = /obj/item/melee/smith/hammer + icon_state = "hammer" + +/obj/item/smithing/hammerhead/startfinish() + var/obj/item/melee/smith/hammer/finalforreal = new /obj/item/melee/smith/hammer(src) + finalforreal.force += quality/2 + finalforreal.qualitymod = quality/4 + finalitem = finalforreal + ..() + + + +/obj/item/smithing/scytheblade + name = "smithed scythe head" + finalitem = /obj/item/scythe/smithed + icon_state = "scythe" + +/obj/item/smithing/scytheblade/startfinish() + finalitem = new /obj/item/scythe/smithed(src) + finalitem.force += quality + ..() + +/obj/item/smithing/shovelhead + name = "smithed shovel head" + finalitem = /obj/item/shovel/smithed + icon_state = "shovel" + +/obj/item/smithing/shovelhead/startfinish() + finalitem = new /obj/item/shovel/smithed(src) + finalitem.force += quality/2 + if(quality > 0) + finalitem.toolspeed = max(0.05,(1-(quality/10))) + else + finalitem.toolspeed *= max(1, (quality * -1)) + ..() + +/obj/item/smithing/cogheadclubhead + name = "smithed coghead club head" + finalitem = /obj/item/melee/smith/cogheadclub + icon_state = "coghead" + +/obj/item/smithing/cogheadclubhead/startfinish() + finalitem = new /obj/item/melee/smith/cogheadclub(src) + finalitem.force += quality + ..() + +/obj/item/smithing/javelinhead + name = "smithed javelin head" + finalitem = /obj/item/melee/smith/twohand/javelin + icon_state = "javelin" + +/obj/item/smithing/javelinhead/startfinish() + var/obj/item/melee/smith/twohand/javelin/finalforreal = new /obj/item/melee/smith/twohand/javelin(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalforreal.throwforce = finalforreal.force*2 + finalitem = finalforreal + ..() + +/obj/item/smithing/pikehead + name = "smithed pike head" + finalitem = /obj/item/melee/smith/twohand/pike + icon_state = "pike" + +/obj/item/smithing/pikehead/startfinish() + var/obj/item/melee/smith/twohand/pike/finalforreal = new /obj/item/melee/smith/twohand/pike(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalforreal.throwforce = finalforreal.force/10 //its a pike not a javelin + finalitem = finalforreal + ..() + +/obj/item/smithing/pickaxehead + name = "smithed pickaxe head" + finalitem = /obj/item/pickaxe/smithed + icon_state = "pickaxe" + +/obj/item/smithing/pickaxehead/startfinish() + var/obj/item/pickaxe/smithed/finalforreal = new /obj/item/pickaxe/smithed(src) + finalforreal.force += quality/2 + if(quality > 0) + finalforreal.toolspeed = max(0.05,(1-(quality/10))) + else + finalforreal.toolspeed *= max(1, (quality * -1)) + switch(quality) + if(10 to INFINITY) + finalforreal.digrange = 4 + if(5 to 9) + finalforreal.digrange = 3 + if(3,4) + finalforreal.digrange = 2 + else + finalforreal.digrange = 1 + finalitem = finalforreal + ..() + + +/obj/item/smithing/prospectingpickhead + name = "smithed prospector's pickaxe head" + finalitem = /obj/item/mining_scanner/prospector + icon_state = "minipick" + +/obj/item/smithing/prospectingpickhead/startfinish() + var/obj/item/mining_scanner/prospector/finalforreal = new /obj/item/mining_scanner/prospector(src) + finalforreal.range = 2 + quality + if(quality) + finalforreal.cooldown = 100/quality + finalitem = finalforreal + ..() + + +/obj/item/smithing/shortswordblade + name = "smithed gladius blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/shortsword + icon_state = "gladius" + +/obj/item/smithing/shortswordblade/startfinish() + finalitem = new /obj/item/melee/smith/shortsword(src) + finalitem.force += quality + ..() + +/obj/item/smithing/scimitarblade + name = "smithed scimitar blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/shortsword/scimitar + icon_state = "scimitar" + +/obj/item/smithing/scimitarblade/startfinish() + finalitem = new /obj/item/melee/smith/shortsword/scimitar(src) + finalitem.force += quality + ..() + +/obj/item/smithing/wakiblade + name = "smithed wakizashi blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/wakizashi + icon_state = "waki" + +/obj/item/smithing/wakiblade/startfinish() + finalitem = new /obj/item/melee/smith/wakizashi(src) + finalitem.force += quality + ..() + +/obj/item/smithing/sabreblade + name = "smithed sabre blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/sabre + icon_state = "sabre" + +/obj/item/smithing/sabreblade/startfinish() + finalitem = new /obj/item/melee/smith/sabre(src) + finalitem.force += quality + ..() + +/obj/item/smithing/rapierblade + name = "smithed rapier blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/sabre/rapier + icon_state = "rapier" + +/obj/item/smithing/rapierblade/startfinish() + finalitem = new /obj/item/melee/smith/sabre/rapier(src) + finalitem.force += quality + ..() + +/obj/item/smithing/knifeblade + name = "smithed knife blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/kitchen/knife + icon_state = "dagger" + +/obj/item/smithing/knifeblade/startfinish() + finalitem = new /obj/item/kitchen/knife(src) + finalitem.force = 4 + quality/2 + finalitem.icon = 'icons/obj/smith.dmi' + finalitem.icon_state = "dagger" + finalitem.name = "dagger" + finalitem.desc = "A dagger." + var/mutable_appearance/overlay = mutable_appearance('icons/obj/smith.dmi', "daggerhilt") + overlay.appearance_flags = RESET_COLOR + finalitem.add_overlay(overlay) + if(finalitem.force < 0) + finalitem.force = 0 + finalitem.material_flags = MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + ..() + +/obj/item/smithing/broadblade + name = "smithed broadsword blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/twohand/broadsword + icon_state = "broadsword" + +/obj/item/smithing/broadblade/startfinish() + var/obj/item/melee/smith/twohand/broadsword/finalforreal = new /obj/item/melee/smith/twohand/broadsword(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalitem = finalforreal + ..() + +/obj/item/smithing/zweiblade + name = "smithed zweihander blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/twohand/zweihander + icon_state = "zwei" + +/obj/item/smithing/zweiblade/startfinish() + var/obj/item/melee/smith/twohand/zweihander/finalforreal = new /obj/item/melee/smith/twohand/zweihander(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalitem = finalforreal + ..() + +/obj/item/smithing/halberdhead + name = "smithed halberd head" + finalitem = /obj/item/melee/smith/twohand/halberd + icon_state = "halberd" + +/obj/item/smithing/halberdhead/startfinish() + var/obj/item/melee/smith/twohand/halberd/finalforreal = new /obj/item/melee/smith/twohand/halberd(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.throwforce = finalforreal.force/3 + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalitem = finalforreal + ..() + +/obj/item/smithing/glaivehead + name = "smithed glaive head" + finalitem = /obj/item/melee/smith/twohand/glaive + icon_state = "glaive" + +/obj/item/smithing/glaivehead/startfinish() + var/obj/item/melee/smith/twohand/glaive/finalforreal = new /obj/item/melee/smith/twohand/glaive(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.throwforce = finalforreal.force + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalitem = finalforreal + ..() + +/obj/item/smithing/katanablade + name = "smithed katana blade" + finishingitem = /obj/item/swordhandle + finalitem = /obj/item/melee/smith/twohand/katana + icon_state = "katana" + + +/obj/item/smithing/katanablade/startfinish() + var/obj/item/melee/smith/twohand/katana/finalforreal = new /obj/item/melee/smith/twohand/katana(src) + finalforreal.force += quality + finalforreal.wield_force = finalforreal.force*finalforreal.wielded_mult + finalforreal.AddComponent(/datum/component/two_handed, force_unwielded=finalforreal.force, force_wielded=finalforreal.wield_force, icon_wielded="[icon_state]") + finalitem = finalforreal + ..() + +/obj/item/stick + name = "wooden rod" + desc = "It's a rod, suitable for use of a handle of a tool. Also could serve as a weapon, in a pinch." + icon = 'icons/obj/smith.dmi' + icon_state = "stick" + force = 7 + +/obj/item/swordhandle + name = "sword handle" + desc = "It's a crudlely shaped wooden sword hilt." + icon = 'icons/obj/smith.dmi' + icon_state = "shorthilt" diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index 472734b74b..9ebcfe91d6 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -31,6 +31,7 @@ anchored = TRUE /obj/machinery/bsa/wrench_act(mob/living/user, obj/item/I) + ..() default_unfasten_wrench(user, I, 10) return TRUE @@ -142,17 +143,17 @@ /obj/machinery/bsa/full/proc/get_front_turf() switch(dir) if(WEST) - return locate(x - 6,y,z) + return locate(x - 7,y,z) if(EAST) - return locate(x + 4,y,z) + return locate(x + 7,y,z) return get_turf(src) /obj/machinery/bsa/full/proc/get_back_turf() switch(dir) if(WEST) - return locate(x + 4,y,z) + return locate(x + 5,y,z) if(EAST) - return locate(x - 6,y,z) + return locate(x - 5,y,z) return get_turf(src) /obj/machinery/bsa/full/proc/get_target_turf() @@ -169,11 +170,12 @@ switch(cannon_direction) if(WEST) setDir(WEST) - pixel_x = -192 top_layer.icon_state = "top_west" icon_state = "cannon_west" if(EAST) setDir(EAST) + pixel_x = -128 + bound_x = -128 top_layer.icon_state = "top_east" icon_state = "cannon_east" add_overlay(top_layer) @@ -211,6 +213,7 @@ message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)] but it was blocked by [blocker] at [ADMIN_VERBOSEJMP(target)].") log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)] but it was blocked by [blocker] at [AREACOORD(target)].") + /obj/machinery/bsa/full/proc/reload() ready = FALSE use_power(power_used_per_shot) @@ -293,15 +296,16 @@ /obj/machinery/computer/bsa_control/proc/get_target_name() if(istype(target, /area)) return get_area_name(target, TRUE) - else if(istype(target, /obj/item/gps)) - var/obj/item/gps/G = target + else if(istype(target, /datum/component/gps)) + var/datum/component/gps/G = target return G.gpstag /obj/machinery/computer/bsa_control/proc/get_impact_turf() if(istype(target, /area)) return pick(get_area_turfs(target)) - else if(istype(target, /obj/item/gps)) - return get_turf(target) + else if(istype(target, /datum/component/gps)) + var/datum/component/gps/G = target + return get_turf(G.parent) /obj/machinery/computer/bsa_control/proc/fire(mob/user) if(cannon.stat) diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 13b1140527..b6a0a387e2 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -180,13 +180,17 @@ . += lips_overlay // eyes - var/image/eyes_overlay = image('icons/mob/human_face.dmi', "eyes", -BODY_LAYER, SOUTH) - . += eyes_overlay - if(!eyes) - eyes_overlay.icon_state = "eyes_missing" - - else if(eyes.eye_color) - eyes_overlay.color = "#" + eyes.eye_color + if(eyes) + var/image/left_eye = image('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER, SOUTH) + var/image/right_eye = image('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER, SOUTH) + if(eyes.left_eye_color && eyes.right_eye_color) + left_eye.color = "#" + eyes.left_eye_color + right_eye.color = "#" + eyes.right_eye_color + . += left_eye + . += right_eye + else + var/eyes_overlay = image('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH) + . += eyes_overlay /obj/item/bodypart/head/monkey icon = 'icons/mob/animal_parts.dmi' diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 9172ce00bc..e3ab44213f 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -26,8 +26,10 @@ var/sight_flags = 0 var/see_in_dark = 2 var/tint = 0 - var/eye_color = "" //set to a hex code to override a mob's eye color - var/old_eye_color = "fff" + var/left_eye_color = "" //set to a hex code to override a mob's eye color + var/right_eye_color = "" + var/old_left_eye_color = "fff" + var/old_right_eye_color = "fff" var/flash_protect = 0 var/see_invisible = SEE_INVISIBLE_LIVING var/lighting_alpha @@ -44,11 +46,19 @@ owner.become_blind(EYE_DAMAGE) if(ishuman(owner)) var/mob/living/carbon/human/H = owner - old_eye_color = H.eye_color - if(eye_color) - H.eye_color = eye_color + old_left_eye_color = H.left_eye_color + old_right_eye_color = H.right_eye_color + + if(left_eye_color) + H.left_eye_color = left_eye_color else - eye_color = H.eye_color + left_eye_color = H.left_eye_color + + if(right_eye_color) + H.right_eye_color = right_eye_color + else + right_eye_color = H.right_eye_color + if(!special) H.dna?.species?.handle_body(H) //regenerate eyeballs overlays. M.update_tint() @@ -64,9 +74,10 @@ C.clear_fullscreen("eye_damage") if(BLIND_VISION_THREE) C.cure_blind(EYE_DAMAGE) - if(ishuman(C) && eye_color) + if(ishuman(C) && left_eye_color && right_eye_color) var/mob/living/carbon/human/H = C - H.eye_color = old_eye_color + H.left_eye_color = old_left_eye_color + H.right_eye_color = old_right_eye_color if(!special) H.dna.species.handle_body(H) if(!special) @@ -162,14 +173,16 @@ /obj/item/organ/eyes/robotic/xray name = "\improper X-ray eyes" desc = "These cybernetic eyes will give you X-ray vision. Blinking is futile." - eye_color = "000" + left_eye_color = "000" + right_eye_color = "000" see_in_dark = 8 sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS /obj/item/organ/eyes/robotic/thermals name = "thermal eyes" desc = "These cybernetic eye implants will give you thermal vision. Vertical slit pupil included." - eye_color = "FC0" + left_eye_color = "FC0" + right_eye_color = "FC0" sight_flags = SEE_MOBS lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE flash_protect = -1 @@ -178,7 +191,8 @@ /obj/item/organ/eyes/robotic/flashlight name = "flashlight eyes" desc = "It's two flashlights rigged together with some wire. Why would you put these in someone's head?" - eye_color ="fee5a3" + left_eye_color ="fee5a3" + right_eye_color ="fee5a3" icon = 'icons/obj/lighting.dmi' icon_state = "flashlight_eyes" flash_protect = 2 @@ -219,7 +233,8 @@ /obj/item/organ/eyes/robotic/glow name = "High Luminosity Eyes" desc = "Special glowing eyes, used by snowflakes who want to be special." - eye_color = "000" + left_eye_color = "000" + right_eye_color = "000" actions_types = list(/datum/action/item_action/organ_action/use, /datum/action/item_action/organ_action/toggle) var/current_color_string = "#ffffff" var/active = FALSE @@ -265,10 +280,6 @@ var/C = input(owner, "Select Color", "Select color", "#ffffff") as color|null if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user) return - var/list/hsv = ReadHSV(RGBtoHSV(C)) - if(hsv[2] > 125) - to_chat(user, "A color that saturated? Surely not!") - return var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num if(!isnum(range)) return @@ -276,14 +287,26 @@ set_distance(clamp(range, 0, max_light_beam_distance)) assume_rgb(C) +#define MAX_SATURATION 192 +#define MAX_LIGHTNESS 256 + /obj/item/organ/eyes/robotic/glow/proc/assume_rgb(newcolor) - current_color_string = newcolor - eye_color = RGB2EYECOLORSTRING(current_color_string) + var/current_color = RGB2EYECOLORSTRING(newcolor) + left_eye_color = current_color + right_eye_color = current_color + var/list/hsv = ReadHSV(RGBtoHSV(newcolor)) + hsv[2] = clamp(hsv[2], 0, MAX_SATURATION) + hsv[3] = clamp(hsv[3], 0, MAX_LIGHTNESS) + var/new_hsv = hsv(hsv[1], hsv[2], hsv[3]) + current_color_string = HSVtoRGB(new_hsv) sync_light_effects() cycle_mob_overlay() if(!QDELETED(owner) && ishuman(owner)) //Other carbon mobs don't have eye color. owner.dna.species.handle_body(owner) +#undef MAX_SATURATION +#undef MAX_LIGHTNESS + /obj/item/organ/eyes/robotic/glow/proc/cycle_mob_overlay() remove_mob_overlay() mob_overlay.color = current_color_string diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 7090ab62e2..929b42f96d 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -11,7 +11,8 @@ var/say_mod = null var/taste_sensitivity = 15 // lower is more sensitive. maxHealth = TONGUE_MAX_HEALTH - var/modifies_speech = FALSE + var/list/initial_accents //the ones the tongue starts with, not what it currently has + var/list/accents = list() //done in order of priority (please always apply abductor accent and stuttering last) var/static/list/languages_possible_base = typecacheof(list( /datum/language/common, /datum/language/draconic, @@ -30,6 +31,8 @@ /obj/item/organ/tongue/Initialize(mapload) . = ..() + for(var/accent in initial_accents) + accents += new accent low_threshold_passed = "Your [name] feels a little sore." low_threshold_cleared = "Your [name] soreness has subsided." high_threshold_passed = "Your [name] is really starting to hurt." @@ -38,12 +41,13 @@ now_fixed = "The excruciating pain of your [name] has subsided." languages_possible = languages_possible_base -/obj/item/organ/tongue/proc/handle_speech(datum/source, list/speech_args) - return +/obj/item/organ/tongue/proc/handle_speech(datum/source, list/speech_args) //this wont proc unless there's initial_accents on the tongue + for(var/datum/accent/speech_modifier in accents) + speech_args = speech_modifier.modify_speech(speech_args, source, owner) /obj/item/organ/tongue/applyOrganDamage(d, maximum = maxHealth) . = ..() - if (damage >= maxHealth) + if(damage >= maxHealth) to_chat(owner, "Your tongue is singed beyond recognition, and disintegrates!") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Tongues lost to Fermi") qdel(src) @@ -52,7 +56,7 @@ ..() if(say_mod && M.dna && M.dna.species) M.dna.species.say_mod = say_mod - if (modifies_speech) + if(length(initial_accents) || length(accents)) RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech) M.UnregisterSignal(M, COMSIG_MOB_SAY) @@ -74,16 +78,7 @@ say_mod = "hisses" taste_sensitivity = 10 // combined nose + tongue, extra sensitive maxHealth = 40 //extra sensitivity means tongue is more susceptible to damage - modifies_speech = TRUE - -/obj/item/organ/tongue/lizard/handle_speech(datum/source, list/speech_args) - var/static/regex/lizard_hiss = new("s+", "g") - var/static/regex/lizard_hiSS = new("S+", "g") - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = lizard_hiss.Replace(message, "sss") - message = lizard_hiSS.Replace(message, "SSS") - speech_args[SPEECH_MESSAGE] = message + initial_accents = list(/datum/accent/lizard) /obj/item/organ/tongue/fly name = "proboscis" @@ -92,16 +87,7 @@ say_mod = "buzzes" taste_sensitivity = 25 // you eat vomit, this is a mercy maxHealth = 80 //years of eatting trash has made your tongue strong - modifies_speech = TRUE - -/obj/item/organ/tongue/fly/handle_speech(datum/source, list/speech_args) - var/static/regex/fly_buzz = new("z+", "g") - var/static/regex/fly_buZZ = new("Z+", "g") - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = fly_buzz.Replace(message, "zzz") - message = fly_buZZ.Replace(message, "ZZZ") - speech_args[SPEECH_MESSAGE] = message + initial_accents = list(/datum/accent/fly) /obj/item/organ/tongue/abductor name = "superlingual matrix" @@ -110,7 +96,7 @@ say_mod = "gibbers" taste_sensitivity = 101 // ayys cannot taste anything. maxHealth = 120 //Ayys probe a lot - modifies_speech = TRUE + initial_accents = list(/datum/accent/abductor) var/mothership /obj/item/organ/tongue/abductor/attack_self(mob/living/carbon/human/H) @@ -138,26 +124,6 @@ else . += "It is attuned to [mothership]." -/obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args) - //Hacks - var/message = speech_args[SPEECH_MESSAGE] - var/mob/living/carbon/human/user = source - var/rendered = "[user.name]: [message]" - user.log_talk(message, LOG_SAY, tag="abductor") - for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) - var/obj/item/organ/tongue/T = H.getorganslot(ORGAN_SLOT_TONGUE) - if(!T || T.type != type) - continue - if(H.dna && H.dna.species.id == "abductor" && user.dna && user.dna.species.id == "abductor") - var/datum/antagonist/abductor/A = user.mind.has_antag_datum(/datum/antagonist/abductor) - if(!A || !(H.mind in A.team.members)) - continue - to_chat(H, rendered) - for(var/mob/M in GLOB.dead_mob_list) - var/link = FOLLOW_LINK(M, user) - to_chat(M, "[link] [rendered]") - speech_args[SPEECH_MESSAGE] = "" - /obj/item/organ/tongue/zombie name = "rotting tongue" desc = "Between the decay and the fact that it's just lying there you doubt a tongue has ever seemed less sexy." @@ -165,23 +131,7 @@ say_mod = "moans" taste_sensitivity = 32 maxHealth = 65 //Stop! It's already dead...! - modifies_speech = TRUE - -/obj/item/organ/tongue/zombie/handle_speech(datum/source, list/speech_args) - var/list/message_list = splittext(speech_args[SPEECH_MESSAGE], " ") - var/maxchanges = max(round(message_list.len / 1.5), 2) - - for(var/i = rand(maxchanges / 2, maxchanges), i > 0, i--) - var/insertpos = rand(1, message_list.len - 1) - var/inserttext = message_list[insertpos] - - if(!(copytext(inserttext, -3) == "..."))//3 == length("...") - message_list[insertpos] = inserttext + "..." - - if(prob(20) && message_list.len > 3) - message_list.Insert(insertpos, "[pick("BRAINS", "Brains", "Braaaiinnnsss", "BRAAAIIINNSSS")]...") - - speech_args[SPEECH_MESSAGE] = jointext(message_list, " ") + initial_accents = list(/datum/accent/zombie) /obj/item/organ/tongue/alien name = "alien tongue" @@ -190,7 +140,7 @@ say_mod = "hisses" taste_sensitivity = 10 // LIZARDS ARE ALIENS CONFIRMED maxHealth = 500 //They've a little mouth for a tongue, so it's pretty rhobust - modifies_speech = TRUE // not really, they just hiss + initial_accents = list(/datum/accent/alien) var/static/list/languages_possible_alien = typecacheof(list( /datum/language/xenocommon, /datum/language/common, @@ -202,9 +152,6 @@ . = ..() languages_possible = languages_possible_alien -/obj/item/organ/tongue/alien/handle_speech(datum/source, list/speech_args) - playsound(owner, "hiss", 25, 1, 1) - /obj/item/organ/tongue/bone name = "bone \"tongue\"" desc = "Apparently skeletons alter the sounds they produce through oscillation of their teeth, hence their characteristic rattling." @@ -214,14 +161,13 @@ attack_verb = list("bitten", "chattered", "chomped", "enamelled", "boned") taste_sensitivity = 101 // skeletons cannot taste anything maxHealth = 75 //Take brute damage instead - modifies_speech = TRUE var/chattering = FALSE var/phomeme_type = "sans" - var/list/phomeme_types = list("sans", "papyrus") + var/list/phomeme_types = list(/datum/accent/span/sans, /datum/accent/span/papyrus) /obj/item/organ/tongue/bone/Initialize() + initial_accents += pick(phomeme_types) . = ..() - phomeme_type = pick(phomeme_types) /obj/item/organ/tongue/bone/applyOrganDamage(var/d, var/maximum = maxHealth) if(d < 0) @@ -234,19 +180,14 @@ return /obj/item/organ/tongue/bone/handle_speech(datum/source, list/speech_args) - if (chattering) + if(chattering) chatter(speech_args[SPEECH_MESSAGE], phomeme_type, source) - switch(phomeme_type) - if("sans") - speech_args[SPEECH_SPANS] |= SPAN_SANS - if("papyrus") - speech_args[SPEECH_SPANS] |= SPAN_PAPYRUS + ..() /obj/item/organ/tongue/bone/plasmaman name = "plasma bone \"tongue\"" desc = "Like animated skeletons, Plasmamen vibrate their teeth in order to produce speech." icon_state = "tongueplasma" - modifies_speech = FALSE /obj/item/organ/tongue/robot name = "robotic voicebox" @@ -256,7 +197,7 @@ icon_state = "tonguerobot" say_mod = "states" attack_verb = list("beeped", "booped") - modifies_speech = TRUE + initial_accents = list(/datum/accent/span/robot) taste_sensitivity = 25 // not as good as an organic tongue maxHealth = 100 //RoboTongue! var/electronics_magic = TRUE @@ -264,34 +205,19 @@ /obj/item/organ/tongue/robot/could_speak_language(language) return ..() || electronics_magic -/obj/item/organ/tongue/robot/handle_speech(datum/source, list/speech_args) - speech_args[SPEECH_SPANS] |= SPAN_ROBOT - /obj/item/organ/tongue/fluffy name = "fluffy tongue" desc = "OwO what's this?" icon_state = "tonguefluffy" taste_sensitivity = 10 // extra sensitive and inquisitive uwu maxHealth = 35 //Sensitive tongue! - modifies_speech = TRUE - -/obj/item/organ/tongue/fluffy/handle_speech(datum/source, list/speech_args) - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = replacetext(message, "ne", "nye") - message = replacetext(message, "nu", "nyu") - message = replacetext(message, "na", "nya") - message = replacetext(message, "no", "nyo") - message = replacetext(message, "ove", "uv") - message = replacetext(message, "l", "w") - message = replacetext(message, "r", "w") - message = lowertext(message) - speech_args[SPEECH_MESSAGE] = message + initial_accents = list(/datum/accent/fluffy) /obj/item/organ/tongue/cybernetic name = "cybernetic tongue" desc = "A state of the art robotic tongue that can detect the pH of anything drank." icon_state = "tonguecybernetic" + initial_accents = list(/datum/accent/span/robot) taste_sensitivity = 10 maxHealth = 60 //It's robotic! organ_flags = ORGAN_SYNTHETIC @@ -303,9 +229,6 @@ var/errormessage = list("Runtime in tongue.dm, line 39: Undefined operation \"zapzap ow my tongue\"", "afhsjifksahgjkaslfhashfjsak", "-1.#IND", "Graham's number", "inside you all along", "awaiting at least 1 approving review before merging this taste request") owner.say("The pH is appropriately [pick(errormessage)].", forced = "EMPed synthetic tongue") -/obj/item/organ/tongue/cybernetic/handle_speech(datum/source, list/speech_args) - speech_args[SPEECH_SPANS] |= SPAN_ROBOT - /obj/item/organ/tongue/robot/ipc name = "positronic voicebox" say_mod = "beeps" diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index c4ded65e9c..0f1004221c 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -10,6 +10,12 @@ tool_behaviour = TOOL_RETRACTOR toolspeed = 1 +/obj/item/retractor/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() + /obj/item/retractor/advanced name = "mechanical pinches" desc = "An agglomerate of rods and gears." @@ -55,6 +61,12 @@ tool_behaviour = TOOL_HEMOSTAT toolspeed = 1 +/obj/item/hemostat/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() + /obj/item/hemostat/augment name = "hemostat" desc = "Tiny servos power a pair of pincers to stop bleeding." @@ -79,6 +91,12 @@ tool_behaviour = TOOL_CAUTERY toolspeed = 1 +/obj/item/cautery/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() + /obj/item/cautery/augment name = "cautery" desc = "A heated element that cauterizes wounds." @@ -107,6 +125,12 @@ tool_behaviour = TOOL_DRILL toolspeed = 1 +/obj/item/surgicaldrill/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() + /obj/item/surgicaldrill/advanced name = "searing tool" desc = "It projects a high power laser used for medical application." @@ -172,6 +196,12 @@ . = ..() AddComponent(/datum/component/butchering, 80 * toolspeed, 100, 0) +/obj/item/scalpel/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() + /obj/item/scalpel/advanced name = "laser scalpel" desc = "An advanced scalpel which uses laser technology to cut." @@ -255,6 +285,11 @@ . = ..() AddComponent(/datum/component/butchering, 40 * toolspeed, 100, 5, 'sound/weapons/circsawhit.ogg') //saws are very accurate and fast at butchering +/obj/item/circular_saw/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() /obj/item/circular_saw/augment name = "circular saw" @@ -392,3 +427,9 @@ attack_verb = list("corrected", "properly set") tool_behaviour = TOOL_BONESET toolspeed = 1 + +/obj/item/bonesetter/attack(mob/living/L, mob/user) + if(user.a_intent == INTENT_HELP) + to_chat(user, "You refrain from hitting [L] with [src], as you are in help intent.") + return + return ..() diff --git a/code/modules/tgchat/message.dm b/code/modules/tgchat/message.dm new file mode 100644 index 0000000000..2e9bfe784e --- /dev/null +++ b/code/modules/tgchat/message.dm @@ -0,0 +1,17 @@ +/** + * Message-related procs + * + * Message format (/list): + * - type - Message type, must be one of defines in `code/__DEFINES/chat.dm` + * - text - Plain message text + * - html - HTML message text + * - Optional metadata, can be any key/value pair. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/proc/message_to_html(message) + // Here it is possible to add a switch statement + // to custom-handle various message types. + return message["html"] || message["text"] diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm new file mode 100644 index 0000000000..a50bf4595e --- /dev/null +++ b/code/modules/tgchat/to_chat.dm @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * Circumvents the message queue and sends the message + * to the recipient (target) as soon as possible. + */ +/proc/to_chat_immediate(target, html, + type = null, + text = null, + avoid_highlighting = FALSE, + // FIXME: These flags are now pointless and have no effect + handle_whitespace = TRUE, + trailing_newline = TRUE, + confidential = FALSE) + if(!target || (!html && !text)) + return + if(target == world) + target = GLOB.clients + // Build a message + var/message = list() + if(type) message["type"] = type + if(text) message["text"] = text + if(html) message["html"] = html + if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + var/message_blob = TGUI_CREATE_MESSAGE("chat/message", message) + var/message_html = message_to_html(message) + if(islist(target)) + for(var/_target in target) + var/client/client = CLIENT_FROM_VAR(_target) + if(client) + // Send to tgchat + client.tgui_panel?.window.send_raw_message(message_blob) + // Send to old chat + SEND_TEXT(client, message_html) + return + var/client/client = CLIENT_FROM_VAR(target) + if(client) + // Send to tgchat + client.tgui_panel?.window.send_raw_message(message_blob) + // Send to old chat + SEND_TEXT(client, message_html) + +/** + * Sends the message to the recipient (target). + * + * Recommended way to write to_chat calls: + * to_chat(client, + * type = MESSAGE_TYPE_INFO, + * html = "You have found [object]") + */ +/proc/to_chat(target, html, + type = null, + text = null, + avoid_highlighting = FALSE, + // FIXME: These flags are now pointless and have no effect + handle_whitespace = TRUE, + trailing_newline = TRUE, + confidential = FALSE) + if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) + to_chat_immediate(target, html, type, text) + return + if(!target || (!html && !text)) + return + if(target == world) + target = GLOB.clients + // Build a message + var/message = list() + if(type) message["type"] = type + if(text) message["text"] = text + if(html) message["html"] = html + if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting + SSchat.queue(target, message) diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm index 46b324e151..8f47c609b2 100644 --- a/code/modules/tgui/external.dm +++ b/code/modules/tgui/external.dm @@ -130,6 +130,13 @@ */ /client/var/list/tgui_windows = list() +/** + * global + * + * TRUE if cache was reloaded by tgui dev server at least once. + */ +/client/var/tgui_cache_reloaded = FALSE + /** * public * @@ -159,25 +166,44 @@ /** * Middleware for /client/Topic. * - * return bool Whether the topic is passed (TRUE), or cancelled (FALSE). + * return bool If TRUE, prevents propagation of the topic call. */ /proc/tgui_Topic(href_list) // Skip non-tgui topics if(!href_list["tgui"]) - return TRUE + return FALSE var/type = href_list["type"] // Unconditionally collect tgui logs if(type == "log") - log_tgui(usr, href_list["message"]) + var/context = href_list["window_id"] + if (href_list["ns"]) + context += " ([href_list["ns"]])" + log_tgui(usr, href_list["message"], + context = context) + // Reload all tgui windows + if(type == "cacheReloaded") + if(!check_rights(R_ADMIN) || usr.client.tgui_cache_reloaded) + return TRUE + // Mark as reloaded + usr.client.tgui_cache_reloaded = TRUE + // Notify windows + var/list/windows = usr.client.tgui_windows + for(var/window_id in windows) + var/datum/tgui_window/window = windows[window_id] + if (window.status == TGUI_WINDOW_READY) + window.on_message(type, null, href_list) + return TRUE // Locate window var/window_id = href_list["window_id"] var/datum/tgui_window/window if(window_id) window = usr.client.tgui_windows[window_id] if(!window) - log_tgui(usr, "Error: Couldn't find the window datum, force closing.") + log_tgui(usr, + "Error: Couldn't find the window datum, force closing.", + context = window_id) SStgui.force_close_window(usr, window_id) - return FALSE + return TRUE // Decode payload var/payload if(href_list["payload"]) @@ -185,4 +211,4 @@ // Pass message to window if(window) window.on_message(type, payload, href_list) - return FALSE + return TRUE diff --git a/code/modules/tgui/states/debug.dm b/code/modules/tgui/states/debug.dm new file mode 100644 index 0000000000..6c600b38ce --- /dev/null +++ b/code/modules/tgui/states/debug.dm @@ -0,0 +1,6 @@ +GLOBAL_DATUM_INIT(debug_state, /datum/ui_state/debug_state, new) + +/datum/ui_state/debug_state/can_use_topic(src_object, mob/user) + if(check_rights_for(user.client, R_DEBUG)) + return UI_INTERACTIVE + return UI_CLOSE diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index d0d5ff8ebb..9393b9641f 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -49,7 +49,9 @@ * return datum/tgui The requested UI. */ /datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y) - log_tgui(user, "new [interface] fancy [user.client.prefs.tgui_fancy]") + log_tgui(user, + "new [interface] fancy [user.client.prefs.tgui_fancy]", + src_object = src_object) src.user = user src.src_object = src_object src.window_key = "[REF(src_object)]-main" @@ -80,14 +82,20 @@ opened_at = world.time window.acquire_lock(src) if(!window.is_ready()) - window.initialize(inline_assets = list( - get_asset_datum(/datum/asset/simple/tgui), - )) + window.initialize( + fancy = user.client.prefs.tgui_fancy, + inline_assets = list( + get_asset_datum(/datum/asset/simple/tgui_common), + get_asset_datum(/datum/asset/simple/tgui), + )) else window.send_message("ping") - window.send_asset(get_asset_datum(/datum/asset/simple/fontawesome)) + var/flush_queue = window.send_asset(get_asset_datum( + /datum/asset/simple/namespaced/fontawesome)) for(var/datum/asset/asset in src_object.ui_assets(user)) - window.send_asset(asset) + flush_queue |= window.send_asset(asset) + if (flush_queue) + user.client.browse_queue_flush() window.send_message("update", get_payload( with_data = TRUE, with_static_data = TRUE)) @@ -143,11 +151,13 @@ * Makes an asset available to use in tgui. * * required asset datum/asset + * + * return bool - true if an asset was actually sent */ /datum/tgui/proc/send_asset(datum/asset/asset) if(!window) CRASH("send_asset() can only be called after open().") - window.send_asset(asset) + return window.send_asset(asset) /** * public @@ -199,13 +209,17 @@ "key" = window_key, "size" = window_size, "fancy" = user.client.prefs.tgui_fancy, - "locked" = user.client.prefs.tgui_lock + "locked" = user.client.prefs.tgui_lock, + ), + "client" = list( + "ckey" = user.client.ckey, + "address" = user.client.address, + "computer_id" = user.client.computer_id, ), "user" = list( "name" = "[user]", - "ckey" = "[user.ckey]", - "observer" = isobserver(user) - ) + "observer" = isobserver(user), + ), ) var/data = custom_data || with_data && src_object.ui_data(user) if(data) @@ -233,11 +247,9 @@ return // Validate ping if(!initialized && world.time - opened_at > TGUI_PING_TIMEOUT) - log_tgui(user, \ - "Error: Zombie window detected, killing it with fire.\n" \ - + "window_id: [window.id]\n" \ - + "opened_at: [opened_at]\n" \ - + "world.time: [world.time]") + log_tgui(user, "Error: Zombie window detected, closing.", + window = window, + src_object = src_object) close(can_be_suspended = FALSE) return // Update through a normal call to ui_interact @@ -270,8 +282,12 @@ /datum/tgui/proc/on_message(type, list/payload, list/href_list) // Pass act type messages to ui_act if(type && copytext(type, 1, 5) == "act/") + var/act_type = copytext(type, 5) + log_tgui(user, "Action: [act_type] [href_list["payload"]]", + window = window, + src_object = src_object) process_status() - if(src_object.ui_act(copytext(type, 5), payload, src, state)) + if(src_object.ui_act(act_type, payload, src, state)) SStgui.update_uis(src_object) return FALSE switch(type) diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm index 3f271163c9..23583e8b53 100644 --- a/code/modules/tgui/tgui_window.dm +++ b/code/modules/tgui/tgui_window.dm @@ -8,12 +8,18 @@ var/client/client var/pooled var/pool_index + var/is_browser = FALSE var/status = TGUI_WINDOW_CLOSED var/locked = FALSE var/datum/tgui/locked_by + var/datum/subscriber_object + var/subscriber_delegate var/fatally_errored = FALSE var/message_queue var/sent_assets = list() + // Vars passed to initialize proc (and saved for later) + var/inline_assets + var/fancy /** * public @@ -26,9 +32,9 @@ /datum/tgui_window/New(client/client, id, pooled = FALSE) src.id = id src.client = client + src.client.tgui_windows[id] = src src.pooled = pooled if(pooled) - client.tgui_windows[id] = src src.pool_index = TGUI_WINDOW_INDEX(id) /** @@ -39,18 +45,26 @@ * will be put into the queue until the window finishes loading. * * optional inline_assets list List of assets to inline into the html. + * optional inline_html string Custom HTML to inject. + * optional fancy bool If TRUE, will hide the window titlebar. */ -/datum/tgui_window/proc/initialize(inline_assets = list()) - log_tgui(client, "[id]/initialize") +/datum/tgui_window/proc/initialize( + inline_assets = list(), + inline_html = "", + fancy = FALSE) + log_tgui(client, + context = "[id]/initialize", + window = src) if(!client) return + src.inline_assets = inline_assets + src.fancy = fancy status = TGUI_WINDOW_LOADING fatally_errored = FALSE - message_queue = null // Build window options var/options = "file=[id].html;can_minimize=0;auto_format=0;" // Remove titlebar and resize handles for a fancy window - if(client.prefs.tgui_fancy) + if(fancy) options += "titlebar=0;can_resize=0;" else options += "titlebar=1;can_resize=1;" @@ -69,13 +83,17 @@ inline_styles += "\n" else if(copytext(name, -3) == ".js") inline_scripts += "\n" - asset.send() + asset.send(client) html = replacetextEx(html, "\n", inline_styles) html = replacetextEx(html, "\n", inline_scripts) + // Inject custom HTML + html = replacetextEx(html, "\n", inline_html) // Open the window client << browse(html, "window=[id];[options]") // Instruct the client to signal UI when the window is closed. winset(client, id, "on-close=\"uiclose [id]\"") + // Detect whether the control is a browser + is_browser = winexists(client, id) == "BROWSER" /** * public @@ -107,8 +125,8 @@ * Acquire the window lock. Pool will not be able to provide this window * to other UIs for the duration of the lock. * - * Can be given an optional tgui datum, which will hook its on_message - * callback into the message stream. + * Can be given an optional tgui datum, which will be automatically + * subscribed to incoming messages via the on_message proc. * * optional ui /datum/tgui */ @@ -117,6 +135,8 @@ locked_by = ui /** + * public + * * Release the window lock. */ /datum/tgui_window/proc/release_lock() @@ -126,6 +146,28 @@ locked = FALSE locked_by = null +/** + * public + * + * Subscribes the datum to consume window messages on a specified proc. + * + * Note, that this supports only one subscriber, because code for that + * is simpler and therefore faster. If necessary, this can be rewritten + * to support multiple subscribers. + */ +/datum/tgui_window/proc/subscribe(datum/object, delegate) + subscriber_object = object + subscriber_delegate = delegate + +/** + * public + * + * Unsubscribes the datum. Do not forget to call this when cleaning up. + */ +/datum/tgui_window/proc/unsubscribe(datum/object) + subscriber_object = null + subscriber_delegate = null + /** * public * @@ -137,11 +179,15 @@ if(!client) return if(can_be_suspended && can_be_suspended()) - log_tgui(client, "[id]/close: suspending") + log_tgui(client, + context = "[id]/close (suspending)", + window = src) status = TGUI_WINDOW_READY send_message("suspend") return - log_tgui(client, "[id]/close") + log_tgui(client, + context = "[id]/close", + window = src) release_lock() status = TGUI_WINDOW_CLOSED message_queue = null @@ -159,25 +205,40 @@ * required payload list Message payload * optional force bool Send regardless of the ready status. */ -/datum/tgui_window/proc/send_message(type, list/payload, force) +/datum/tgui_window/proc/send_message(type, payload, force) if(!client) return - var/message = json_encode(list( - "type" = type, - "payload" = payload, - )) - // Strip #255/improper. - message = replacetext(message, "\proper", "") - message = replacetext(message, "\improper", "") - // Pack for sending via output() - message = url_encode(message) + var/message = TGUI_CREATE_MESSAGE(type, payload) // Place into queue if window is still loading if(!force && status != TGUI_WINDOW_READY) if(!message_queue) message_queue = list() message_queue += list(message) return - client << output(message, "[id].browser:update") + client << output(message, is_browser \ + ? "[id]:update" \ + : "[id].browser:update") + +/** + * public + * + * Sends a raw payload to tgui window. + * + * required message string JSON+urlencoded blob to send. + * optional force bool Send regardless of the ready status. + */ +/datum/tgui_window/proc/send_raw_message(message, force) + if(!client) + return + // Place into queue if window is still loading + if(!force && status != TGUI_WINDOW_READY) + if(!message_queue) + message_queue = list() + message_queue += list(message) + return + client << output(message, is_browser \ + ? "[id]:update" \ + : "[id].browser:update") /** * public @@ -185,16 +246,18 @@ * Makes an asset available to use in tgui. * * required asset datum/asset + * + * return bool - TRUE if any assets had to be sent to the client */ /datum/tgui_window/proc/send_asset(datum/asset/asset) if(!client || !asset) return + sent_assets |= list(asset) + . = asset.send(client) if(istype(asset, /datum/asset/spritesheet)) var/datum/asset/spritesheet/spritesheet = asset send_message("asset/stylesheet", spritesheet.css_filename()) send_message("asset/mappings", asset.get_url_mappings()) - sent_assets += list(asset) - asset.send(client) /** * private @@ -205,7 +268,9 @@ if(!client || !message_queue) return for(var/message in message_queue) - client << output(message, "[id].browser:update") + client << output(message, is_browser \ + ? "[id]:update" \ + : "[id].browser:update") message_queue = null /** @@ -213,26 +278,45 @@ * * Callback for handling incoming tgui messages. */ -/datum/tgui_window/proc/on_message(type, list/payload, list/href_list) - switch(type) - if("ready") - // Status can be READY if user has refreshed the window. - if(status == TGUI_WINDOW_READY) - // Resend the assets - for(var/asset in sent_assets) - send_asset(asset) - status = TGUI_WINDOW_READY - if("log") - if(href_list["fatal"]) - fatally_errored = TRUE +/datum/tgui_window/proc/on_message(type, payload, href_list) + // Status can be READY if user has refreshed the window. + if(type == "ready" && status == TGUI_WINDOW_READY) + // Resend the assets + for(var/asset in sent_assets) + send_asset(asset) + // Mark this window as fatally errored which prevents it from + // being suspended. + if(type == "log" && href_list["fatal"]) + fatally_errored = TRUE + // Mark window as ready since we received this message from somewhere + if(status != TGUI_WINDOW_READY) + status = TGUI_WINDOW_READY + flush_message_queue() // Pass message to UI that requested the lock if(locked && locked_by) - locked_by.on_message(type, payload, href_list) - flush_message_queue() - return + var/prevent_default = locked_by.on_message(type, payload, href_list) + if(prevent_default) + return + // Pass message to the subscriber + else if(subscriber_object) + var/prevent_default = call( + subscriber_object, + subscriber_delegate)(type, payload, href_list) + if(prevent_default) + return // If not locked, handle these message types switch(type) + if("ping") + send_message("pingReply", payload) if("suspend") close(can_be_suspended = TRUE) if("close") close(can_be_suspended = FALSE) + if("openLink") + client << link(href_list["url"]) + if("cacheReloaded") + // Reinitialize + initialize(inline_assets = inline_assets, fancy = fancy) + // Resend the assets + for(var/asset in sent_assets) + send_asset(asset) diff --git a/code/modules/tgui_panel/audio.dm b/code/modules/tgui_panel/audio.dm new file mode 100644 index 0000000000..e62c4b5bc1 --- /dev/null +++ b/code/modules/tgui_panel/audio.dm @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/// Admin music volume, from 0 to 1. +/client/var/admin_music_volume = 1 + +/** + * public + * + * Sends music data to the browser. + * + * Optional settings: + * - pitch: the playback rate + * - start: the start time of the sound + * - end: when the musics stops playing + * + * required url string Must be an https URL. + * optional extra_data list Optional settings. + */ +/datum/tgui_panel/proc/play_music(url, extra_data) + if(!is_ready()) + return + if(!findtext(url, GLOB.is_http_protocol)) + return + var/list/payload = list() + if(length(extra_data) > 0) + for(var/key in extra_data) + payload[key] = extra_data[key] + payload["url"] = url + window.send_message("audio/playMusic", payload) + +/** + * public + * + * Stops playing music through the browser. + */ +/datum/tgui_panel/proc/stop_music() + if(!is_ready()) + return + window.send_message("audio/stopMusic") diff --git a/code/modules/tgui_panel/external.dm b/code/modules/tgui_panel/external.dm new file mode 100644 index 0000000000..35aa31eca7 --- /dev/null +++ b/code/modules/tgui_panel/external.dm @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/client/var/datum/tgui_panel/tgui_panel + +/** + * tgui panel / chat troubleshooting verb + */ +/client/verb/fix_tgui_panel() + set name = "Fix chat" + set category = "OOC" + var/action + log_tgui(src, "Started fixing.", + context = "verb/fix_tgui_panel") + // Not ready + if(!tgui_panel?.is_ready()) + log_tgui(src, "Panel is not ready", + context = "verb/fix_tgui_panel") + tgui_panel.window.send_message("ping", force = TRUE) + action = alert(src, "Method: Pinging the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope") + if(action == "Fixed") + log_tgui(src, "Fixed by sending a ping", + context = "verb/fix_tgui_panel") + return + // Catch all solution + if(!tgui_panel || !istype(tgui_panel)) + log_tgui(src, "tgui_panel datum is missing", + context = "verb/fix_tgui_panel") + tgui_panel = new(src) + tgui_panel.initialize(force = TRUE) + // Force show the panel to see if there are any errors + winset(src, "output", "is-disabled=1&is-visible=0") + winset(src, "browseroutput", "is-disabled=0;is-visible=1") + action = alert(src, "Method: Reinitializing the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope") + if(action == "Fixed") + log_tgui(src, "Fixed by calling 'initialize'", + context = "verb/fix_tgui_panel") + return + // Failed to fix + action = alert(src, "Welp, I'm all out of ideas. Try closing BYOND and reconnecting.\nWe could also disable tgui_panel and re-enable the old UI", "", "Thanks anyways", "Switch to old UI") + if (action == "Switch to old UI") + winset(src, "output", "on-show=&is-disabled=0&is-visible=1") + winset(src, "browseroutput", "is-disabled=1;is-visible=0") + log_tgui(src, "Failed to fix.", + context = "verb/fix_tgui_panel") diff --git a/code/modules/tgui_panel/telemetry.dm b/code/modules/tgui_panel/telemetry.dm new file mode 100644 index 0000000000..79087d8500 --- /dev/null +++ b/code/modules/tgui_panel/telemetry.dm @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * Maximum number of connection records allowed to analyze. + * Should match the value set in the browser. + */ +#define TGUI_TELEMETRY_MAX_CONNECTIONS 5 + +/** + * Maximum time allocated for sending a telemetry packet. + */ +#define TGUI_TELEMETRY_RESPONSE_WINDOW 30 SECONDS + +/// Time of telemetry request +/datum/tgui_panel/var/telemetry_requested_at +/// Time of telemetry analysis completion +/datum/tgui_panel/var/telemetry_analyzed_at +/// List of previous client connections +/datum/tgui_panel/var/list/telemetry_connections + +/** + * private + * + * Requests some telemetry from the client. + */ +/datum/tgui_panel/proc/request_telemetry() + telemetry_requested_at = world.time + telemetry_analyzed_at = null + window.send_message("telemetry/request", list( + "limits" = list( + "connections" = TGUI_TELEMETRY_MAX_CONNECTIONS, + ), + )) + +/** + * private + * + * Analyzes a telemetry packet. + * + * Is currently only useful for detecting ban evasion attempts. + */ +/datum/tgui_panel/proc/analyze_telemetry(payload) + if(world.time > telemetry_requested_at + TGUI_TELEMETRY_RESPONSE_WINDOW) + message_admins("[key_name(client)] sent telemetry outside of the allocated time window.") + return + if(telemetry_analyzed_at) + message_admins("[key_name(client)] sent telemetry more than once.") + return + telemetry_analyzed_at = world.time + if(!payload) + return + telemetry_connections = payload["connections"] + var/len = length(telemetry_connections) + if(len == 0) + return + if(len > TGUI_TELEMETRY_MAX_CONNECTIONS) + message_admins("[key_name(client)] was kicked for sending a huge telemetry payload") + qdel(client) + return + var/list/found + for(var/i in 1 to len) + if(QDELETED(client)) + // He got cleaned up before we were done + return + var/list/row = telemetry_connections[i] + // Check for a malformed history object + if (!row || row.len < 3 || (!row["ckey"] || !row["address"] || !row["computer_id"])) + return + if (world.IsBanned(row["ckey"], row["address"], row["computer_id"], real_bans_only = TRUE)) + found = row + break + CHECK_TICK + // This fucker has a history of playing on a banned account. + if(found) + var/msg = "[key_name(client)] has a banned account in connection history! (Matched: [found["ckey"]], [found["address"]], [found["computer_id"]])" + message_admins(msg) + log_admin_private(msg) diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm new file mode 100644 index 0000000000..b983484046 --- /dev/null +++ b/code/modules/tgui_panel/tgui_panel.dm @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * tgui_panel datum + * Hosts tgchat and other nice features. + */ +/datum/tgui_panel + var/client/client + var/datum/tgui_window/window + var/broken = FALSE + var/initialized_at + +/datum/tgui_panel/New(client/client) + src.client = client + window = new(client, "browseroutput") + window.subscribe(src, .proc/on_message) + +/datum/tgui_panel/Del() + window.unsubscribe(src) + window.close() + return ..() + +/** + * public + * + * TRUE if panel is initialized and ready to receive messages. + */ +/datum/tgui_panel/proc/is_ready() + return !broken && window.is_ready() + +/** + * public + * + * Initializes tgui panel. + */ +/datum/tgui_panel/proc/initialize(force = FALSE) + initialized_at = world.time + // Perform a clean initialization + window.initialize(inline_assets = list( + get_asset_datum(/datum/asset/simple/tgui_common), + get_asset_datum(/datum/asset/simple/tgui_panel), + )) + window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/fontawesome)) + window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat)) + request_telemetry() + addtimer(CALLBACK(src, .proc/on_initialize_timed_out), 2 SECONDS) + +/** + * private + * + * Called when initialization has timed out. + */ +/datum/tgui_panel/proc/on_initialize_timed_out() + // Currently does nothing but sending a message to old chat. + SEND_TEXT(client, "Failed to load fancy chat, reverting to old chat. Certain features won't work.") + +/** + * private + * + * Callback for handling incoming tgui messages. + */ +/datum/tgui_panel/proc/on_message(type, payload) + if(type == "ready") + broken = FALSE + window.send_message("update", list( + "config" = list( + "client" = list( + "ckey" = client.ckey, + "address" = client.address, + "computer_id" = client.computer_id, + ), + "window" = list( + "fancy" = FALSE, + "locked" = FALSE, + ), + ), + )) + return TRUE + if(type == "audio/setAdminMusicVolume") + client.admin_music_volume = payload["volume"] + return TRUE + if(type == "telemetry") + analyze_telemetry(payload) + return TRUE + +/** + * public + * + * Sends a round restart notification. + */ +/datum/tgui_panel/proc/send_roundrestart() + window.send_message("roundrestart") diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index c739d426c2..e758a43589 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -3,6 +3,7 @@ #ifdef UNIT_TESTS #include "anchored_mobs.dm" +#include "character_saving.dm" #include "component_tests.dm" #include "reagent_id_typos.dm" #include "reagent_recipe_collisions.dm" diff --git a/code/modules/unit_tests/character_saving.dm b/code/modules/unit_tests/character_saving.dm new file mode 100644 index 0000000000..bdcb0f0276 --- /dev/null +++ b/code/modules/unit_tests/character_saving.dm @@ -0,0 +1,14 @@ +/datum/unit_test/character_saving/Run() + try + var/datum/preferences/P = new + P.load_path("test") + P.features["flavor_text"] = "Foo" + P.features["ooc_notes"] = "Bar" + P.save_character() + P.load_character() + if(P.features["flavor_text"] != "Foo") + Fail("Flavor text is failing to save.") + if(P.features["ooc_notes"] != "Bar") + Fail("OOC text is failing to save.") + catch(var/exception/e) + Fail("Failed to save and load character due to exception [e.file]:[e.line], [e.name]") diff --git a/code/modules/unit_tests/reactions.dm b/code/modules/unit_tests/reactions.dm new file mode 100644 index 0000000000..66d9b49099 --- /dev/null +++ b/code/modules/unit_tests/reactions.dm @@ -0,0 +1,6 @@ +/datum/unit_test/reactions/Run() + for(var/datum/gas_reaction/G in SSair.gas_reactions) + var/test_info = G.test() + if(!test_info["success"]) + var/message = test_info["message"] + Fail("Gas reaction [G.name] is failing its unit test with the following message: [message]") diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm index c26a9ae1f0..745eddcc07 100644 --- a/code/modules/uplink/uplink_items/uplink_clothing.dm +++ b/code/modules/uplink/uplink_items/uplink_clothing.dm @@ -90,6 +90,7 @@ desc = "Through bluespace magic stolen from an organisation that hoards technology, these boots simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through." item = /obj/item/clothing/shoes/wallwalkers cost = 6 + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/device_tools/guerillagloves name = "Guerilla Gloves" diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm index 58cb43996d..898b716775 100644 --- a/code/modules/uplink/uplink_items/uplink_dangerous.dm +++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm @@ -20,6 +20,7 @@ desc = "A sleek box containing a brutally simple Syndicate revolver that fires .357 Magnum rounds and has 7 chambers, and an extra speedloader." item = /obj/item/storage/box/syndie_kit/revolver cost = 13 + player_minimum = 15 surplus = 50 exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) diff --git a/code/modules/vending/kinkmate.dm b/code/modules/vending/kinkmate.dm index a78a4e6ef4..e522583772 100644 --- a/code/modules/vending/kinkmate.dm +++ b/code/modules/vending/kinkmate.dm @@ -26,7 +26,12 @@ /obj/item/clothing/under/shorts/polychromic/pantsu = 3, /obj/item/clothing/under/misc/poly_bottomless = 3, /obj/item/clothing/under/misc/poly_tanktop = 3, - /obj/item/clothing/under/misc/poly_tanktop/female = 3 + /obj/item/clothing/under/misc/poly_tanktop/female = 3, + /obj/item/autosurgeon/penis = 3, + /obj/item/autosurgeon/testicles = 3, + /obj/item/storage/pill_bottle/penis_enlargement = 5, + /obj/item/storage/pill_bottle/breast_enlargement = 5, + /obj/item/storage/daki = 4 ) contraband = list( /obj/item/clothing/neck/petcollar/locked = 2, diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 26beccaac0..bbe0e40d9b 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -91,6 +91,9 @@ /obj/item/clothing/suit/hooded/wintercoat/engineering = 3, /obj/item/clothing/under/rank/engineering/engineer = 5, /obj/item/clothing/under/rank/engineering/engineer/skirt = 5, + /obj/item/clothing/under/rank/engineering/engineer/hazard = 5, + /obj/item/clothing/under/rank/engineering/engineer/hazard/green = 5, + /obj/item/clothing/under/rank/engineering/engineer/hazard/white = 5, /obj/item/clothing/suit/hazardvest = 5, /obj/item/clothing/shoes/workboots = 5, /obj/item/clothing/head/hardhat = 5, @@ -160,7 +163,10 @@ /obj/item/clothing/shoes/sneakers/black = 3, /obj/item/clothing/gloves/fingerless = 3, /obj/item/clothing/head/soft/black = 3, - /obj/item/clothing/mask/bandana/skull = 2) + /obj/item/clothing/mask/bandana/skull = 2, + /obj/item/clothing/under/misc/mechsuitred = 1, + /obj/item/clothing/under/misc/mechsuitwhite = 1, + /obj/item/clothing/under/misc/mechsuitblue = 1) contraband = list(/obj/item/clothing/suit/hooded/techpriest = 2) refill_canister = /obj/item/vending_refill/wardrobe/robo_wardrobe payment_department = ACCOUNT_SCI diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm index 9395cef952..6949a7030f 100644 --- a/code/modules/vore/eating/living.dm +++ b/code/modules/vore/eating/living.dm @@ -11,13 +11,11 @@ // Hook for generic creation of stuff on new creatures // /hook/living_new/proc/vore_setup(mob/living/M) - M.verbs += /mob/living/proc/preyloop_refresh - M.verbs += /mob/living/proc/lick - M.verbs += /mob/living/proc/escapeOOC + add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC)) if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach. return TRUE - M.verbs += /mob/living/proc/insidePanel + add_verb(M, /mob/living/proc/insidePanel) //Tries to load prefs if a client is present otherwise gives freebie stomach spawn(2 SECONDS) // long delay because the server delays in its startup. just on the safe side. diff --git a/config/config.txt b/config/config.txt index 46f9a0cdc4..a550e6bf8a 100644 --- a/config/config.txt +++ b/config/config.txt @@ -4,6 +4,8 @@ $include game_options.txt $include dbconfig.txt $include comms.txt $include antag_rep.txt +$include resources.txt +# Cit-specific imports $include donator_groupings.txt $include dynamic_config.txt $include plushies/defines.txt @@ -431,6 +433,8 @@ AUTOADMIN_RANK Game Master #CLIENT_WARN_MESSAGE Byond released 511 as the stable release. You can set the framerate your client runs at, which makes the game feel very different and cool. Shortly after its release we will end up using 511 client features and you will be forced to update. CLIENT_ERROR_VERSION 511 CLIENT_ERROR_MESSAGE Your version of byond is not supported. Please upgrade. +## The minimum build needed for joining the server, if using 512, a good minimum build would be 1421 as that disables the Middle Mouse Button exploit. +CLIENT_ERROR_BUILD 1421 ## TOPIC RATE LIMITING ## This allows you to limit how many topic calls (clicking on an interface window) the client can do in any given game second and/or game minute. diff --git a/config/policy.json b/config/policy.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/config/policy.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/config/resources.txt b/config/resources.txt new file mode 100644 index 0000000000..909bef0809 --- /dev/null +++ b/config/resources.txt @@ -0,0 +1,38 @@ +# External resources +# Set this to the location of a .zip with the server's .rsc inside of it. +# If you set this mutiple times, the server will rotate between the links. +# To use this, the compile option PRELOAD_RSC must be set to 0 to keep byond from preloading resources + +EXTERNAL_RSC_URLS http://tgstation13.download/byond/tgstationv2.zip + + +######################## +# Browser Asset Config # +######################## +# Browser assets are any file included in interfaces. css, images, javascript, etc. +# This handles configuring how we get these to the player so interfaces can access them. + +# Asset Transport +# The normal way of getting assets to clients is to use the internal byond system. This can be slow and delay the opening of interface windows. It also doesn't allow the internal IE windows byond uses to cache anything. +# You can instead have the server save them to a website via a folder within the game server that the web server can read. This could be a simple webserver or something backed by a CDN. +# Valid values: simple, webroot. Simple is the default. +#ASSET_TRANSPORT webroot + + +# Simple asset transport configurable values. + +# Uncomment this to have the server passively send all browser assets to each client in the background. (instead of waiting for them to be needed) +# This should be uncommented in production and commented in development +#ASSET_SIMPLE_PRELOAD + + +# Webroot asset transport configurable values. + +# Local folder to save assets to. +# Assets will be saved in the format of asset.MD5HASH.EXT or in namespaces/hash/ as ASSET_FILE_NAME or asset.MD5HASH.EXT +#ASSET_CDN_WEBROOT data/asset-store/ + +# URL the folder from above can be accessed from. +# for best results the webserver powering this should return a long cache validity time, as all assets sent via this transport use hash based urls +# if you want to test this locally, you simpily run the `localhost-asset-webroot-server.py` python3 script to host assets stored in `data/asset-store/` via http://localhost:58715/ +#ASSET_CDN_URL http://localhost:58715/ diff --git a/html/panels.css b/html/admin/panels.css similarity index 97% rename from html/panels.css rename to html/admin/panels.css index 1f969c690e..22373ee0ca 100644 --- a/html/panels.css +++ b/html/admin/panels.css @@ -1,10 +1,10 @@ -body {padding:0px;margin:0px;} -#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;} -#main {position:relative;top:10px;left:3%;width:96%;text-align:center;z-index:0;} -#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";} -tr.norm {background-color:#f4f4f4;} -tr.title {background-color:#ccc;} -tr.alt {background-color:#e7e7e7;} -.small {font-size:80%;} -a {text-decoration:none;} -a:hover {color:#d3d;} +body {padding:0px;margin:0px;} +#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;} +#main {position:relative;top:10px;left:3%;width:96%;text-align:center;z-index:0;} +#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";} +tr.norm {background-color:#f4f4f4;} +tr.title {background-color:#ccc;} +tr.alt {background-color:#e7e7e7;} +.small {font-size:80%;} +a {text-decoration:none;} +a:hover {color:#d3d;} diff --git a/html/search.js b/html/admin/search.js similarity index 100% rename from html/search.js rename to html/admin/search.js diff --git a/html/changelog.html b/html/changelog.html index dff9c06723..ff47eda1c3 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,449 @@

    30 August 2020

    raspy-on-osu updated:

    +

    29 September 2020

    +

    timothyteakettle updated:

    +
      +
    • fixed a typo causing your right eye colour to save as the left eye colour
    • +
    + +

    28 September 2020

    +

    ArchieBeepBoop updated:

    +
      +
    • Craftable Micro Powered Fans
    • +
    +

    Degirin2120 updated:

    +
      +
    • Added engineering hazard jumpsuits, can be found in the engidrobe, comes in 3 varieties.
    • +
    +

    Putnam3145 updated:

    +
      +
    • Added a brute-force check-every-single-tile step to SSair when it has enough time to run.
    • +
    • G fuid production is now much lower.
    • +
    • Supermatter sabotage objective's gone.
    • +
    • Subterfuge objectives are now all equally likely.
    • +
    • Replaced a "(hopefully) 1" with a "2"
    • +
    • Cryoing no longer unwins already-won objectives.
    • +
    +

    SiliconMain updated:

    +
      +
    • Minor adjustment to material cost of long range atmos analyzer
    • +
    +

    Trilbyspaceclone updated:

    +
      +
    • Most drinks now have some animation in them, from basic soda bubbles fizzing around to ice cubes bobbing just a bit.
    • +
    +

    Tupinambis updated:

    +
      +
    • Ghost poly's color value is now a hex value instead of an oct value. This has been a thing for OVER FIVE YEARS
    • +
    • Updates TEG, Antimatter, Jetpack sprites (CO2 and Oxy from Eris).
    • +
    • Replaced old chair sprites with new ones ported and modified from eris.
    • +
    • Beds can now be placed both right and left.
    • +
    • Subtle changes to stool legs to give them more of a shine.
    • +
    +

    raspy-on-osu updated:

    +
      +
    • TEG power generation
    • +
    +

    thakyZ updated:

    +
      +
    • Added the ability to print the Light Replacer at the Engineering Protolathe
    • +
    +

    timothyteakettle updated:

    +
      +
    • turrets can once again be broken
    • +
    • you can now have heterochromia and select individual eye colours
    • +
    + +

    27 September 2020

    +

    SiliconMain updated:

    +
      +
    • Holograms made from projectors (atmos, engi, sec, medical, ect...) can no longer be contaminated by radiation
    • +
    + +

    26 September 2020

    +

    CoreFlare updated:

    +
      +
    • IPC's can have hair. Why wasn't this added earlier. Use the bald hairstyle for no hair.
    • +
    + +

    25 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Removed a non-working proc that already had its functionality implemented in another proc in the same file.
    • +
    + +

    24 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Atmos is free.
    • +
    + +

    22 September 2020

    +

    Arturlang updated:

    +
      +
    • TGUI Statpanel
    • +
    +

    YakumoChen updated:

    +
      +
    • Mechsuits, robotics jumpsuits added to RoboDrobe
    • +
    +

    timothyteakettle updated:

    +
      +
    • character previews should be more consistent now
    • +
    + +

    20 September 2020

    +

    DeltaFire15 updated:

    +
      +
    • Sutures work on simplemobs again.
    • +
    • Attacking dismembered bodyparts now targets the chest instead, for weapons aswell as unarmed attacks.
    • +
    +

    MrJWhit updated:

    +
      +
    • New sprites for chess pieces! You can craft them in-game with metal sheets.
    • +
    +

    silicons updated:

    +
      +
    • hulks can smash again (walls no longer break their hands)
    • +
    • acid no longer degrades armor
    • +
    + +

    17 September 2020

    +

    DeltaFire15 updated:

    +
      +
    • Failing the plushmium reaction can now create peculiar plushies, depending on reaction volume.
    • +
    • The mood-buff from petting a plushie now works properly again.
    • +
    • Fixed wacky necropolis loot chest behavior
    • +
    +

    EmeraldSundisk updated:

    +
      +
    • Adds the Research Director's office to Omega Station
    • +
    • Adds 2 new solar arrays (and control rooms)
    • +
    • Adds some action figures that weren't there previously
    • +
    • The CMO's office now has a light switch
    • +
    • Slight readjustments to impacted areas
    • +
    • Readjusts the toxins air supply line to (ideally) be easier to service
    • +
    • Department camera consoles should now be able to actually check appropriate cameras
    • +
    • Xenobiology can now be locked down (by the Research Director)
    • +
    +

    MrJWhit updated:

    +
      +
    • Adds a brain damage line
    • +
    +

    Putnam3145 updated:

    +
      +
    • Your balls finally feel full, again.
    • +
    +

    timothyteakettle updated:

    +
      +
    • due to changes in policy, and several lawsuits, Nanotrasen has been forced to allow disabled people to sign up
    • +
    + +

    16 September 2020

    +

    timothyteakettle updated:

    +
      +
    • fixed an icon path
    • +
    + +

    12 September 2020

    +

    BlueWildrose updated:

    +
      +
    • The Polychromic winter coat's hoodie will now polychrome, alongside any other new polychromic items with toggleable headwear.
    • +
    • Minesweeper will no longer blow up the player's ears when they select "Play on the same board"
    • +
    • Slimepeople will find warm donk pockets among other toxin healing items even more repulsive, as they are anti-toxic.
    • +
    • Slimepeople are now neutral to gross foods.
    • +
    +

    DeltaFire15 updated:

    +
      +
    • AIs can no longer qdel() the gravity generator
    • +
    +

    Putnam3145 updated:

    +
      +
    • Added some unit tests for reactions.
    • +
    • replaced handle_changeling and handle_bloodsucker with signal registration
    • +
    +

    Sonic121x updated:

    +
      +
    • Fixed pill button on chemical press
    • +
    +

    TheObserver-sys updated:

    +
      +
    • Brass now has a proper datum. Aspiring Forgetenders rejoice!
    • +
    +

    Trilbyspaceclone updated:

    +
      +
    • Race based drinks will no longer stay inside your blood for ever.
    • +
    +

    Tupinambis updated:

    +
      +
    • Redid Cogstation atmos pipes to make it less cluttered.
    • +
    • Removed a few doors from the main hallway to mitigate chokepoint issues
    • +
    • All belt hell conveyers are now on by default, so that belt hell actually works.
    • +
    • IDs for poddoors and belts and the like. Everything is now properly hooked and should work as expected (except for the pressure triggered mass drivers)
    • +
    • addresses most if not all roundstart active turfs.
    • +
    • Issue where wires were connected to the SMES improperly, and SMES were not properly precharged, resulting in power failure earlier than intended.
    • +
    • various rogue turfs and wirings.
    • +
    • security office APC being hooked to maintenance for some reason.
    • +
    • TEG is now directly wired to the SMES.
    • +
    • adds a subtype of mass drivers that is triggered by things being on it. TODO: Make these mass drivers trigger poddoors, to make belt hell fully functional.
    • +
    +

    lolman360 updated:

    +
      +
    • glaives now work again
    • +
    +

    zeroisthebiggay updated:

    +
      +
    • Revolver is now poplocked down to fifteen people.
    • +
    + +

    11 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Superconducting turfs now can't go below 0 celsius.
    • +
    + +

    09 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Made superconductivity work for the first time literally ever.
    • +
    +

    timothyteakettle updated:

    +
      +
    • accents work better
    • +
    + +

    08 September 2020

    +

    Ghommie updated:

    +
      +
    • fixed names of the Electrical Toolbox goodie pack and green croptop christmas suit.
    • +
    • Fixed turf visuals for real. Original PR by AnturK on tgstation.
    • +
    +

    KeRSedChaplain updated:

    +
      +
    • added borg_deathsound.ogg and android_scream.ogg
    • +
    +

    silicons updated:

    +
      +
    • meteor waves now have a static 5 minute timer.
    • +
    + +

    07 September 2020

    +

    DeltaFire15 updated:

    +
      +
    • fixed a typo causing a span not to show.
    • +
    +

    Putnam for debugging ammo loading! Thx!! updated:

    +
      +
    • Removed spell blade, diamond picaxe, and fire wand from lava land loot tables
    • +
    • Each mini boss now has its own type of crate.
    • +
    • Each spike has its own type of crate that it pulls its now smaller loot table from
    • +
    • Moved god eye from spike loot table to hard spawn collosses fight
    • +
    • Moved holoparasight from spike loot table to bubble gum
    • +
    • Moved magic meat hook from spike loot table to drake
    • +
    • 2 more crates to Arena Shuttle as well as 4-4-4 of each new type of chest
    • +
    • Replaced the diamond pick loot with a better one
    • +
    • Replaced the cursted katana with a non cursted verson that deals half the damage and has less block!
    • +
    • Three new potions, blue heals the mind like a mama potion, Green heals the soul aka the organs! Lastly Red heals the body, by 100 damage of each main types. Best not to waste them!
    • +
    • Four more "wands" Spellbooks! These fun little guys shoot out its own pages to do the affect, one will set the target on fire like a bullet, one will harm them a bit, one will heal the target a small bit - How nice! Last one will give them a few statis affects like a taser bolt but without as much power or tasing affect
    • +
    + +

    06 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Dynamic no longer pushes events.
    • +
    • Made spontaneous brain trauma a good deal less annoying.
    • +
    +

    lolman360, NecromancerAnne updated:

    +
      +
    • The ancient art of blacksmithing, now in pixels.
    • +
    • cool swords and shit (thanks anne)
    • +
    +

    raspy-on-osu updated:

    +
      +
    • thermomachine examine text
    • +
    + +

    05 September 2020

    +

    Bhijn updated:

    +
      +
    • Readded the old method of temperature notifications in the form of a new pair of shivering/sweating notifications.
    • +
    +

    Putnam3145 updated:

    +
      +
    • Hilbert hotel flavor text for one particular snowflake hotel changed.
    • +
    • admins can now actually reduce threat level in dynamic
    • +
    • Made owo.ogg smaller.
    • +
    • Character saving unit test is now more verbose on failure.
    • +
    • Added an extools proc hook alternative to rust_g logging.
    • +
    +

    raspy-on-osu updated:

    +
      +
    • supermatter shard examine text
    • +
    • protolathe item categories
    • +
    + +

    04 September 2020

    +

    timothyteakettle updated:

    +
      +
    • ipcs can speak
    • +
    + +

    03 September 2020

    +

    Ghommie updated:

    +
      +
    • Jaunters should now work with magic mirror chasming.
    • +
    • The photocopier can now print more than one copy at a time.
    • +
    • Alkali perspiration infos don't crash the Pandemic UI anymore.
    • +
    • Windoors can be actually tinted now.
    • +
    + +

    02 September 2020

    +

    Putnam3145 updated:

    +
      +
    • Added a unit test for character saving.
    • +
    • Plastitanium rapier no longer silently sleeps with no chance at counterplay when used by pacifists.
    • +
    • Fusion scan is now actually useful.
    • +
    +

    Tupinambis updated:

    +
      +
    • moved the dakis, genital growth pills, and genital autosurgeons out of the maintenance loot table and into kinkmates.
    • +
    +

    raspy-on-osu updated:

    +
      +
    • pyroclastic anomaly client spam
    • +
    +

    timothyteakettle updated:

    +
      +
    • you can hide your ckey now from the roundend report
    • +
    + +

    01 September 2020

    +

    BlueWildrose updated:

    +
      +
    • fixed slimes starting off hungry
    • +
    + +

    31 August 2020

    +

    Arturlang updated:

    +
      +
    • Slimes can now damage structures, don't leave them unfed!
    • +
    +

    Chiirno updated:

    +
      +
    • Moves pill_bottles/dice to box/dice on CogStation.
    • +
    +

    Couls, ported by NecromancerAnne updated:

    +
      +
    • cleans up mech backstabbing code
    • +
    +

    DeltaFire15 updated:

    +
      +
    • teleport-to-ark ability of the eminence, commented out
    • +
    • teleport-to-obelisk ability for the eminence
    • +
    +

    Detective-Google updated:

    +
      +
    • plasmamen have no more slowdown
    • +
    • object reskins now use very nice and cool radials
    • +
    +

    EmeraldSundisk updated:

    +
      +
    • Adds a pool to MetaStation
    • +
    • Slight readjustments to the surrounding area
    • +
    • Fixes a handful of external airlocks
    • +
    +

    ForrestWick updated:

    +
      +
    • removes wall walking boots from nukie uplink
    • +
    +

    Ghommie updated:

    +
      +
    • e-gun overlays and some floor decals should have been fixed.
    • +
    +

    LetterN updated:

    +
      +
    • tgchat
    • +
    +

    Lynxless updated:

    +
      +
    • Changed anatomic panacea into a direct buff, instead of a chem injection
    • +
    • Changed the values of anatomic panacea
    • +
    • Added a new icon for panacea's buff alert
    • +
    +

    Putnam3145 updated:

    +
      +
    • Pref for genital/vore examine text
    • +
    • Fixed a couple events having ghost roles eligible.
    • +
    • Buffed slaughter demon: gets stronger as it eats people
    • +
    • Nerfed slaughter demon: no longer permanently round-removes all who are eaten by it, instead releasing their now-heartless bodies
    • +
    • Dynamic storytellers now calculate property weights properly.
    • +
    +

    Sonic121x updated:

    +
      +
    • Fix the four type of new tea that will stuck inside your vein.
    • +
    • drinking glass sprite for those tea.
    • +
    +

    kappa-sama updated:

    +
      +
    • miners can no longer acquire funny antag item
    • +
    +

    lolman360 updated:

    +
      +
    • shuttle engine/heater sprites now face the right way
    • +
    +

    raspy-on-osu updated:

    +
      +
    • TEG power output
    • +
    • tesla movement priorities
    • +
    • tesla counterplay
    • +
    • tesla containment check (containment variable now usable)
    • +
    +

    silicons updated:

    +
      +
    • brooms now sweep objects on MOVABLE_PRE_MOVE rather than MOVABLE_MOVED
    • +
    • firedoors no longer automatically open on touch when there's no pressure differences.
    • +
    +

    timothyteakettle updated:

    +
      +
    • buzz, buzz2 and ping are now all unrestricted emotes and can be used by anyone
    • +
    • the drake credit and pickle credit sprites have been removed
    • +
    • tongue speech handling is now done by accent datums
    • +
    +

    zeroisthebiggay updated:

    +
      +
    • waffleco
    • +
    + +

    30 August 2020

    +

    raspy-on-osu updated:

    +
      +
    • new explosion echoes
    • +
    • explosion echo range
    • +
    • 5 new explosion related sounds
    • +
    + +

    28 August 2020

    +

    EmeraldSundisk updated:

    +
      +
    • Adds more paper to the library
    • +
    • The law office now has a desk window
    • +
    • Expands most of CogStation's exterior airlocks. Slightly adjusts surrounding areas to accommodate this.
    • +
    • Updates some of CogStation's paperwork
    • +
    • The rat in the morgue turned themselves into a possum. Funniest shit I've ever seen.
    • +
    • Adjusts some area designations so cameras should receive power properly
    • +
    • Cleans up an errant decal
    • +
    +

    Hatterhat updated:

    +
      +
    • Traitor holoparasites can now only be bought once, because apparently you can only have one active holopara.
    • +
    • PDA bombs can now only be bought once per uplink.
    • +
    +

    lolman360 updated:

    +
      +
    • atmos = radiation = chemistry.
    • +
    +

    shellspeed1 updated: