Log 2: Damn thing is acting up again. Three days no contact this time. I thought I heard clanking noises from it yesterday. Jim is going on about the NT base or some shit. We've been over this before - They don't know we're here, that engineer was too drunk to recognise his suit, especially since I had it painted orange. He's starting to get annoying. We're safe.
Log 3: Gateway synced itself up automatically today. I opened it for an instant to spy through it, got a glimpse of the inside of a transport container. Either HQ's redecorating or something, or there's more than two of these things."; name = "Personal Log"},/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"br" = (/obj/machinery/door/window{dir = 1; name = "Gateway Access"; req_access_txt = "150"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bs" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/weapon/storage/firstaid/regular,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bt" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/machinery/recharger{pixel_y = 4},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bu" = (/obj/structure/sink{pixel_y = 28},/obj/machinery/light/small{dir = 8},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bv" = (/obj/machinery/door/airlock{name = "Unisex Restrooms"; req_access_txt = "0"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bw" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bx" = (/obj/structure/stool,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"by" = (/obj/structure/table,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = 32; pixel_y = 0},/obj/item/trash/plate,/obj/item/weapon/cigbutt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bz" = (/obj/machinery/light{dir = 8},/obj/structure/stool,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bA" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bB" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bC" = (/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bD" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bE" = (/obj/structure/toilet{dir = 1},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bF" = (/obj/structure/closet/crate/bin,/obj/item/trash/syndi_cakes,/obj/item/trash/sosjerky,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bG" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bH" = (/obj/structure/stool,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bI" = (/obj/structure/table,/obj/item/weapon/storage/box/donkpockets,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bJ" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bK" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bL" = (/obj/structure/closet/emcloset,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bM" = (/obj/structure/closet/l3closet/general,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bN" = (/obj/machinery/door/airlock/glass{name = "Break Room"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bO" = (/obj/structure/grille,/obj/structure/window/full/basic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bP" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/highsecurity{icon_state = "door_locked"; locked = 1; name = "Gateway"; req_access_txt = "150"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bQ" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/table,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/item/clothing/gloves/color/yellow,/obj/item/device/multitool,/turf/simulated/floor/plating{dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bR" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/computer3frame,/turf/simulated/floor/plating{dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (NORTHEAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bS" = (/obj/machinery/power/smes{charge = 0; input_level = 10000; inputting = 0; output_level = 15000; outputting = 1},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bT" = (/obj/machinery/portable_atmospherics/canister/air,/obj/machinery/alarm/monitor{frequency = 1439; locked = 1; pixel_y = 23; req_access = "150"},/turf/simulated/floor/plating{dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bU" = (/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating{dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (NORTHEAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bV" = (/obj/structure/alien/weeds/node,/mob/living/simple_animal/hostile/alien,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"bW" = (/obj/machinery/conveyor{dir = 2; id = "awaysyndie"},/obj/machinery/mineral/output,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bX" = (/obj/machinery/mineral/unloading_machine{dir = 1; icon_state = "unloader-corner"},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bY" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/sign/poster{icon_state = "poster5"; pixel_x = 0; pixel_y = 32; serial_number = 5},/obj/machinery/mineral/input,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "loadingarea"; nitrogen = 13.2; oxygen = 32.4; tag = "loading"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"bZ" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorgrime (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"ca" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cb" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cc" = (/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = "150"},/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cd" = (/obj/structure/sign/biohazard{pixel_y = 32},/obj/structure/alien/weeds/node,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warningcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"ce" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 1; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cf" = (/obj/structure/sign/securearea{pixel_x = 0; pixel_y = 32},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warningcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cg" = (/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"ch" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/table,/obj/machinery/cell_charger,/obj/machinery/light/small{dir = 8},/obj/item/weapon/stock_parts/cell/high,/obj/item/weapon/paper{info = "Alright, listen up. If you're reading this, I'm either taking a shit or I've been recalled back to Command. Either way, you'll need to know how to restore power. We've stolen this stuff from Nanotrasen, so all the equipment is jury-rigged. We have generators that work on both plasma and uranium, about 50 sheets should power the outpost for quite a while. If the generators aren't working, which is very likely, take the power cell on the desk and put it into the APC in the hallway. That should get the place running, at least for a little while."; name = "Engineering Instructions"},/turf/simulated/floor/plating{dir = 8; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"ci" = (/obj/structure/stool,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cj" = (/obj/machinery/power/terminal{icon_state = "term"; dir = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{dir = 1; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"ck" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{dir = 4; heat_capacity = 1e+006; icon_state = "warnplatecorner"; tag = "icon-warnplatecorner (EAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cl" = (/obj/machinery/light/small{dir = 4},/obj/structure/sign/poster{icon_state = "poster10"; pixel_x = 32; pixel_y = 0; serial_number = 10},/turf/simulated/floor/plating{dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cm" = (/obj/machinery/conveyor{dir = 2; id = "awaysyndie"},/obj/machinery/mineral/input,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bi" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/clothing/under/syndicate,/obj/item/clothing/glasses/night,/obj/effect/decal/cleanable/blood{color = "red"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"bj" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood/gibs{color = "red"; icon_state = "gib2_flesh"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"bk" = (/obj/structure/alien/weeds,/mob/living/simple_animal/hostile/alien/sentinel,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"bl" = (/turf/simulated/mineral/random/high_chance,/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"bm" = (/obj/machinery/light/small{dir = 8},/obj/structure/sign/poster{icon_state = "poster17"; pixel_x = -32; pixel_y = 0; serial_number = 17; subtype = 0},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bn" = (/obj/item/weapon/cigbutt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bo" = (/obj/machinery/alarm{frequency = 1439; locked = 1; pixel_y = 23; req_access = "150"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bp" = (/obj/structure/table,/obj/machinery/microwave{pixel_x = -3; pixel_y = 6},/obj/machinery/light/small{dir = 4},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bq" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/device/radio/off{pixel_x = -4; pixel_y = 4},/obj/item/device/radio/off{pixel_x = 2},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"br" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/obj/item/weapon/paper{info = "Log 1: We got our promised supply drop today. We were only meant to get it, what, a week ago? This bloody gateway keeps desyncing itself, and that means subsisting off recycled water and carb packs. No clue where the damn thing connects to on its off days, and HQ say we are 'not to touch it if it isn't linking to command.' We dumped off the assload of crates Jim filled, got our boxes of oxygen, food and drink, and closed the portal.
Log 2: Damn thing is acting up again. Three days no contact this time. I thought I heard clanking noises from it yesterday. Jim is going on about the NT base or some shit. We've been over this before - They don't know we're here, that engineer was too drunk to recognise his suit, especially since I had it painted orange. He's starting to get annoying. We're safe.
Log 3: Gateway synced itself up automatically today. I opened it for an instant to spy through it, got a glimpse of the inside of a transport container. Either HQ's redecorating or something, or there's more than two of these things."; name = "Personal Log"},/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bs" = (/obj/machinery/door/window{dir = 1; name = "Gateway Access"; req_access_txt = "150"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bt" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/item/weapon/storage/firstaid/regular,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bu" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/table,/obj/machinery/recharger{pixel_y = 4},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bv" = (/obj/structure/sink{pixel_y = 28},/obj/machinery/light/small{dir = 8},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bw" = (/obj/machinery/door/airlock{name = "Unisex Restrooms"; req_access_txt = "0"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bx" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"by" = (/obj/structure/stool,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bz" = (/obj/structure/table,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = 32; pixel_y = 0},/obj/item/trash/plate,/obj/item/weapon/cigbutt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bA" = (/obj/machinery/light{dir = 8},/obj/structure/stool,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bB" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bC" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bD" = (/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bE" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/obj/machinery/alarm{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bF" = (/obj/structure/toilet{dir = 1},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bG" = (/obj/structure/closet/crate/bin,/obj/item/trash/syndi_cakes,/obj/item/trash/sosjerky,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bH" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bI" = (/obj/structure/stool,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bJ" = (/obj/structure/table,/obj/item/weapon/storage/box/donkpockets,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "bar"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bK" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bL" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bM" = (/obj/structure/closet/emcloset,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bN" = (/obj/structure/closet/l3closet/general,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bO" = (/obj/machinery/door/airlock/glass{name = "Break Room"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bP" = (/obj/structure/grille,/obj/structure/window/full/basic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bQ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/highsecurity{icon_state = "door_locked"; locked = 1; name = "Gateway"; req_access_txt = "150"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bR" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/table,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/item/clothing/gloves/color/yellow,/obj/item/device/multitool,/turf/simulated/floor/plating{dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bS" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/computer/monitor,/turf/simulated/floor/plating{dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (NORTHEAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bT" = (/obj/machinery/power/smes{charge = 0; input_level = 10000; inputting = 0; output_level = 15000; outputting = 1},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bU" = (/obj/machinery/portable_atmospherics/canister/air,/obj/machinery/alarm{frequency = 1439; locked = 1; pixel_y = 23; req_access = "150"},/turf/simulated/floor/plating{dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bV" = (/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating{dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (NORTHEAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bW" = (/obj/structure/alien/weeds/node,/mob/living/simple_animal/hostile/alien,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"bX" = (/obj/machinery/conveyor{dir = 2; id = "awaysyndie"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bY" = (/obj/machinery/mineral/unloading_machine{dir = 1; icon_state = "unloader-corner"; input_dir = 4; output_dir = 8},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"bZ" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/sign/poster{icon_state = "poster5"; pixel_x = 0; pixel_y = 32; serial_number = 5; subtype = 0},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "loadingarea"; nitrogen = 13.2; oxygen = 32.4; tag = "loading"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"ca" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorgrime (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cb" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cc" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cd" = (/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = "150"},/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"ce" = (/obj/structure/sign/biohazard{pixel_y = 32},/obj/structure/alien/weeds/node,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warningcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cf" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 1; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cg" = (/obj/structure/sign/securearea{pixel_x = 0; pixel_y = 32},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warningcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"ch" = (/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"ci" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/table,/obj/machinery/cell_charger,/obj/machinery/light/small{dir = 8},/obj/item/weapon/stock_parts/cell/high,/obj/item/weapon/paper{info = "Alright, listen up. If you're reading this, I'm either taking a shit or I've been recalled back to Command. Either way, you'll need to know how to restore power. We've stolen this stuff from Nanotrasen, so all the equipment is jury-rigged. We have generators that work on both plasma and uranium, about 50 sheets should power the outpost for quite a while. If the generators aren't working, which is very likely, take the power cell on the desk and put it into the APC in the hallway. That should get the place running, at least for a little while."; name = "Engineering Instructions"},/turf/simulated/floor/plating{dir = 8; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cj" = (/obj/structure/stool,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"ck" = (/obj/machinery/power/terminal{icon_state = "term"; dir = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{dir = 1; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cl" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{dir = 4; heat_capacity = 1e+006; icon_state = "warnplatecorner"; tag = "icon-warnplatecorner (EAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cm" = (/obj/machinery/light/small{dir = 4},/obj/structure/sign/poster{icon_state = "poster10"; pixel_x = 32; pixel_y = 0; serial_number = 10; subtype = 0},/turf/simulated/floor/plating{dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cn" = (/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"co" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cp" = (/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
@@ -130,7 +130,7 @@
"cz" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cA" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/plating{burnt = 1; heat_capacity = 1e+006; icon_state = "panelscorched"; tag = "icon-panelscorched"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cB" = (/obj/machinery/space_heater,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cC" = (/obj/machinery/mineral/processing_unit{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cC" = (/obj/machinery/mineral/processing_unit{dir = 1; output_dir = 2},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cD" = (/obj/machinery/mineral/processing_unit_console{machinedir = 8},/turf/simulated/wall,/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cE" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cF" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
@@ -138,7 +138,7 @@
"cH" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 10; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cI" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cJ" = (/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cK" = (/obj/structure/cable,/obj/machinery/power/apc/noalarm{cell_type = 15000; dir = 2; locked = 1; name = "Worn-out APC"; pixel_x = 0; pixel_y = -25; req_access = "150"; start_charge = 0},/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cK" = (/obj/structure/cable,/obj/machinery/power/apc{cell_type = 15000; dir = 2; locked = 1; name = "Worn-out APC"; pixel_x = 0; pixel_y = -25; req_access = "150"; start_charge = 0},/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cL" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 6; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cM" = (/obj/item/weapon/storage/box/lights/mixed,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{dir = 10; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (SOUTHWEST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cN" = (/obj/structure/cable,/obj/machinery/power/port_gen/pacman{desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator"},/turf/simulated/floor/plating{dir = 2; heat_capacity = 1e+006; icon_state = "warnplate"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
@@ -146,7 +146,7 @@
"cP" = (/obj/machinery/portable_atmospherics/scrubber,/turf/simulated/floor/plating{dir = 6; heat_capacity = 1e+006; icon_state = "warnplate"; tag = "icon-warnplate (SOUTHEAST)"},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cQ" = (/obj/machinery/conveyor_switch/oneway{id = "awaysyndie"; layer = 3.1; name = "mining conveyor"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cR" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged4"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged4 (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"cS" = (/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"cS" = (/obj/machinery/alarm{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "red"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cT" = (/obj/machinery/door/airlock{density = 0; emagged = 1; icon_state = "door_open"; id_tag = "awaydorm4"; locked = 1; name = "Dorm 1"; opacity = 0},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cU" = (/obj/machinery/door/airlock{id_tag = "awaydorm5"; name = "Dorm 2"},/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"cV" = (/obj/structure/alien/weeds/node,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
@@ -157,57 +157,57 @@
"da" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"db" = (/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dc" = (/obj/machinery/door_control{id = "awaydorm5"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 0; pixel_y = 25; req_access_txt = "0"; specialfunctions = 4},/obj/structure/dresser,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dd" = (/obj/structure/alien/weeds/node,/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"de" = (/obj/machinery/mineral/stacking_machine{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dd" = (/obj/structure/alien/weeds/node,/mob/living/simple_animal/hostile/alien/drone{plants_off = 1},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"de" = (/obj/machinery/mineral/stacking_machine{dir = 1; input_dir = 1; output_dir = 2},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"df" = (/obj/machinery/mineral/stacking_unit_console{machinedir = 8},/turf/simulated/wall,/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dg" = (/obj/structure/closet/crate,/obj/item/stack/sheet/glass{amount = 10},/obj/structure/alien/weeds,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 1; heat_capacity = 1e+006; icon_state = "bot"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dh" = (/obj/structure/stool/bed/chair/wood/normal,/obj/machinery/alarm/monitor{dir = 4; frequency = 1439; locked = 1; pixel_x = -23; pixel_y = 0; req_access = "150"},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dh" = (/obj/structure/stool/bed/chair/wood/normal,/obj/machinery/alarm{dir = 4; frequency = 1439; locked = 1; pixel_x = -23; pixel_y = 0; req_access = "150"},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"di" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dj" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dk" = (/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dl" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/machinery/mineral/output,/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "loadingarea"; nitrogen = 13.2; oxygen = 32.4; tag = "loading"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dk" = (/obj/machinery/alarm{dir = 8; frequency = 1439; locked = 1; pixel_x = 23; pixel_y = 0; req_access = "150"},/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dl" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "loadingarea"; nitrogen = 13.2; oxygen = 32.4; tag = "loading"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dm" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 1; heat_capacity = 1e+006; icon_state = "warning"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dn" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "warningcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"do" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged1 (WEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dp" = (/obj/structure/closet/crate,/obj/item/weapon/storage/bag/ore,/obj/structure/alien/weeds,/obj/item/device/mining_scanner,/obj/item/weapon/shovel,/obj/item/weapon/pickaxe,/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg3"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg3"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dq" = (/obj/structure/table/woodentable,/obj/structure/sign/poster{icon_state = "poster24"; pixel_x = 0; pixel_y = -32; serial_number = 24},/obj/item/weapon/pen,/obj/item/weapon/paper{info = "Log 1: While mining today I noticed the NT station was finished with its renovations. They placed some huge reinforced tumor on the station, looks so ugly. I wouldn't be surprised if those pigs decided to turn that little astronomy outpost into a prison with that thing, it'd be pretty typical of them.
Log 2: Really dumb of me but I just waved at an engineer in the outpost, and he waved back. I hope to god he was too dumb or drunk to recognize the suit, because if he isn't then we might have to pull out before they come looking for us.
Log 3: That huge reinforced tumor in their science section has been making a lot of noise lately. I've been hearing some banging and scratching from the other side and I'm kind of glad now that they reinforced this thing so much. I'll be sleeping with my gun under my pillow from now on."; name = "Personal Log"},/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dq" = (/obj/structure/table/woodentable,/obj/structure/sign/poster{icon_state = "poster24"; pixel_x = 0; pixel_y = -32; serial_number = 24; subtype = 0},/obj/item/weapon/pen,/obj/item/weapon/paper{info = "Log 1: While mining today I noticed the NT station was finished with its renovations. They placed some huge reinforced tumor on the station, looks so ugly. I wouldn't be surprised if those pigs decided to turn that little astronomy outpost into a prison with that thing, it'd be pretty typical of them.
Log 2: Really dumb of me but I just waved at an engineer in the outpost, and he waved back. I hope to god he was too dumb or drunk to recognize the suit, because if he isn't then we might have to pull out before they come looking for us.
Log 3: That huge reinforced tumor in their science section has been making a lot of noise lately. I've been hearing some banging and scratching from the other side and I'm kind of glad now that they reinforced this thing so much. I'll be sleeping with my gun under my pillow from now on."; name = "Personal Log"},/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dr" = (/obj/structure/closet/secure_closet{desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_broken = "cabinetdetective_broken"; icon_closed = "cabinetdetective"; icon_locked = "cabinetdetective_locked"; icon_off = "cabinetdetective_broken"; icon_opened = "cabinetdetective_open"; icon_state = "cabinetdetective_locked"; locked = 1; name = "personal closet"; req_access_txt = "150"},/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/weapon/suppressor,/turf/simulated/floor/wood{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"ds" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/syndie,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dt" = (/obj/structure/closet/secure_closet{desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_broken = "cabinetdetective_broken"; icon_closed = "cabinetdetective"; icon_locked = "cabinetdetective_locked"; icon_off = "cabinetdetective_broken"; icon_opened = "cabinetdetective_open"; icon_state = "cabinetdetective"; locked = 0; name = "personal closet"; req_access_txt = "150"},/obj/item/weapon/spacecash/c50,/turf/simulated/floor/wood{heat_capacity = 1e+006},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"du" = (/obj/machinery/door/airlock/external{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; opacity = 0; req_access_txt = "150"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dv" = (/obj/item/weapon/ore/iron,/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dv" = (/obj/item/weapon/ore/iron,/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
"dw" = (/obj/structure/dispenser/oxygen{oxygentanks = 9},/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 9; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dx" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dy" = (/obj/structure/rack,/obj/item/clothing/suit/space/syndicate/orange,/obj/item/clothing/mask/gas,/obj/item/weapon/pickaxe/drill,/obj/item/clothing/head/helmet/space/syndicate/orange,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 5; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (NORTHEAST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dz" = (/obj/item/weapon/ore/iron{pixel_x = -3; pixel_y = 9},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dA" = (/turf/simulated/mineral,/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dz" = (/obj/item/weapon/ore/iron{pixel_x = -3; pixel_y = 9},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dA" = (/turf/simulated/mineral,/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
"dB" = (/obj/structure/sign/vacuum{desc = "A warning sign which reads 'HOSTILE ATMOSPHERE AHEAD'"; name = "\improper HOSTILE ATMOSPHERE AHEAD"; pixel_x = 0; pixel_y = -32},/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 10; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (SOUTHWEST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dC" = (/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg1"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
"dD" = (/obj/structure/rack,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{carbon_dioxide = 48.7; dir = 6; heat_capacity = 1e+006; icon_state = "warnplate"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-warnplate (SOUTHEAST)"; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dE" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dF" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_2"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dG" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/obj/item/device/mining_scanner,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dH" = (/obj/item/device/flashlight/lantern{icon_state = "lantern-on"; on = 1},/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dI" = (/obj/machinery/door/airlock/external{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; opacity = 0; req_access_txt = "150"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dJ" = (/obj/item/weapon/storage/bag/ore,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dK" = (/obj/item/weapon/pickaxe/drill,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dL" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
-"dM" = (/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dN" = (/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dO" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/weapon/tank/oxygen,/obj/item/clothing/suit/space/syndicate/orange,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/syndicate/orange,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dP" = (/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dQ" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dR" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dS" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/mob/living/simple_animal/hostile/alien/drone,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dT" = (/obj/structure/alien/weeds,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dU" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dV" = (/obj/structure/alien/weeds/node,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dW" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"dX" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dE" = (/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dF" = (/obj/item/device/mining_scanner,/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 6; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dG" = (/obj/item/device/flashlight/lantern{icon_state = "lantern-on"; on = 1},/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dH" = (/obj/machinery/door/airlock/external{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; opacity = 0; req_access_txt = "150"},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dI" = (/obj/item/weapon/storage/bag/ore,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dJ" = (/obj/item/weapon/pickaxe/drill,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dK" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a4{has_gravity = 1; name = "Syndicate Outpost"})
+"dL" = (/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dM" = (/obj/item/weapon/ore/iron{pixel_x = -7; pixel_y = -4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dN" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/item/weapon/tank/oxygen,/obj/item/clothing/suit/space/syndicate/orange,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/syndicate/orange,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dO" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dP" = (/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dQ" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dR" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dS" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood{color = "red"},/mob/living/simple_animal/hostile/alien/drone{plants_off = 1},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a5{always_unpowered = 1; has_gravity = 1; name = "The Hive"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dT" = (/obj/structure/alien/weeds,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dU" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dV" = (/obj/structure/alien/weeds/node,/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dW" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"dX" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; ambientsounds = list('sound/ambience/ambimine.ogg'); has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
"dY" = (/obj/machinery/light/small,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"dZ" = (/turf/simulated/wall/r_wall/rust,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ea" = (/turf/simulated/wall/r_wall,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eb" = (/obj/structure/grille,/obj/machinery/door/poddoor{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaybiohazard"; layer = 2.9; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eb" = (/obj/structure/grille,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaybiohazard"; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/machinery/door/poddoor{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaybiohazard"; layer = 2.9; name = "Acid-Proof biohazard containment door"; unacidable = 1},/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ec" = (/obj/structure/sign/biohazard,/turf/simulated/wall/r_wall,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ed" = (/obj/machinery/vending/snack,/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ee" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
@@ -217,572 +217,521 @@
"ei" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible{dir = 10},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ej" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ek" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/shieldwallgen{locked = 0; req_access = null},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"el" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"em" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"el" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 9; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"em" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"en" = (/obj/structure/alien/weeds,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"eo" = (/obj/machinery/light{active_power_usage = 0; dir = 1; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/obj/machinery/camera{c_tag = "Xenobiology Containment North"; network = list("MO19X")},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ep" = (/obj/machinery/sparker{desc = "A wall-mounted ignition device. This one has been applied with an acid-proof coating."; id = "awayxenobio"; name = "Acid-Proof mounted igniter"; pixel_x = 0; pixel_y = 25; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"eq" = (/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"er" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"es" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"er" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"es" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"et" = (/obj/machinery/vending/coffee,/turf/simulated/floor{icon_state = "dark"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"eu" = (/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ev" = (/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ew" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ex" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/manifold/visible{color = "cyan"; dir = 4; initialize_directions = 11; level = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ex" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/manifold/visible{dir = 4; initialize_directions = 11; level = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ey" = (/obj/structure/table/reinforced,/obj/structure/alien/weeds,/obj/machinery/computer/security/telescreen{desc = "Used for watching the contents of the xenobiology containment pen."; dir = 8; name = "xenobiology monitor"; network = list("MO19X")},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"ez" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
"eA" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"},/turf/simulated/wall/r_wall,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eB" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eC" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eD" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eE" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eF" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eG" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eH" = (/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eI" = (/turf/simulated/wall,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eJ" = (/turf/simulated/wall/rust,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eK" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eL" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eM" = (/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/obj/machinery/camera{c_tag = "Xenobiology"; dir = 4; network = list("MO19","MO19R")},/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eN" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible,/obj/structure/stool/bed/chair/office/light{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eO" = (/obj/structure/table/reinforced,/obj/machinery/door_control{id = "Awaylab"; name = "Containment Chamber Blast Doors"; pixel_x = 4; pixel_y = -2; req_access_txt = "201"},/obj/machinery/ignition_switch{id = "awayxenobio"; pixel_x = 4; pixel_y = 8},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eP" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eQ" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eR" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eS" = (/obj/machinery/power/port_gen/pacman{desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eT" = (/obj/machinery/power/port_gen/pacman/super{desc = "A portable generator for emergency backup power."; name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg2"; tag = "icon-platingdmg2"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eU" = (/obj/machinery/space_heater,/obj/machinery/light/small{dir = 1},/obj/structure/sign/poster{icon_state = "poster5_legit"; pixel_x = 0; pixel_y = 32; serial_number = 21},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eV" = (/obj/machinery/power/terminal{dir = 4},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eW" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/power/smes{charge = 1.5e+006; input_level = 10000; inputting = 0; output_level = 15000; outputting = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eX" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eY" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/item/weapon/newspaper,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"eZ" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fa" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fb" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fc" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "201"; req_one_access_txt = "0"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fd" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 5; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fe" = (/obj/structure/sign/securearea{pixel_x = 32},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ff" = (/obj/structure/table,/obj/machinery/reagentgrinder,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fg" = (/obj/structure/table,/obj/item/stack/sheet/mineral/plasma{layer = 2.9},/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fh" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/table,/obj/item/weapon/storage/box/beakers{pixel_x = 2; pixel_y = 2},/obj/item/weapon/storage/box/syringes,/obj/structure/alien/weeds,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fi" = (/obj/structure/closet/crate/freezer,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/xenos_claw,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fj" = (/obj/machinery/door/firedoor,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fk" = (/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fl" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fm" = (/obj/structure/closet/l3closet/scientist,/obj/structure/window/reinforced,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fn" = (/obj/structure/cable,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fo" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fp" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fq" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fr" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/generic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fs" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ft" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fv" = (/obj/structure/extinguisher_cabinet{pixel_x = -26},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_2"},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fw" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fx" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/research{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Xenobiology Lab"; opacity = 0; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fy" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fz" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fA" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/alien/weeds/node,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fC" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible{dir = 5},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fD" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fE" = (/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "medium"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fF" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fG" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fH" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fI" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fJ" = (/obj/machinery/atmospherics/unary/outlet_injector{desc = "Has a valve and pump attached to it. This one has been applied with an acid-proof coating."; dir = 8; icon_state = "on"; name = "Acid-Proof Air Injector"; on = 1; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fK" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/machinery/camera{c_tag = "Xenobiology Containment East"; dir = 8; network = list("MO19X")},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fL" = (/obj/machinery/portable_atmospherics/scrubber,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fM" = (/obj/item/weapon/cigbutt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fN" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fO" = (/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fP" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fQ" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "0"; req_one_access_txt = "0"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fR" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/effect/decal/cleanable/blood/oil,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fS" = (/obj/structure/filingcabinet,/obj/item/weapon/paper{info = "Entry One - 27/05/2554: I just arrived, and already I hate my job. I'm stuck on this shithole of an outpost, trying to avoid these damn eggheads running all over the place preparing for god knows what. There's no crimes to stop, no syndies to kill, and I'm not even allowed to beat the fuckin' assistant senseless! They said I was transferred from Space Station 13 for 'good behavior', but this feels more like a punishment than a reward. All I know is that if I don't get some action soon, I'm going to go insane.
Entry Two - 03/06/2554: Okay, so get this: we got a fuckin' deathsquad coming in today! I thought the day I saw one of them would be the day my employment was 'terminated', if you get my drift. They're escorting some sort of weird alien creature for the eggheads to study. I heard one of the docs telling the chef that this thing killed a whole security force before it was captured. I sure as hell hope that I don't have to fight it.
Entry Three - 08/06/2554: My first real bit of 'action' today, if you could call it that. Crazy Ivan got in a fight with Kuester today about his Booze-O-Mat. Apparently one of the crewmembers had stolen a couple bottles of booze from the machine after Ivan disabled the ID lock. Tell you the truth, I don't blame the thief. Everyone is going a little stir-crazy in here, and the bartender is being damn stingy with the alcohol. Either way, once they started to pick a fight, I had to take them down. It's a damn shame that we don't have a brig, though. I had to lock Ivan in a fuckin' freezer, for god's sake. Let's hope that we can keep our sanity together, at least for a while.
Entry Four - 10/06/2554: Jesus fucking Christ riding on a motorbike. These things the scientists are studying are terrifying! Fucking great huge purple bug things as tall as the ceiling, with blades for arms and drooling at the mouth. I don't think my taser will do jack shit against these damn things, but the eggheads say that they're safely contained. If they do, I have a feeling that it's only a matter of time before we're all screwed. These bastards look like walking death.
Entry Five - 18/06/2554: Finally caught who stole the booze from Kuester. It was that fuckin' loser assistant Steve! He was in the dorms, chugging his worries away. I took one of the bottles back to the barkeep, but no one has to know about this second one. I think I'm gonna enjoy this while watching tomorrow's Thunderdome match.
Entry Six - 19/06/2554: Oh, great. The chef is still sleeping, so we get Ivan's gruel for breakfast today. I overheard Sano and Douglas saying something about the aliens being restless, so we might get some action today. As long as it happens after the big game, I'm fine with it. I still got one beer to drink before I'm ready to die."; name = "Personal Log - Kenneth Cunningham"},/turf/simulated/floor{dir = 9; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fT" = (/obj/structure/closet/secure_closet{icon_broken = "secbroken"; icon_closed = "sec"; icon_locked = "sec1"; icon_off = "secoff"; icon_opened = "secopen"; icon_state = "sec1"; locked = 1; name = "security officer's locker"; req_access_txt = "201"},/obj/item/clothing/suit/armor/vest,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/grenade/flashbang,/obj/item/weapon/storage/belt/security,/obj/item/weapon/reagent_containers/food/drinks/cans/beer{pixel_x = -3; pixel_y = -2},/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fU" = (/obj/structure/sign/poster{icon_state = "poster21_legit"; pixel_y = 32; serial_number = 21},/obj/item/device/radio/off,/obj/item/weapon/screwdriver{pixel_y = 10},/turf/simulated/floor{dir = 5; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fV" = (/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fW" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fX" = (/obj/structure/sign/biohazard{pixel_x = 32},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fY" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"fZ" = (/obj/machinery/door/firedoor,/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -29},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ga" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/closet/l3closet/scientist,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gb" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/item/stack/cable_coil/cut{amount = 1; icon_state = "coil_red1"; item_state = "coil_red1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gc" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood,/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gd" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/gibs,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ge" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gf" = (/obj/structure/stool,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gg" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gh" = (/obj/effect/decal/cleanable/blood/oil,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gi" = (/obj/structure/reagent_dispensers/peppertank{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gj" = (/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gk" = (/obj/machinery/door/airlock/glass_security{name = "Security Post"; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gl" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gm" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gn" = (/obj/structure/table,/obj/item/weapon/scalpel{pixel_y = 12},/obj/item/weapon/circular_saw,/obj/item/weapon/razor{pixel_y = 5},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"go" = (/obj/structure/alien/weeds/node,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gp" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gq" = (/obj/structure/table,/obj/item/device/mmi,/obj/item/device/mmi,/obj/item/device/mmi,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gr" = (/obj/structure/sink{dir = 8; icon_state = "sink"; pixel_x = -12; pixel_y = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gs" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gt" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gu" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gv" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 2; icon_state = "pipe-c"; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gw" = (/obj/structure/table,/obj/effect/decal/cleanable/dirt,/obj/machinery/cell_charger,/obj/item/weapon/stock_parts/cell/high,/obj/item/device/radio/off,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gx" = (/obj/structure/table,/obj/item/weapon/paper{info = "Ivan Volodin Stories:
Entry Won - 28/05/2554: Hello. I am Crazy Ivan. Boss say I must write. I do good job fixing outpost. Is very good job. Much better than mines. Many nice people. I cause no trouble.
Entry Too - 05/06/2554: I am finding problem with Booze-O-Mat. Is not problem. I solve very easy. Use yellow tool to make purple light go off. I am good engineer! Bartender will be very happy.
Entry Tree - 08/06/2554: Bartender is not happy. Security man is not happy. Cannot feel legs, is very cold in freezer. Is not good. Table is jammed into door, have no tools. Is very not good. But, on bright side, found meat! Shall chew to keep spirits up.
Entry Fore - 12/06/2554: Big nasty purple bug looked at me today. Make nervous. Blue wall wire can be broken, then bad thing happens. Very very bad thing. Man in orange spacesuit wave at me today too. He seem nice. Wonder who was?
Entry Fiv - 15/06/2554: I eat cornflakes today. Is good day. Sun shine for a while. Was nice. I also take ride on disposals chute. Was fun, but tiny. Get clog out of pipes, was vodka bottle. Is empty. This make many sads.
Entry Sex: 19/06/2554: Purple bugs jumpy today. When waved, get hiss. Maybe very bad. Maybe just ill. Do not know. Is science problem, is not engineer problem. I eat sandwich. Is glorious job. Wish to never end."; name = "Personal Log - Ivan Volodin"},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gy" = (/obj/machinery/light/small,/obj/structure/closet/toolcloset,/obj/item/clothing/gloves/color/yellow,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gz" = (/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gA" = (/obj/structure/cable,/obj/structure/computer3frame,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gB" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/newscaster/security_unit{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gC" = (/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gD" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gE" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gF" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 6; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gG" = (/obj/structure/cable,/obj/machinery/power/apc/noalarm{cell_type = 15000; dir = 4; locked = 0; name = "Worn-out APC"; pixel_x = 25; req_access = null; start_charge = 100},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gH" = (/obj/structure/table,/obj/item/weapon/retractor,/obj/item/weapon/hemostat,/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gI" = (/obj/structure/table,/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gJ" = (/obj/structure/filingcabinet/filingcabinet,/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: As expected, all that is left of the monkeys we sent in earlier is a group of xenomorph larvae. It is quite clear that the facehuggers are not selective in their hosts, and so far the gestation process has been shown to have a 100% success rate.
The larvae themselves have been behaving very differently from the lone larva we first observed, and despite shying away from humans they are clearly comfortable with others of their kind. Our previous suspicions on larvae have been confirmed with their demonstration of playfulness: they are not nearly as aggressive or violent when young, before molting to adulthood.
The majority of the play we observed involved a sort of hide-and-seek, and occasionally wrestling by tangling themselves and struggling out of it. While normally we would write these off as instinctual play for honing their skills when they molt, their growth period is so incredibly fast and they are still such adept killers that it would serve no practical purpose. The only explanation for this is perhaps to create bonds and friendships with each other, if that is even possible for such an incredibly hostile race. It may be that they are much more reasonable with each other than other life forms.
It had become clear that now was the best time to extract a xenomorph for dissecting, as these were all still larvae and the queen was still attached to its ovipositor and would be immobile. With the approval of the research director, we sent in our medical robot that had been dubbed 'Head Surgeon' into the containment pen, dropping the shields for only a fraction of a second to allow it entry. The larvae were cautious, but the curiosity of one had him within grabbing range of our robot. It was brought out and quickly euthanized through lethal injection, courtesy of our mechanical doctor."; name = "Larva Xenomorph Social Interactions & Capturing Procedure"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: I have studied many interesting and diverse life-forms as a xenobiologist ranging from creatures as large as cows, to specimens too small see with the naked eye. This is by far the largest alien I have ever seen. The alien we were previously studying has molted and has become an absolutely enormous creature. Standing at over 15 feet tall and weighing in at likely two tons or more, the xenomorph queen is an absolutely breathtakingly large and cruel monster. Its behavior has changed drastically from when it was a drone, having become far more comfortable with sitting and staring at us, rather than smashing at the windows.
The queen, physiologically speaking, is fairly similar to the other xenomorphs, with a few key differences. Its enormous size demands large legs, while the back seems to be always hunched forward. The dorsal tubes on the back have changed to several large spikes, and we observed the alien now sports a second pair of smaller arms on its chest. The purpose of these secondary arms is still unknown. Finally, the queen's crown has become incredibly large, with what seems to be a retractable slot to hide its head in. The dome appears to be extremely thick near the front, and will likely be able to resist a lot of trauma. Despite the enormous size it has grown to, it is not that much slower than it used to be.
After two hours of doing relatively nothing but staring, the queen began to produce an unusually large amount of resin and weeds, quickly shaping up a large nest that it then hid behind. It then proceeded to smash out all the lights, leaving us with very little to see with our cameras. When we looked through the back cameras, we had discovered that it had grown a large ovipositor, and was releasing large eggs onto the ground. This had us all in agreement that this stage of the life cycle was the queen.
Over the next few hours, the eggs grew to their full sizes, and we provided the subject with new monkey hosts. When they approached the eggs, they opened to release more facehuggers. It seems that we have observed the full cycle of reproduction for this species. We can expect more larvae in the next few hours."; name = "Queen Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The other scientists and I can hardly believe our eyes. The snake-like larva has molted into a 7 foot tall insectoid nightmare in just a few hours. It's obvious now as to why such heavy duty containment was needed. It immediately tried to escape however by flinging itself at the window in a flurry of swipes and stabs. It seems its behavior has returned to a state that is very similar to the facehugger, though I doubt with the same intent! Thankfully, our glass and shields have shown to be more than sturdy enough for such a violent creature, and so far, any attempts at the creature escaping have been in vain.
As for its physiology, the creature has an elongated head with what appears to be have an exoskeleton resembling an external rib-cage on the torso. The alien is also fairly skinny with a lean body. The little amount of meat on the alien appears to be entirely muscle. We assume this makes it deceptively strong, while remaining agile at the same time. One of the most interesting things we have seen is its pharyngeal jaw. It has some what of an inner mouth capable of being fired externally at extremely high speeds. It has already caused many dents in the walls and a few small cracks in the window with it. The alien also has a couple of dorsal tubes on its back, their purpose unknown. Finally, this monster sports a long ridged tail, complete with a large and extremely sharp blade at the tip.
Normally I would be absolutely terrified of something like this, but I'm putting my trust in Nanotrasen with the containment. After all, they wouldn't build a cell that could fail to contain its subject, would they?"; name = "Adult Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: When the larva first emerged from the chest of the monkey, it seemed very curious. It would wander around aimlessly for awhile and then sit still. We are unable to determine the gender of the larva, or even determine if it has a gender. After some time had passed, it seemed to lose interest in its surroundings and sat mostly still while occasionally wagging its tail. We decided to throw in a live mouse to see if it would consume it. The larva quickly attacked and ate the mouse and seemed to get larger very suddenly, this suggests that the larvae are capable of metabolizing and directing all the energy towards growth at previously thought impossible speeds. It is a shame that we cannot observe the process more closely, as we do not currently know how dangerous or violent this creature is or will become as it matures fully.
It is tempting to imagine the possibilities of utilizing such a mechanism. The capability of skipping years of growth time for children, repairing bodily damage in a matter of moments, even its usage in existing cloning technology."; name = "Larva Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The test subject we were provided with truly is alien. It is a small spider-like creature with bony legs leading to a smooth body. It has a long tail connected to it, and it has shown extremely aggressive behavior by flinging its entire body at the glass and shields to no avail. While doing so, we noticed there was a small pink hole in the middle of the body.
When we sent in a monkey through the crude but effective disposal tube, the alien immediately jumped at its face and latched on. The monkey was quickly suffocated by its constricting tail, unable to pry off the fingers. The monkey at first seemed to be dead, but was observed to be breathing. The recently named alien 'facehugger' fell off dead and curled its legs up like a spider moments after it had finished with the monkey's body.
While the monkey appeared to be unharmed, we kept it in the cell for a couple more hours until we were horrified to discover it screaming out in pain as a snake-like creature erupted from the monkey's chest! It appears that the 'facehugger' is only the start of this life cycle. The impregnation cycle involving the creatures growing inside the chests of their hosts seems to only be the beginning."; name = "'Facehugger' Xenomorph Physiology & Behavior Observation"},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gK" = (/obj/structure/table/reinforced,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/obj/item/device/radio/off,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gL" = (/obj/structure/cable,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gM" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gN" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/item/stack/rods,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gO" = (/obj/machinery/door_control{id = "Awaybiohazard"; name = "Biohazard Shutter Control"; pixel_x = -25; pixel_y = 0; req_access_txt = "201"},/obj/machinery/light/small{dir = 8},/obj/machinery/computer/security{desc = "Used to access the various cameras on the outpost."; network = list("MO19R","MO19")},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gP" = (/obj/structure/stool/bed/chair/office/dark,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gQ" = (/obj/structure/table,/obj/machinery/recharger{pixel_y = 4},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gR" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gS" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 0; pixel_x = 23; pixel_y = 0; req_access = null},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gT" = (/obj/machinery/optable,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gU" = (/obj/machinery/computer/operating,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gV" = (/obj/structure/table,/obj/item/clothing/gloves/color/latex,/obj/item/clothing/mask/surgical,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gW" = (/obj/structure/filingcabinet/filingcabinet,/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 17/06/2554
Report: Earlier today we have observed a new phenomenon with our subjects. While feeding them our last monkey subject and throwing out the box, the aliens merely looked at us instead of infecting the monkey right away. They looked to be collectively distressed as they would no longer be given hosts, where instead we would move to the next phase of the experiment. When I glanced at the gas tanks and piping leading to their cell, I looked back to see all of them were up against the glass, even the queen! It was as if they all understood what was going to happen, even though we knew only the queen had the cognitive capability to do so.
The only explanation for this is a form of communication between the aliens, but we have seen no such action take place anywhere in the cell until now. We also know that regular drone and hunter xenomorphs have no personality or instinct to survive by themselves. Perhaps the queen has a direct link to them? A form of a commander or overseer that controls their every move? A hivemind?"; name = "The Hivemind Hypothesis"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 08/06/2554
Report: The xenomorphs we have come to study here are a remarkable species. They are almost universally aggressive across all castes, showing no remorse or guilt or pause before or after acts of violence. They appear to be a species entirely designed to kill. Oddly enough, even their method of reproduction is a brutal two-for-one method of birthing a new xenomorph and killing its host.
The lone xenomorph we studied only five days ago showed little sign of intelligence. Only a simple drone that flung itself at the safety glass and shields repeatedly and thankfully without success. Once the drone molted into a queen, it became much more calm and calculating, merely looking at us and waiting while building its nest. As the hive grew in size and in numbers, so too did the intelligence of the common hunter and drone. We are still researching how they can communicate with one another and the relationship between the different castes and the queen. We will continue to update our research as we learn more about the species."; name = "A Preliminary Study of Alien Behavior"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 06/06/2554
Report: While observing the growing number of aliens in the containment cell, we began to notice subtle differences that were consistently repeating. Like ants, these creatures clearly have different specialized variations that determine their roles in the hive. We have dubbed the three currently observed castes as Hunters, Drones, and Sentinels.
Hunters have been observed to be by far the most aggressive and agile of the three, constantly running on every surface and frequently swiping at the windows. They are also remarkably good at camouflaging themselves in darkness and on their resin structures, appearing almost invisible to the unwary observer. They are always the first to reach the monkeys we send in leading us to believe that this caste is primarily used for finding and retrieving hosts.
Drones on the other hand are much more docile and seem more shy by comparison, though not any less aggressive than the other castes. They have been observed to have a much wider head and lack dorsal tubes. They have shown to be less agile and visibly more fragile than any other caste. The drone however has never been observed to interact with the monkeys directly and instead preferring maintenance of the hive by building walls of resin and moving eggs around the nest. As far as we know, we have only ever observed a drone become a queen, and we have no way of knowing if the other castes have that capability.
Lastly, we have the Sentinels, which appear at first glance to be the guards of the hive. They have so far been only observed to remain near the queen and the eggs, frequently curled up against the walls. We have only observed one instance where they have interacted with a monkey who strayed too closely to the queen, and was pounced and held down immediately until it was applied with a facehugger. Their lack of movement makes it difficult to determine their exact purpose as guards, sentries, or other role."; name = "The Xenomorph 'Castes'"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 04/06/2554
Report: After an extremely dangerous, time consuming and costly dissection, we have managed to record and identify several of the organs inside of the first stage of the xenomorph cycle: the larva. This procedure took an extensive amount of time because these creatures have incredibly, almost-comically acidic blood that can melt through almost anything in a few moments. We had to use over a dozen scalpels and retractors to complete the autopsy.
The larva seems to possess far fewer and quite different organs than that of a human. There is a stomach, with no digestive tract, a heart, which seems to lack any blood-oxygen circulation purpose, and an elongated brain, even though its as dumb as any large cat. It also lacks any liver, kidneys, or other basic organs.
We can't determine the exact nature of how these creatures grow, nor if they gain organs as they become adults. The larger breeds of xenomorph are too dangerous to kill and capture to give us an accurate answer to these questions. All that we can conclude is that being able to function with so little and yet be so deadly means that these creatures are highly evolved and likely to be extremely durable to various hazards that would otherwise be lethal to humans."; name = "Larva Xenomorph Autopsy Report"},/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gX" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gY" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"gZ" = (/obj/machinery/shieldwallgen{locked = 0; req_access = null},/obj/structure/cable,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ha" = (/obj/structure/disposaloutlet{desc = "An outlet for the pneumatic disposal system. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal outlet"; unacidable = 1},/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hb" = (/obj/machinery/light{active_power_usage = 0; dir = 2; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/machinery/camera{c_tag = "Xenobiology Containment South"; dir = 1; network = list("MO19X")},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hc" = (/obj/machinery/sparker{desc = "A wall-mounted ignition device. This one has been applied with an acid-proof coating."; id = "awayxenobio"; name = "Acid-Proof mounted igniter"; pixel_x = 0; pixel_y = -25; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hd" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"he" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hf" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hg" = (/obj/structure/table,/obj/item/weapon/book/manual/security_space_law,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = -32; pixel_y = 0},/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hh" = (/obj/structure/table,/obj/item/weapon/folder/red,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hi" = (/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hj" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hk" = (/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres"; locked = 0; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/storage/labcoat,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hl" = (/obj/structure/window/reinforced,/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres1"; locked = 1; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/storage/labcoat,/obj/item/weapon/tank/air,/obj/item/clothing/mask/gas,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hm" = (/obj/machinery/vending/medical{req_access_txt = "201"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hn" = (/obj/structure/closet/crate/bin,/obj/item/clothing/gloves/color/latex,/obj/item/trash/chips,/obj/effect/decal/cleanable/dirt,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ho" = (/obj/structure/table,/obj/item/weapon/storage/box/gloves{pixel_x = 0; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hp" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/effect/decal/cleanable/blood/oil,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hq" = (/obj/structure/closet/secure_closet{icon_broken = "rdsecurebroken"; icon_closed = "rdsecure"; icon_locked = "rdsecure1"; icon_off = "rdsecureoff"; icon_opened = "rdsecureopen"; icon_state = "rdsecure1"; locked = 1; name = "research director's locker"; req_access_txt = "201"},/obj/item/weapon/storage/backpack/satchel_tox,/obj/item/clothing/gloves/color/latex,/obj/item/clothing/suit/storage/labcoat/science,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hr" = (/obj/structure/table,/obj/item/weapon/cartridge/signal/toxins,/obj/item/weapon/cartridge/signal/toxins{pixel_x = -4; pixel_y = 2},/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hs" = (/obj/structure/filingcabinet/chestdrawer,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/item/weapon/paper{info = "Personal Log for Research Director Gerald Rosswell
Entry One - 17/05/2554: You know, I can't believe I took this position so suddenly. I saw that corporate needed a research director for one of it's outposts and thought it would be a cakewalk, there isn't going to be a lot of research to be done on a tiny outpost. Mainly just running scans on the gas giant we are orbiting or some basic RnD. However, they conveniently forgot to tell me that me and my science staff would have to pull double duty as medical staff and that there is no one higher up on the chain of command here, so I get to pull triple duty as acting captain as well! This shit is probably allowed in some 3 point fine print buried underneath the literally thousands of pages of contracts. Well, at least the research will be easy work.
Entry Two - 25/05/2554: Well, we all expected it at the outpost, CentComm has decided to completely change what research we are doing. They've decided that we should be research the species known as 'xenomporphs'. They announced this change 4 days ago and along with it, sadly, the termination of our current science staff barring me. Not to mention the constant noise made by the construction detail they sent to staple on an xenobiology lab ensuring no one has been able to sleep decently ever since they announced the shift. To make matters worse our current security guard actually died of a heart attack today. Just goes to show that 75 year old men shouldn't be security guards. Still can't believe that they decided to do this major change less than a month after the outpost was established.
Entry Three - 27/05/2554: The new security guard arrived today. Apparently transferred here from the research station that also is orbiting the gas giant. He seems to be rather angry about his transfer. Considering the rumors I've heard about the research station he's probably caught off guard by the fact that Steve hasn't tried to force an IED down his throat.
Entry Four - 06/06/2554: My requests for additional security and containment measures for the 'xenomorph' has been denied. Does Central Command not notice how dangerous these creatures are? The only thing keeping them in is a force field, a minor problem with the power grid and the entire hive is loose. What would stop them then, the lone security guard with a dinky little taser? Kenneth can barely handle a short-tempered engineer. We are under equipped and under staffed, we are inevitably going to be destroyed unless we get the equipment and staff we need.
Entry Five - 10/06/2554: Cunningham got a good look at the xenomorph in containment. He was frightened for the rest of the day, rather amusing if it wasn't for the fact that we are all trapped on this scrap heap with naught but a force field keeping those xenomorphs in.
Entry Six - 17/06/2554: The reactions from the specimens today has shown that they possess strange mental properties. Mark hypothesizes that they possibly have a sort of hive mind, while nothing is certain this would explain how xenomorphs seem to have vastly increased intellect when a 'queen' is present. Of course, to test this hypothesis would require many complicated procedures which we will not be able to undertake. But we do not know the full extend of the xenomorph mind, it may or may not be able to find a way to circumvent our containment system. I will resend my request for additional security measures along with this new found information."; name = "Personal Log - Gerald Rosswell"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"ht" = (/obj/structure/closet/crate/bin,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hu" = (/obj/structure/grille,/obj/machinery/door/poddoor{id_tag = "AwayRD"; layer = 2.9; name = "privacy shutter"},/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hv" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hw" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hx" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "medium"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hy" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hz" = (/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/oil,/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer{pixel_x = 6; pixel_y = -5},/obj/item/device/assembly/prox_sensor{pixel_x = -5; pixel_y = -2},/obj/item/robot_parts/l_arm,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hA" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/fire{pixel_x = 0; pixel_y = 0},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hB" = (/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hC" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hD" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/command{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Research Director's Office"; opacity = 0; req_access_txt = "201"; req_one_access_txt = "0"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
-"hE" = (/obj/structure/noticeboard{dir = 1; pixel_y = -32},/obj/machinery/light/small{active_power_usage = 0; dir = 2; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "
In The Event of Xenobiology Breach: Evacuate staff, Lock down Xenobiology, Notify on-site superiors and/or Central Command immediatly.
Welcome to Moon Outpost 19! Property of Nanotrasen Inc.
Staff Roster: -Dr. Gerald Rosswell: Research Director & Acting Captain -Dr. Sakuma Sano: Xenobiologist -Dr. Mark Douglas: Xenobiologist -Kenneth Cunningham: Security Officer-Ivan Volodin: Engineer -Mathias Kuester: Bartender -Sven Edling: Chef -Steve: Assistant
Please enjoy your stay, and report any abnormalities to an officer."; name = "Welcome Notice"},/obj/machinery/camera{c_tag = "Arrivals South"; dir = 8; network = list("MO19")},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"mX" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"mY" = (/obj/machinery/light/small{dir = 8},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 9; icon_state = "ltrails_1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "neutralcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"mZ" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"na" = (/obj/machinery/door/airlock{id_tag = "awaydorm2"; name = "Dorm 2"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nb" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 5; icon_state = "ltrails_1"},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nc" = (/obj/machinery/light/small{dir = 4},/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 0; pixel_x = 23; pixel_y = 0; req_access = null},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nd" = (/obj/machinery/portable_atmospherics/scrubber,/obj/structure/window{tag = "icon-window (NORTH)"; icon_state = "window"; dir = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ne" = (/obj/structure/grille,/obj/structure/window/full/shuttle{icon_state = "15"},/turf/simulated/shuttle/plating,/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nf" = (/obj/structure/table,/obj/item/weapon/clipboard,/obj/item/weapon/pen,/turf/simulated/shuttle/floor,/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ng" = (/obj/structure/stool/bed/chair,/obj/machinery/light/small{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nh" = (/turf/simulated/shuttle/wall{icon_state = "swall2"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ni" = (/obj/machinery/light/small{dir = 4},/obj/structure/window/reinforced,/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nj" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "neutralcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nk" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet,/obj/effect/decal/cleanable/blood,/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nl" = (/obj/structure/closet/secure_closet{desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_broken = "cabinetdetective_broken"; icon_closed = "cabinetdetective"; icon_locked = "cabinetdetective_locked"; icon_off = "cabinetdetective_broken"; icon_opened = "cabinetdetective_open"; icon_state = "cabinetdetective"; locked = 0; name = "personal closet"; req_access_txt = "201"},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nm" = (/obj/machinery/space_heater,/obj/effect/decal/cleanable/generic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nn" = (/turf/simulated/floor/plating,/turf/simulated/shuttle/wall{icon_state = "swall_f5"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"no" = (/turf/simulated/shuttle/floor,/turf/simulated/shuttle/wall{icon_state = "swall_f10"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"np" = (/obj/structure/filingcabinet,/turf/simulated/shuttle/floor,/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nq" = (/obj/structure/stool/bed/chair{dir = 8},/obj/machinery/light/small,/turf/simulated/shuttle/floor,/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nr" = (/obj/machinery/newscaster{pixel_x = 0; pixel_y = -30},/obj/machinery/light/small,/turf/simulated/shuttle/floor,/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ns" = (/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nt" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged2 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nu" = (/obj/effect/decal/cleanable/dirt,/obj/item/trash/candy,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nv" = (/obj/item/weapon/cigbutt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nw" = (/obj/structure/sign/vacuum{desc = "A warning sign which reads 'HOSTILE ATMOSPHERE AHEAD'"; name = "\improper HOSTILE ATMOSPHERE AHEAD"; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nx" = (/turf/simulated/shuttle/wall{icon_state = "swall13"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ny" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nz" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nA" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_2"},/obj/machinery/camera{c_tag = "Dormitories"; dir = 4; network = list("MO19")},/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged1 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nB" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg2"; tag = "icon-platingdmg2"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nC" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nD" = (/obj/structure/grille,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nE" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nF" = (/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 10},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"nG" = (/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"nH" = (/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/turf/simulated/shuttle/wall{icon_state = "swall_f5"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nI" = (/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/turf/simulated/shuttle/wall{icon_state = "swall_f9"; dir = 2},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nJ" = (/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 6},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"nK" = (/obj/machinery/washing_machine,/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "barber"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nL" = (/obj/machinery/light/small{dir = 1},/obj/structure/window/reinforced{dir = 4; layer = 2.9},/obj/structure/table,/obj/structure/bedsheetbin,/obj/item/clothing/accessory/black,/obj/item/clothing/under/lawyer/black,/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "barber"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nM" = (/obj/machinery/alarm/monitor{dir = 8; frequency = 1439; locked = 0; pixel_x = 23; pixel_y = 0; req_access = null},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 2; heat_capacity = 1e+006; icon_state = "neutralcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nN" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "201"; req_one_access_txt = "0"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nO" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nP" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 9; icon_state = "ltrails_1"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"nQ" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/weapon/shard,/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_2"},/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg1"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nR" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_2"},/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg3"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg3"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nS" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorgrime (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nT" = (/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 6; icon_state = "ltrails_1"},/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorgrime (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nU" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet,/obj/machinery/door_control{id = "awaydorm3"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = -25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/obj/effect/decal/remains/human{desc = "They look like human remains. The skeleton is laid out on its side and there seems to have been no sign of struggle."; layer = 4.1},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nV" = (/obj/structure/dresser,/obj/item/weapon/paper{info = "Bugs break out. I run to here and lock door. I hear door next to me break open and screams. All nice people here dead now. I no want to be eaten, and bottle always said to be coward way out, but person who say that is stupid. Mira, there is no escape for me, tell Alexis and Elena that father will never come home, and that I love you all."; name = "Note"},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nW" = (/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nX" = (/obj/structure/sign/vacuum{desc = "A warning sign which reads 'HOSTILE ATMOSPHERE AHEAD'"; name = "\improper HOSTILE ATMOSPHERE AHEAD"; pixel_x = -32},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nY" = (/obj/machinery/suit_storage_unit/standard_unit,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"nZ" = (/obj/structure/stool/bed/chair/comfy/black{dir = 8},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "neutralcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oa" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 4; heat_capacity = 1e+006; icon_state = "neutral"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ob" = (/obj/machinery/door/airlock{icon_state = "door_locked"; id_tag = "awaydorm3"; locked = 1; name = "Dorm 3"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oc" = (/obj/item/weapon/pen,/obj/item/weapon/storage/pill_bottle{pixel_y = 6},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"od" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oe" = (/obj/structure/closet,/obj/item/weapon/storage/box/lights/mixed,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"of" = (/obj/structure/table,/obj/item/toy/cards/deck,/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged1 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"og" = (/obj/machinery/newscaster{pixel_x = 30; pixel_y = 0},/turf/simulated/floor/carpet{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oh" = (/obj/structure/grille,/obj/structure/disposalpipe/segment,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oi" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oj" = (/obj/structure/stool/bed/chair/comfy/black{dir = 8},/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ok" = (/obj/machinery/light/small{dir = 4},/obj/effect/decal/cleanable/generic,/turf/simulated/floor{carbon_dioxide = 48.7; dir = 2; heat_capacity = 1e+006; icon_state = "neutralcorner"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"ol" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"om" = (/obj/structure/stool/bed/chair/comfy/black,/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"on" = (/obj/structure/flora/kirbyplants{desc = "A plastic potted plant."; layer = 4.1; pixel_y = 3},/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "neutral"; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a1{has_gravity = 1; name = "MO19 Arrivals"})
-"oo" = (/obj/structure/disposaloutlet,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_plating = "asteroidplating"; icon_state = "asteroidplating"; nitrogen = 13.2; oxygen = 32.45; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"op" = (/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oq" = (/obj/item/trash/candy,/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"or" = (/obj/item/weapon/shard,/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"os" = (/obj/item/weapon/shard{icon_state = "medium"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"ot" = (/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"ou" = (/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"ov" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"ow" = (/obj/item/stack/rods,/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"ox" = (/obj/item/stack/cable_coil,/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oy" = (/obj/item/stack/cable_coil{amount = 5},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oz" = (/obj/item/stack/cable_coil{amount = 2; icon_state = "coil_red2"; item_state = "coil_red2"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oA" = (/obj/item/stack/cable_coil{amount = 1; icon_state = "coil_red1"; item_state = "coil_red1"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oB" = (/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oC" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oD" = (/turf/simulated/floor{broken = 1; dir = 8; heat_capacity = 1e+006; icon_state = "damaged1"; tag = "icon-damaged1 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oE" = (/turf/simulated/floor{broken = 1; dir = 8; heat_capacity = 1e+006; icon_state = "damaged2"; tag = "icon-damaged2 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oF" = (/turf/simulated/floor{broken = 1; dir = 8; heat_capacity = 1e+006; icon_state = "damaged3"; tag = "icon-damaged3 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oG" = (/turf/simulated/floor{broken = 1; dir = 8; heat_capacity = 1e+006; icon_state = "damaged4"; tag = "icon-damaged4 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oH" = (/turf/simulated/floor{broken = 1; dir = 8; heat_capacity = 1e+006; icon_state = "damaged5"; tag = "icon-damaged5 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oI" = (/turf/simulated/floor{burnt = 1; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched1"; tag = "icon-floorscorched1 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oJ" = (/turf/simulated/floor{burnt = 1; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; tag = "icon-floorscorched2 (WEST)"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oK" = (/turf/simulated/shuttle/floor,/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oL" = (/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oM" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oN" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg2"; tag = "icon-platingdmg2"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oO" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oP" = (/turf/simulated/floor/plating{burnt = 1; heat_capacity = 1e+006; icon_state = "panelscorched"; tag = "icon-panelscorched"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oQ" = (/turf/simulated/floor{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oR" = (/turf/simulated/floor{carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorgrime (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oS" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged1 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oT" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged2 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oU" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged3"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged3 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oV" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged4"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged4 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oW" = (/turf/simulated/floor{broken = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "damaged5"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-damaged5 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oX" = (/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched1 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oY" = (/turf/simulated/floor{burnt = 1; carbon_dioxide = 48.7; dir = 8; heat_capacity = 1e+006; icon_state = "floorscorched2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-floorscorched2 (WEST)"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"oZ" = (/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"pa" = (/turf/simulated/floor/plating{carbon_dioxide = 48.7; heat_capacity = 1e+006; nitrogen = 13.2; oxygen = 32.4; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"pb" = (/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg1"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg1"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"pc" = (/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg2"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg2"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"pd" = (/turf/simulated/floor/plating{broken = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "platingdmg3"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-platingdmg3"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
-"pe" = (/turf/simulated/floor/plating{burnt = 1; carbon_dioxide = 48.7; heat_capacity = 1e+006; icon_state = "panelscorched"; nitrogen = 13.2; oxygen = 32.4; tag = "icon-panelscorched"; temperature = 251},/area/awaycontent/a3{always_unpowered = 1; has_gravity = 1; name = "Khonsu 19"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0})
+"eB" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/effect/decal/cleanable/blood/gibs{color = "red"; icon_state = "gib2_flesh"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eC" = (/obj/structure/alien/weeds/node,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eD" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eE" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eF" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eG" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eH" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eI" = (/obj/structure/alien/weeds,/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eJ" = (/turf/simulated/wall,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eK" = (/turf/simulated/wall/rust,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eL" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eM" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eN" = (/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/obj/machinery/camera{c_tag = "Xenobiology"; dir = 4; network = list("MO19","MO19R")},/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eO" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible,/obj/structure/stool/bed/chair/office/light{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eP" = (/obj/structure/table/reinforced,/obj/machinery/door_control{id = "Awaylab"; name = "Containment Chamber Blast Doors"; pixel_x = 4; pixel_y = -2; req_access_txt = "201"},/obj/machinery/ignition_switch{id = "awayxenobio"; pixel_x = 4; pixel_y = 8},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eQ" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eR" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood{color = "red"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eS" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eT" = (/obj/machinery/power/port_gen/pacman{desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eU" = (/obj/machinery/power/port_gen/pacman/super{desc = "A portable generator for emergency backup power."; name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator"},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg2"; tag = "icon-platingdmg2"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eV" = (/obj/machinery/space_heater,/obj/machinery/light/small{dir = 1},/obj/structure/sign/poster{icon_state = "poster5_legit"; pixel_x = 0; pixel_y = 32; serial_number = 21; subtype = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eW" = (/obj/machinery/power/terminal{dir = 4},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eX" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/power/smes{charge = 1.5e+006; input_level = 10000; inputting = 0; output_level = 15000; outputting = 1},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eY" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"eZ" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/item/weapon/newspaper,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fa" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fb" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fc" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fd" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "201"; req_one_access_txt = "0"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fe" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 5; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ff" = (/obj/structure/sign/securearea{pixel_x = 32},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fg" = (/obj/structure/table,/obj/machinery/reagentgrinder,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fh" = (/obj/structure/table,/obj/item/stack/sheet/mineral/plasma{layer = 2.9},/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fi" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/table,/obj/item/weapon/storage/box/beakers{pixel_x = 2; pixel_y = 2},/obj/item/weapon/storage/box/syringes,/obj/structure/alien/weeds,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fj" = (/obj/structure/closet/crate/freezer,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/item/xenos_claw,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fk" = (/obj/machinery/door/firedoor,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fl" = (/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fm" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fn" = (/obj/structure/closet/l3closet/scientist,/obj/structure/window/reinforced,/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fo" = (/obj/structure/cable,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fp" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/weeds{desc = "A large mottled egg."; health = 100; icon_state = "egg_hatched"; name = "egg"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fq" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fr" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fs" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/generic,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ft" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fv" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fw" = (/obj/structure/extinguisher_cabinet{pixel_x = -26},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; icon_state = "ltrails_2"},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fx" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fy" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/research{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Xenobiology Lab"; opacity = 0; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fz" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fA" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fC" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/alien/weeds/node,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fD" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible{dir = 5},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fE" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fF" = (/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/item/stack/rods,/obj/item/stack/cable_coil{amount = 5},/obj/item/weapon/shard{icon_state = "medium"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fG" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fH" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood{color = "red"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fI" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fJ" = (/obj/machinery/atmospherics/pipe/simple/visible{desc = "A one meter section of pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof Pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fK" = (/obj/machinery/atmospherics/unary/outlet_injector{desc = "Has a valve and pump attached to it. This one has been applied with an acid-proof coating."; dir = 8; icon_state = "on"; name = "Acid-Proof Air Injector"; on = 1; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fL" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/machinery/camera{c_tag = "Xenobiology Containment East"; dir = 8; network = list("MO19X")},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fM" = (/obj/machinery/portable_atmospherics/scrubber,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fN" = (/obj/item/weapon/cigbutt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fO" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fP" = (/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fQ" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fR" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "0"; req_one_access_txt = "0"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fS" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/effect/decal/cleanable/blood/oil{color = "black"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fT" = (/obj/structure/filingcabinet,/obj/item/weapon/paper{info = "Entry One - 27/05/2554: I just arrived, and already I hate my job. I'm stuck on this shithole of an outpost, trying to avoid these damn eggheads running all over the place preparing for god knows what. There's no crimes to stop, no syndies to kill, and I'm not even allowed to beat the fuckin' assistant senseless! They said I was transferred from Space Station 13 for 'good behavior', but this feels more like a punishment than a reward. All I know is that if I don't get some action soon, I'm going to go insane.
Entry Two - 03/06/2554: Okay, so get this: we got a fuckin' deathsquad coming in today! I thought the day I saw one of them would be the day my employment was 'terminated', if you get my drift. They're escorting some sort of weird alien creature for the eggheads to study. I heard one of the docs telling the chef that this thing killed a whole security force before it was captured. I sure as hell hope that I don't have to fight it.
Entry Three - 08/06/2554: My first real bit of 'action' today, if you could call it that. Crazy Ivan got in a fight with Kuester today about his Booze-O-Mat. Apparently one of the crewmembers had stolen a couple bottles of booze from the machine after Ivan disabled the ID lock. Tell you the truth, I don't blame the thief. Everyone is going a little stir-crazy in here, and the bartender is being damn stingy with the alcohol. Either way, once they started to pick a fight, I had to take them down. It's a damn shame that we don't have a brig, though. I had to lock Ivan in a fuckin' freezer, for god's sake. Let's hope that we can keep our sanity together, at least for a while.
Entry Four - 10/06/2554: Jesus fucking Christ riding on a motorbike. These things the scientists are studying are terrifying! Fucking great huge purple bug things as tall as the ceiling, with blades for arms and drooling at the mouth. I don't think my taser will do jack shit against these damn things, but the eggheads say that they're safely contained. If they do, I have a feeling that it's only a matter of time before we're all screwed. These bastards look like walking death.
Entry Five - 18/06/2554: Finally caught who stole the booze from Kuester. It was that fuckin' loser assistant Steve! He was in the dorms, chugging his worries away. I took one of the bottles back to the barkeep, but no one has to know about this second one. I think I'm gonna enjoy this while watching tomorrow's Thunderdome match.
Entry Six - 19/06/2554: Oh, great. The chef is still sleeping, so we get Ivan's gruel for breakfast today. I overheard Sano and Douglas saying something about the aliens being restless, so we might get some action today. As long as it happens after the big game, I'm fine with it. I still got one beer to drink before I'm ready to die."; name = "Personal Log - Kenneth Cunningham"},/turf/simulated/floor{dir = 9; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fU" = (/obj/structure/closet/secure_closet{icon_broken = "secbroken"; icon_closed = "sec"; icon_locked = "sec1"; icon_off = "secoff"; icon_opened = "secopen"; icon_state = "sec1"; locked = 1; name = "security officer's locker"; req_access_txt = "201"},/obj/item/clothing/suit/armor/vest,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/grenade/flashbang,/obj/item/weapon/storage/belt/security,/obj/item/weapon/reagent_containers/food/drinks/cans/beer{pixel_x = -3; pixel_y = -2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fV" = (/obj/structure/sign/poster{icon_state = "poster21_legit"; pixel_y = 32; serial_number = 21; subtype = 1},/obj/item/device/radio/off,/obj/item/weapon/screwdriver{pixel_y = 10},/turf/simulated/floor{dir = 5; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fW" = (/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fX" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fY" = (/obj/structure/sign/biohazard{pixel_x = 32},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"fZ" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ga" = (/obj/machinery/door/firedoor,/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -29},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gb" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/closet/l3closet/scientist,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gc" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/item/stack/cable_coil/cut{amount = 1; icon_state = "coil_red1"; item_state = "coil_red1"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gd" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/effect/decal/cleanable/blood{color = "red"},/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ge" = (/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gf" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; dir = 4; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gg" = (/obj/structure/alien/weeds,/obj/structure/stool/bed/nest,/obj/item/clothing/mask/facehugger{icon_state = "facehugger_impregnated"; item_state = "facehugger_impregnated"; stat = 2},/obj/effect/decal/cleanable/blood/gibs{color = "red"; icon_state = "gibdown1_flesh"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gh" = (/obj/structure/stool,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gi" = (/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gj" = (/obj/effect/decal/cleanable/blood/oil{color = "black"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gk" = (/obj/structure/reagent_dispensers/peppertank{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gl" = (/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gm" = (/obj/machinery/door/airlock/glass_security{name = "Security Post"; req_access_txt = "201"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gn" = (/obj/effect/decal/cleanable/blood/tracks{color = "red"; desc = "Your instincts say you shouldn't be following these."; icon = 'icons/effects/blood.dmi'; icon_state = "tracks"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"go" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gp" = (/obj/structure/table,/obj/item/weapon/scalpel{pixel_y = 12},/obj/item/weapon/circular_saw,/obj/item/weapon/razor{pixel_y = 5},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gq" = (/obj/structure/alien/weeds/node,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gr" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gs" = (/obj/structure/table,/obj/item/device/mmi,/obj/item/device/mmi,/obj/item/device/mmi,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "warnwhite"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gt" = (/obj/structure/sink{dir = 8; icon_state = "sink"; pixel_x = -12; pixel_y = 2},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gu" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gv" = (/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable,/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gw" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 4; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds,/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gx" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 2; icon_state = "pipe-c"; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gy" = (/obj/structure/table,/obj/effect/decal/cleanable/dirt,/obj/machinery/cell_charger,/obj/item/weapon/stock_parts/cell/high,/obj/item/device/radio/off,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gz" = (/obj/structure/table,/obj/item/weapon/paper{info = "Ivan Volodin Stories:
Entry Won - 28/05/2554: Hello. I am Crazy Ivan. Boss say I must write. I do good job fixing outpost. Is very good job. Much better than mines. Many nice people. I cause no trouble.
Entry Too - 05/06/2554: I am finding problem with Booze-O-Mat. Is not problem. I solve very easy. Use yellow tool to make purple light go off. I am good engineer! Bartender will be very happy.
Entry Tree - 08/06/2554: Bartender is not happy. Security man is not happy. Cannot feel legs, is very cold in freezer. Is not good. Table is jammed into door, have no tools. Is very not good. But, on bright side, found meat! Shall chew to keep spirits up.
Entry Fore - 12/06/2554: Big nasty purple bug looked at me today. Make nervous. Blue wall wire can be broken, then bad thing happens. Very very bad thing. Man in orange spacesuit wave at me today too. He seem nice. Wonder who was?
Entry Fiv - 15/06/2554: I eat cornflakes today. Is good day. Sun shine for a while. Was nice. I also take ride on disposals chute. Was fun, but tiny. Get clog out of pipes, was vodka bottle. Is empty. This make many sads.
Entry Sex: 19/06/2554: Purple bugs jumpy today. When waved, get hiss. Maybe very bad. Maybe just ill. Do not know. Is science problem, is not engineer problem. I eat sandwich. Is glorious job. Wish to never end."; name = "Personal Log - Ivan Volodin"},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gA" = (/obj/machinery/light/small,/obj/structure/closet/toolcloset,/obj/item/clothing/gloves/color/yellow,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gB" = (/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gC" = (/obj/machinery/computer/monitor,/obj/structure/cable,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gD" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/newscaster/security_unit{pixel_x = -30; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gE" = (/obj/effect/decal/cleanable/blood/splatter{color = "red"},/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gF" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/obj/effect/decal/cleanable/blood/tracks{desc = "Your instincts say you shouldn't be following these."; dir = 8; icon_state = "ltrails_1"},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gG" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gH" = (/obj/structure/cable,/obj/machinery/power/apc{cell_type = 15000; dir = 4; locked = 0; name = "Worn-out APC"; pixel_x = 25; req_access = null; start_charge = 100},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gI" = (/obj/structure/table,/obj/item/weapon/retractor,/obj/item/weapon/hemostat,/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gJ" = (/obj/structure/table,/obj/machinery/light/small{active_power_usage = 0; dir = 4; icon_state = "bulb-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gK" = (/obj/structure/filingcabinet/filingcabinet,/obj/machinery/light/small{active_power_usage = 0; dir = 8; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: As expected, all that is left of the monkeys we sent in earlier is a group of xenomorph larvae. It is quite clear that the facehuggers are not selective in their hosts, and so far the gestation process has been shown to have a 100% success rate.
The larvae themselves have been behaving very differently from the lone larva we first observed, and despite shying away from humans they are clearly comfortable with others of their kind. Our previous suspicions on larvae have been confirmed with their demonstration of playfulness: they are not nearly as aggressive or violent when young, before molting to adulthood.
The majority of the play we observed involved a sort of hide-and-seek, and occasionally wrestling by tangling themselves and struggling out of it. While normally we would write these off as instinctual play for honing their skills when they molt, their growth period is so incredibly fast and they are still such adept killers that it would serve no practical purpose. The only explanation for this is perhaps to create bonds and friendships with each other, if that is even possible for such an incredibly hostile race. It may be that they are much more reasonable with each other than other life forms.
It had become clear that now was the best time to extract a xenomorph for dissecting, as these were all still larvae and the queen was still attached to its ovipositor and would be immobile. With the approval of the research director, we sent in our medical robot that had been dubbed 'Head Surgeon' into the containment pen, dropping the shields for only a fraction of a second to allow it entry. The larvae were cautious, but the curiosity of one had him within grabbing range of our robot. It was brought out and quickly euthanized through lethal injection, courtesy of our mechanical doctor."; name = "Larva Xenomorph Social Interactions & Capturing Procedure"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 04/06/2554
Report: I have studied many interesting and diverse life-forms as a xenobiologist ranging from creatures as large as cows, to specimens too small see with the naked eye. This is by far the largest alien I have ever seen. The alien we were previously studying has molted and has become an absolutely enormous creature. Standing at over 15 feet tall and weighing in at likely two tons or more, the xenomorph queen is an absolutely breathtakingly large and cruel monster. Its behavior has changed drastically from when it was a drone, having become far more comfortable with sitting and staring at us, rather than smashing at the windows.
The queen, physiologically speaking, is fairly similar to the other xenomorphs, with a few key differences. Its enormous size demands large legs, while the back seems to be always hunched forward. The dorsal tubes on the back have changed to several large spikes, and we observed the alien now sports a second pair of smaller arms on its chest. The purpose of these secondary arms is still unknown. Finally, the queen's crown has become incredibly large, with what seems to be a retractable slot to hide its head in. The dome appears to be extremely thick near the front, and will likely be able to resist a lot of trauma. Despite the enormous size it has grown to, it is not that much slower than it used to be.
After two hours of doing relatively nothing but staring, the queen began to produce an unusually large amount of resin and weeds, quickly shaping up a large nest that it then hid behind. It then proceeded to smash out all the lights, leaving us with very little to see with our cameras. When we looked through the back cameras, we had discovered that it had grown a large ovipositor, and was releasing large eggs onto the ground. This had us all in agreement that this stage of the life cycle was the queen.
Over the next few hours, the eggs grew to their full sizes, and we provided the subject with new monkey hosts. When they approached the eggs, they opened to release more facehuggers. It seems that we have observed the full cycle of reproduction for this species. We can expect more larvae in the next few hours."; name = "Queen Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The other scientists and I can hardly believe our eyes. The snake-like larva has molted into a 7 foot tall insectoid nightmare in just a few hours. It's obvious now as to why such heavy duty containment was needed. It immediately tried to escape however by flinging itself at the window in a flurry of swipes and stabs. It seems its behavior has returned to a state that is very similar to the facehugger, though I doubt with the same intent! Thankfully, our glass and shields have shown to be more than sturdy enough for such a violent creature, and so far, any attempts at the creature escaping have been in vain.
As for its physiology, the creature has an elongated head with what appears to be have an exoskeleton resembling an external rib-cage on the torso. The alien is also fairly skinny with a lean body. The little amount of meat on the alien appears to be entirely muscle. We assume this makes it deceptively strong, while remaining agile at the same time. One of the most interesting things we have seen is its pharyngeal jaw. It has some what of an inner mouth capable of being fired externally at extremely high speeds. It has already caused many dents in the walls and a few small cracks in the window with it. The alien also has a couple of dorsal tubes on its back, their purpose unknown. Finally, this monster sports a long ridged tail, complete with a large and extremely sharp blade at the tip.
Normally I would be absolutely terrified of something like this, but I'm putting my trust in Nanotrasen with the containment. After all, they wouldn't build a cell that could fail to contain its subject, would they?"; name = "Adult Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: When the larva first emerged from the chest of the monkey, it seemed very curious. It would wander around aimlessly for awhile and then sit still. We are unable to determine the gender of the larva, or even determine if it has a gender. After some time had passed, it seemed to lose interest in its surroundings and sat mostly still while occasionally wagging its tail. We decided to throw in a live mouse to see if it would consume it. The larva quickly attacked and ate the mouse and seemed to get larger very suddenly, this suggests that the larvae are capable of metabolizing and directing all the energy towards growth at previously thought impossible speeds. It is a shame that we cannot observe the process more closely, as we do not currently know how dangerous or violent this creature is or will become as it matures fully.
It is tempting to imagine the possibilities of utilizing such a mechanism. The capability of skipping years of growth time for children, repairing bodily damage in a matter of moments, even its usage in existing cloning technology."; name = "Larva Xenomorph Physiology & Behavior Observation"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 03/06/2554
Report: The test subject we were provided with truly is alien. It is a small spider-like creature with bony legs leading to a smooth body. It has a long tail connected to it, and it has shown extremely aggressive behavior by flinging its entire body at the glass and shields to no avail. While doing so, we noticed there was a small pink hole in the middle of the body.
When we sent in a monkey through the crude but effective disposal tube, the alien immediately jumped at its face and latched on. The monkey was quickly suffocated by its constricting tail, unable to pry off the fingers. The monkey at first seemed to be dead, but was observed to be breathing. The recently named alien 'facehugger' fell off dead and curled its legs up like a spider moments after it had finished with the monkey's body.
While the monkey appeared to be unharmed, we kept it in the cell for a couple more hours until we were horrified to discover it screaming out in pain as a snake-like creature erupted from the monkey's chest! It appears that the 'facehugger' is only the start of this life cycle. The impregnation cycle involving the creatures growing inside the chests of their hosts seems to only be the beginning."; name = "'Facehugger' Xenomorph Physiology & Behavior Observation"},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gL" = (/obj/structure/table/reinforced,/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/obj/item/device/radio/off,/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gM" = (/obj/structure/cable,/obj/machinery/door/poddoor/preopen{desc = "A heavy duty blast door that opens mechanically. This one has been applied with an acid-proof coating."; id_tag = "Awaylab"; name = "Acid-Proof containment chamber blast door"; unacidable = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/grille,/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gN" = (/obj/structure/disposalpipe/segment{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gO" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/item/stack/rods,/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gP" = (/obj/machinery/door_control{id = "Awaybiohazard"; name = "Biohazard Shutter Control"; pixel_x = -25; pixel_y = 0; req_access_txt = "201"},/obj/machinery/light/small{dir = 8},/obj/machinery/computer/security{desc = "Used to access the various cameras on the outpost."; network = list("MO19R","MO19")},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gQ" = (/obj/structure/stool/bed/chair/office/dark,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gR" = (/obj/structure/table,/obj/machinery/recharger{pixel_y = 4},/turf/simulated/floor{dir = 4; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gS" = (/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gT" = (/obj/machinery/light{active_power_usage = 0; dir = 4; icon_state = "tube-broken"; status = 2},/obj/machinery/alarm{dir = 8; frequency = 1439; locked = 0; pixel_x = 23; pixel_y = 0; req_access = null},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gU" = (/obj/machinery/optable,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gV" = (/obj/machinery/computer/operating,/obj/structure/alien/weeds,/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gW" = (/obj/structure/table,/obj/item/clothing/gloves/color/latex,/obj/item/clothing/mask/surgical,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gX" = (/obj/structure/filingcabinet/filingcabinet,/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 17/06/2554
Report: Earlier today we have observed a new phenomenon with our subjects. While feeding them our last monkey subject and throwing out the box, the aliens merely looked at us instead of infecting the monkey right away. They looked to be collectively distressed as they would no longer be given hosts, where instead we would move to the next phase of the experiment. When I glanced at the gas tanks and piping leading to their cell, I looked back to see all of them were up against the glass, even the queen! It was as if they all understood what was going to happen, even though we knew only the queen had the cognitive capability to do so.
The only explanation for this is a form of communication between the aliens, but we have seen no such action take place anywhere in the cell until now. We also know that regular drone and hunter xenomorphs have no personality or instinct to survive by themselves. Perhaps the queen has a direct link to them? A form of a commander or overseer that controls their every move? A hivemind?"; name = "The Hivemind Hypothesis"},/obj/item/weapon/paper{info = "Researcher: Dr. Sakuma Sano Date: 08/06/2554
Report: The xenomorphs we have come to study here are a remarkable species. They are almost universally aggressive across all castes, showing no remorse or guilt or pause before or after acts of violence. They appear to be a species entirely designed to kill. Oddly enough, even their method of reproduction is a brutal two-for-one method of birthing a new xenomorph and killing its host.
The lone xenomorph we studied only five days ago showed little sign of intelligence. Only a simple drone that flung itself at the safety glass and shields repeatedly and thankfully without success. Once the drone molted into a queen, it became much more calm and calculating, merely looking at us and waiting while building its nest. As the hive grew in size and in numbers, so too did the intelligence of the common hunter and drone. We are still researching how they can communicate with one another and the relationship between the different castes and the queen. We will continue to update our research as we learn more about the species."; name = "A Preliminary Study of Alien Behavior"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 06/06/2554
Report: While observing the growing number of aliens in the containment cell, we began to notice subtle differences that were consistently repeating. Like ants, these creatures clearly have different specialized variations that determine their roles in the hive. We have dubbed the three currently observed castes as Hunters, Drones, and Sentinels.
Hunters have been observed to be by far the most aggressive and agile of the three, constantly running on every surface and frequently swiping at the windows. They are also remarkably good at camouflaging themselves in darkness and on their resin structures, appearing almost invisible to the unwary observer. They are always the first to reach the monkeys we send in leading us to believe that this caste is primarily used for finding and retrieving hosts.
Drones on the other hand are much more docile and seem more shy by comparison, though not any less aggressive than the other castes. They have been observed to have a much wider head and lack dorsal tubes. They have shown to be less agile and visibly more fragile than any other caste. The drone however has never been observed to interact with the monkeys directly and instead preferring maintenance of the hive by building walls of resin and moving eggs around the nest. As far as we know, we have only ever observed a drone become a queen, and we have no way of knowing if the other castes have that capability.
Lastly, we have the Sentinels, which appear at first glance to be the guards of the hive. They have so far been only observed to remain near the queen and the eggs, frequently curled up against the walls. We have only observed one instance where they have interacted with a monkey who strayed too closely to the queen, and was pounced and held down immediately until it was applied with a facehugger. Their lack of movement makes it difficult to determine their exact purpose as guards, sentries, or other role."; name = "The Xenomorph 'Castes'"},/obj/item/weapon/paper{info = "Researcher: Dr. Mark Douglas Date: 04/06/2554
Report: After an extremely dangerous, time consuming and costly dissection, we have managed to record and identify several of the organs inside of the first stage of the xenomorph cycle: the larva. This procedure took an extensive amount of time because these creatures have incredibly, almost-comically acidic blood that can melt through almost anything in a few moments. We had to use over a dozen scalpels and retractors to complete the autopsy.
The larva seems to possess far fewer and quite different organs than that of a human. There is a stomach, with no digestive tract, a heart, which seems to lack any blood-oxygen circulation purpose, and an elongated brain, even though its as dumb as any large cat. It also lacks any liver, kidneys, or other basic organs.
We can't determine the exact nature of how these creatures grow, nor if they gain organs as they become adults. The larger breeds of xenomorph are too dangerous to kill and capture to give us an accurate answer to these questions. All that we can conclude is that being able to function with so little and yet be so deadly means that these creatures are highly evolved and likely to be extremely durable to various hazards that would otherwise be lethal to humans."; name = "Larva Xenomorph Autopsy Report"},/obj/structure/alien/weeds,/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gY" = (/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor{icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"gZ" = (/obj/effect/decal/cleanable/dirt,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "warning"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ha" = (/obj/machinery/shieldwallgen{locked = 0; req_access = null},/obj/structure/cable,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hb" = (/obj/structure/disposaloutlet{desc = "An outlet for the pneumatic disposal system. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal outlet"; unacidable = 1},/obj/structure/disposalpipe/trunk{desc = "An underfloor disposal pipe. This one has been applied with an acid-proof coating."; dir = 1; name = "Acid-Proof disposal pipe"; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds1"},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hc" = (/obj/machinery/light{active_power_usage = 0; dir = 2; icon_state = "tube-broken"; status = 2},/obj/structure/alien/weeds{icon_state = "weeds1"},/obj/machinery/camera{c_tag = "Xenobiology Containment South"; dir = 1; network = list("MO19X")},/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hd" = (/obj/machinery/sparker{desc = "A wall-mounted ignition device. This one has been applied with an acid-proof coating."; id = "awayxenobio"; name = "Acid-Proof mounted igniter"; pixel_x = 0; pixel_y = -25; unacidable = 1},/obj/structure/alien/weeds{icon_state = "weeds2"},/obj/structure/alien/resin/wall,/turf/simulated/floor/engine,/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"he" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hf" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hg" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hh" = (/obj/structure/table,/obj/item/weapon/book/manual/security_space_law,/obj/machinery/computer/security/telescreen/entertainment{pixel_x = -32; pixel_y = 0},/turf/simulated/floor{dir = 10; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hi" = (/obj/structure/table,/obj/item/weapon/folder/red,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hj" = (/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/turf/simulated/floor{dir = 6; heat_capacity = 1e+006; icon_state = "red"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hk" = (/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hl" = (/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres"; locked = 0; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/storage/labcoat,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hm" = (/obj/structure/window/reinforced,/obj/structure/closet/secure_closet{icon_broken = "secureresbroken"; icon_closed = "secureres"; icon_locked = "secureres1"; icon_off = "secureresoff"; icon_opened = "secureresopen"; icon_state = "secureres1"; locked = 1; name = "scientist's locker"; req_access_txt = "201"},/obj/item/clothing/suit/storage/labcoat,/obj/item/weapon/tank/air,/obj/item/clothing/mask/gas,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hn" = (/obj/machinery/vending/medical{req_access_txt = "201"},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ho" = (/obj/structure/closet/crate/bin,/obj/item/clothing/gloves/color/latex,/obj/item/trash/chips,/obj/effect/decal/cleanable/dirt,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hp" = (/obj/structure/table,/obj/item/weapon/storage/box/gloves{pixel_x = 0; pixel_y = 0},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hq" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/effect/decal/cleanable/blood/oil{color = "black"},/turf/simulated/floor/plating{broken = 1; heat_capacity = 1e+006; icon_state = "platingdmg3"; tag = "icon-platingdmg3"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hr" = (/obj/structure/closet/secure_closet{icon_broken = "rdsecurebroken"; icon_closed = "rdsecure"; icon_locked = "rdsecure1"; icon_off = "rdsecureoff"; icon_opened = "rdsecureopen"; icon_state = "rdsecure1"; locked = 1; name = "research director's locker"; req_access_txt = "201"},/obj/item/weapon/storage/backpack/satchel_tox,/obj/item/clothing/gloves/color/latex,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hs" = (/obj/structure/table,/obj/item/weapon/cartridge/signal/toxins,/obj/item/weapon/cartridge/signal/toxins{pixel_x = -4; pixel_y = 2},/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"ht" = (/obj/structure/filingcabinet/chestdrawer,/obj/machinery/light/small{active_power_usage = 0; dir = 1; icon_state = "bulb-broken"; status = 2},/obj/machinery/alarm{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/item/weapon/paper{info = "Personal Log for Research Director Gerald Rosswell
Entry One - 17/05/2554: You know, I can't believe I took this position so suddenly. I saw that corporate needed a research director for one of it's outposts and thought it would be a cakewalk, there isn't going to be a lot of research to be done on a tiny outpost. Mainly just running scans on the gas giant we are orbiting or some basic RnD. However, they conveniently forgot to tell me that me and my science staff would have to pull double duty as medical staff and that there is no one higher up on the chain of command here, so I get to pull triple duty as acting captain as well! This shit is probably allowed in some 3 point fine print buried underneath the literally thousands of pages of contracts. Well, at least the research will be easy work.
Entry Two - 25/05/2554: Well, we all expected it at the outpost, CentComm has decided to completely change what research we are doing. They've decided that we should be research the species known as 'xenomporphs'. They announced this change 4 days ago and along with it, sadly, the termination of our current science staff barring me. Not to mention the constant noise made by the construction detail they sent to staple on an xenobiology lab ensuring no one has been able to sleep decently ever since they announced the shift. To make matters worse our current security guard actually died of a heart attack today. Just goes to show that 75 year old men shouldn't be security guards. Still can't believe that they decided to do this major change less than a month after the outpost was established.
Entry Three - 27/05/2554: The new security guard arrived today. Apparently transferred here from the research station that also is orbiting the gas giant. He seems to be rather angry about his transfer. Considering the rumors I've heard about the research station he's probably caught off guard by the fact that Steve hasn't tried to force an IED down his throat.
Entry Four - 06/06/2554: My requests for additional security and containment measures for the 'xenomorph' has been denied. Does Central Command not notice how dangerous these creatures are? The only thing keeping them in is a force field, a minor problem with the power grid and the entire hive is loose. What would stop them then, the lone security guard with a dinky little taser? Kenneth can barely handle a short-tempered engineer. We are under equipped and under staffed, we are inevitably going to be destroyed unless we get the equipment and staff we need.
Entry Five - 10/06/2554: Cunningham got a good look at the xenomorph in containment. He was frightened for the rest of the day, rather amusing if it wasn't for the fact that we are all trapped on this scrap heap with naught but a force field keeping those xenomorphs in.
Entry Six - 17/06/2554: The reactions from the specimens today has shown that they possess strange mental properties. Mark hypothesizes that they possibly have a sort of hive mind, while nothing is certain this would explain how xenomorphs seem to have vastly increased intellect when a 'queen' is present. Of course, to test this hypothesis would require many complicated procedures which we will not be able to undertake. But we do not know the full extend of the xenomorph mind, it may or may not be able to find a way to circumvent our containment system. I will resend my request for additional security measures along with this new found information."; name = "Personal Log - Gerald Rosswell"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hu" = (/obj/structure/closet/crate/bin,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hv" = (/obj/structure/grille,/obj/machinery/door/poddoor{id_tag = "AwayRD"; layer = 2.9; name = "privacy shutter"},/obj/structure/window/full/reinforced,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hw" = (/turf/simulated/floor{dir = 1; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hx" = (/turf/simulated/floor{dir = 2; heat_capacity = 1e+006; icon_state = "whitepurplecorner"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hy" = (/obj/structure/grille{density = 0; destroyed = 1; icon_state = "brokengrille"},/obj/item/stack/rods,/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "medium"},/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hz" = (/obj/item/stack/rods,/obj/item/weapon/shard{icon_state = "small"},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hA" = (/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/oil{color = "black"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer{pixel_x = 6; pixel_y = -5},/obj/item/device/assembly/prox_sensor{pixel_x = -5; pixel_y = -2},/obj/item/robot_parts/l_arm,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "white"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hB" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/fire{pixel_x = 0; pixel_y = 0},/obj/machinery/firealarm{dir = 4; pixel_x = 28},/turf/simulated/floor{dir = 8; heat_capacity = 1e+006; icon_state = "whitehall"},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hC" = (/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hD" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hE" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/command{density = 0; emagged = 1; icon_state = "door_open"; locked = 1; name = "Research Director's Office"; opacity = 0; req_access_txt = "201"; req_one_access_txt = "0"},/turf/simulated/floor{tag = "icon-cafeteria (NORTHEAST)"; icon_state = "cafeteria"; dir = 5},/area/awaycontent/a2{has_gravity = 1; name = "MO19 Research"})
+"hF" = (/obj/structure/noticeboard{dir = 1; pixel_y = -32},/obj/machinery/light/small{active_power_usage = 0; dir = 2; icon_state = "bulb-broken"; status = 2},/obj/item/weapon/paper{info = "
In The Event of Xenobiology Breach: Evacuate staff, Lock down Xenobiology, Notify on-site superiors and/or Central Command immediatly.
"
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index e6d258b3386..37c6a60bcdd 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -2,38 +2,42 @@
world/IsBanned(key,address,computer_id)
if (!key || !address || !computer_id)
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
- return list("reason"="invalid login data", "desc"="Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]' If you continue to get this error, please restart byond or contact byond support.")
- if(ckey(key) in admin_datums)
- return ..()
+ return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
+ var/admin = 0
+ var/ckey = ckey(key)
+ if((ckey in admin_datums) || (ckey in deadmins))
+ admin = 1
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
- log_access("Failed Login: [key] - Guests not allowed")
+ log_access("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("\blue Failed Login: [key] - Guests not allowed")
- return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
+ return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
- //check if the IP address is a known TOR node
- if(config && config.ToRban && ToRban_isbanned(address))
- log_access("Failed Login: [src] - Banned: ToR")
- message_admins("\blue Failed Login: [src] - Banned: ToR")
+ //check if the IP address is a known Tor node
+ if(config.ToRban && ToRban_isbanned(address))
+ log_access("Failed Login: [key] [computer_id] [address] - Banned: Tor")
+ message_admins("Failed Login: [key] - Banned: Tor")
//ban their computer_id and ckey for posterity
- AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0)
- return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]")
+ AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0)
+ var/mistakemessage = ""
+ if(config.banappeals)
+ mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
+ return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
if(config.ban_legacy_system)
-
//Ban Checking
- . = CheckBan( ckey(key), computer_id, address )
+ . = CheckBan(ckey(key), computer_id, address)
if(.)
- log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
- message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
- return .
-
- return ..() //default pager ban stuff
-
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]].")
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
else
-
var/ckeytext = ckey(key)
if(!establish_db_connection())
@@ -49,7 +53,7 @@ world/IsBanned(key,address,computer_id)
if(computer_id)
cidquery = " OR computerid = '[computer_id]' "
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
@@ -63,18 +67,47 @@ world/IsBanned(key,address,computer_id)
var/duration = query.item[7]
var/bantime = query.item[8]
var/bantype = query.item[9]
-
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ //admin bans MUST match on ckey to prevent cid-spoofing attacks
+ // as well as dynamic ip abuse
+ if (pckey != ckey)
+ continue
+ if (admin)
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ log_admin("The admin [key] is admin banned, and has been disallowed access")
+ message_admins("The admin [key] is admin banned, and has been disallowed access")
+ else
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [pckey].")
+ continue
var/expires = ""
if(text2num(duration) > 0)
- expires = "The ban is for [duration] minutes and expires on [expiration] (server time)."
- if(istext(bantype) && (bantype == "PERMABAN"))
- var/appealmsg = ""
- if(config && config.banappeals)
- appealmsg = " You may appeal it at [config.banappeals]."
- expires = "The ban is permanent.[appealmsg]"
+ expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
+ else
+ var/appealmessage = ""
+ if(config.banappeals)
+ appealmessage = " You may appeal it at [config.banappeals]."
+ expires = " The is a permanent ban.[appealmessage]"
- var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime]. [expires]"
+ var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
- return list("reason"="[bantype]", "desc"="[desc]")
+ . = list("reason"="[bantype]", "desc"="[desc]")
- return ..() //default pager ban stuff
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
+
+ . = ..() //default pager ban stuff
+ if (.)
+ //byond will not trigger isbanned() for "global" host bans,
+ //ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked)
+ //So it's safe to let admins walk thru host/sticky bans here
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ message_admins("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban.")
+ return null
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]")
+
+ return .
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b7a5fa46935..8e008fccb4f 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -519,21 +519,16 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER))
return
- var/confirm = alert("Restart the game world?", "Restart", "Yes", "Cancel")
- if(confirm == "Cancel")
+ var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
+ if(isnull(delay))
return
- if(confirm == "Yes")
- var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num
- if(isnull(delay))
- delay = 50
- else
- delay = delay * 10
- message_admins("[key_name_admin(usr)] has initiated a server restart with a delay of [delay/10] seconds")
- log_admin("[key_name(usr)] has initiated a server restart with a delay of [delay/10] seconds")
- ticker.delay_end = 0
- feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay)
-
+ else
+ delay = delay * 10
+ message_admins("[key_name_admin(usr)] has initiated a server restart with a delay of [delay/10] seconds")
+ log_admin("[key_name(usr)] has initiated a server restart with a delay of [delay/10] seconds")
+ ticker.delay_end = 0
+ feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay)
/datum/admins/proc/announce()
set category = "Special Verbs"
@@ -800,7 +795,7 @@ var/global/nologevent = 0
set desc = "Edit mobs's memory and role"
set name = "Show Traitor Panel"
- if(!check_rights(R_ADMIN))
+ if(!check_rights(R_ADMIN|R_MOD))
return
if(!istype(M))
diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm
index 03fc3767b8e..355a82aa697 100644
--- a/code/modules/admin/admin_memo.dm
+++ b/code/modules/admin/admin_memo.dm
@@ -11,7 +11,7 @@
return
admin_memo_output(memotask)
-/client/proc/admin_memo_output(task, checkrights = 1)
+/client/proc/admin_memo_output(task, checkrights = 1, silent = 0)
if(checkrights && !check_rights(R_SERVER))
return
if(!task)
@@ -99,7 +99,7 @@
if(last_editor)
output += " Last edit by [last_editor] (Click here to see edit log)"
output += " [memotext] "
- if(!output)
+ if(!output && !silent)
src << "No memos found in database."
return
src << output
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 236fbe42779..ae6ea3c4aae 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -42,6 +42,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
if("spawn","create") rights |= R_SPAWN
if("mod") rights |= R_MOD
if("mentor") rights |= R_MENTOR
+ if("proccall") rights |= R_PROCCALL
admin_ranks[rank] = rights
previous_rights = rights
diff --git a/code/modules/admin/admin_report.dm b/code/modules/admin/admin_report.dm
index b0f43741d02..89b267cd348 100644
--- a/code/modules/admin/admin_report.dm
+++ b/code/modules/admin/admin_report.dm
@@ -118,7 +118,7 @@ client/proc/display_admin_reports()
usr << browse(output, "window=news;size=600x400")
-client/proc/Report(mob/M as mob in world)
+client/proc/Report(mob/M as mob in view())
set category = "Admin"
if(!src.holder)
return
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 839634b2887..e2b26e7c491 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -69,11 +69,13 @@ var/list/admin_verbs_admin = list(
/client/proc/alt_check,
/client/proc/secrets,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
- /client/proc/change_human_appearance_self /* Allows the human-based mob itself change its basic appearance */
+ /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
+ /client/proc/debug_variables
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
- /client/proc/jobbans
+ /client/proc/jobbans,
+ /client/proc/stickybanpanel
)
var/list/admin_verbs_sounds = list(
/client/proc/play_local_sound,
@@ -139,8 +141,6 @@ var/list/admin_verbs_debug = list(
/client/proc/reload_admins,
/client/proc/restart_controller,
/client/proc/enable_debug_verbs,
- /client/proc/callproc,
- /client/proc/callproc_datum,
/client/proc/toggledebuglogs,
/client/proc/qdel_toggle,
/client/proc/gc_dump_hdl,
@@ -179,12 +179,16 @@ var/list/admin_verbs_mod = list(
/client/proc/jobbans,
/client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
)
-
var/list/admin_verbs_mentor = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_pm_by_key_panel /*admin-pm list by key*/
)
+var/list/admin_verbs_proccall = list (
+ /client/proc/callproc,
+ /client/proc/callproc_datum,
+ /client/proc/SDQL2_query
+)
/client/proc/add_admin_verbs()
if(holder)
@@ -203,6 +207,7 @@ var/list/admin_verbs_mentor = list(
if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
if(holder.rights & R_MOD) verbs += admin_verbs_mod
if(holder.rights & R_MENTOR) verbs += admin_verbs_mentor
+ if(holder.rights & R_PROCCALL) verbs += admin_verbs_proccall
/client/proc/remove_admin_verbs()
verbs.Remove(
@@ -221,6 +226,7 @@ var/list/admin_verbs_mentor = list(
admin_verbs_spawn,
admin_verbs_mod,
admin_verbs_mentor,
+ admin_verbs_proccall,
admin_verbs_show_debug_verbs,
/client/proc/readmin,
)
@@ -566,7 +572,7 @@ var/list/admin_verbs_mentor = list(
log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
message_admins("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
-/client/proc/make_sound(var/obj/O in world) // -- TLE
+/client/proc/make_sound(var/obj/O in view()) // -- TLE
set category = "Event"
set name = "Make Sound"
set desc = "Display a message to everyone who can hear the target"
@@ -635,7 +641,7 @@ var/list/admin_verbs_mentor = list(
set name = "De-admin self"
set category = "Admin"
- if(!check_rights(R_ADMIN|R_MOD))
+ if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
return
log_admin("[key_name(usr)] deadmined themself.")
diff --git a/code/modules/admin/machine_upgrade.dm b/code/modules/admin/machine_upgrade.dm
index 9f2039fdd0f..a0e97c4ae7b 100644
--- a/code/modules/admin/machine_upgrade.dm
+++ b/code/modules/admin/machine_upgrade.dm
@@ -1,10 +1,21 @@
/proc/machine_upgrade(obj/machinery/M in world)
set name = "Tweak Component Ratings"
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ if(!istype(M))
+ usr << "This can only be used on subtypes of /obj/machinery."
+ return
+
var/new_rating = input("Enter new rating:","Num") as num
- if(new_rating && M.component_parts)
+ if(!isnull(new_rating) && M.component_parts)
for(var/obj/item/weapon/stock_parts/P in M.component_parts)
P.rating = new_rating
M.RefreshParts()
+
+ message_admins("[key_name_admin(usr)] has set the component rating of [M] to [new_rating]")
+ log_admin("[key_name(usr)] has set the component rating of [M] to [new_rating]")
feedback_add_details("admin_verb","MU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm
index e53d4644c33..19ca9ef9b4f 100644
--- a/code/modules/admin/permissionverbs/permissionedit.dm
+++ b/code/modules/admin/permissionverbs/permissionedit.dm
@@ -2,11 +2,13 @@
set category = "Admin"
set name = "Permissions Panel"
set desc = "Edit admin permissions"
- if(!check_rights(R_PERMISSIONS)) return
+ if(!check_rights(R_PERMISSIONS))
+ return
usr.client.holder.edit_admin_permissions()
/datum/admins/proc/edit_admin_permissions()
- if(!check_rights(R_PERMISSIONS)) return
+ if(!check_rights(R_PERMISSIONS))
+ return
var/output = {"
@@ -55,8 +57,7 @@
if(!usr.client)
return
- if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
- usr << "\red You do not have permission to do this!"
+ if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
@@ -100,13 +101,13 @@
usr << "\blue Admin rank changed."
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
- if(config.admin_legacy_system) return
+ if(config.admin_legacy_system)
+ return
if(!usr.client)
return
- if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
- usr << "\red You do not have permission to do this!"
+ if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
new file mode 100644
index 00000000000..474b7c76265
--- /dev/null
+++ b/code/modules/admin/stickyban.dm
@@ -0,0 +1,211 @@
+/datum/admins/proc/stickyban(action,data)
+ if(!check_rights(R_BAN))
+ return
+
+ switch (action)
+ if ("show")
+ stickyban_show()
+ return
+ if ("add")
+ var/list/ban = list()
+ var/ckey
+ ban["admin"] = usr.key
+ ban["type"] = list("sticky")
+ ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
+
+ if (data["ckey"])
+ ckey = ckey(data["ckey"])
+ else
+ ckey = input(usr,"Ckey","Ckey","") as text|null
+ if (!ckey)
+ return
+ ckey = ckey(ckey)
+ if (get_stickyban_from_ckey(ckey))
+ usr << "Error: Can not add a stickyban: User already has a current sticky ban"
+
+ if (data["reason"])
+ ban["message"] = data["reason"]
+ else
+ var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null
+ if (!reason)
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban", ckey, list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+ message_admins("[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+
+ if ("remove")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
+ return
+ if (!get_stickyban_from_ckey(ckey))
+ usr << "Error: The ban disappeared."
+ return
+ world.SetConfig("ban", ckey, null)
+
+ log_admin("[key_name(usr)] removed [ckey]'s stickyban")
+ message_admins("[key_name_admin(usr)] removed [ckey]'s stickyban")
+
+ if ("remove_alt")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ if (!data["alt"])
+ return
+ var/alt = ckey(data["alt"])
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+
+ var/found = 0
+ //we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] is not linked to [ckey]'s sticky ban!"
+ return
+
+ if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
+ return
+
+ //we have to do this again incase something changes
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+
+ found = 0
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ ban["keys"] -= key
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] link to [ckey]'s sticky ban disappeared."
+ return
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+ message_admins("[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+
+ if ("edit")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ var/oldreason = ban["message"]
+ var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
+ if (!reason || reason == oldreason)
+ return
+ //we have to do this again incase something changed while we waited for input
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+ message_admins("[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+
+ spawn(10)
+ stickyban_show()
+
+/datum/admins/proc/stickyban_gethtml(ckey, ban)
+ . = "\[-\][ckey] "
+ . += "[ban["message"]] \[Edit\] "
+ if (ban["admin"])
+ . += "[ban["admin"]] "
+ else
+ . += "LEGACY "
+ . += "Caught keys \n"
+ for (var/key in ban["keys"])
+ if (ckey(key) == ckey)
+ continue
+ . += "
\[+\]
+ [banhtml]
+
+ "}
+ usr << browse(html,"window=stickybans;size=700x400")
+
+/proc/get_stickyban_from_ckey(var/ckey)
+ if (!ckey)
+ return null
+ ckey = ckey(ckey)
+ . = null
+ for (var/key in world.GetConfig("ban"))
+ if (ckey(key) == ckey)
+ . = stickyban2list(world.GetConfig("ban",key))
+ break
+
+/proc/stickyban2list(var/ban)
+ if (!ban)
+ return null
+ . = params2list(ban)
+ .["keys"] = text2list(.["keys"], ",")
+ .["type"] = text2list(.["type"], ",")
+ .["IP"] = text2list(.["IP"], ",")
+ .["computer_id"] = text2list(.["computer_id"], ",")
+
+/proc/list2stickyban(var/list/ban)
+ if (!ban || !islist(ban))
+ return null
+ . = ban.Copy()
+ if (.["keys"])
+ .["keys"] = list2text(.["keys"], ",")
+ if (.["type"])
+ .["type"] = list2text(.["type"], ",")
+ if (.["IP"])
+ .["IP"] = list2text(.["IP"], ",")
+ if (.["computer_id"])
+ .["computer_id"] = list2text(.["computer_id"], ",")
+ . = list2params(.)
+
+/client/proc/stickybanpanel()
+ set name = "Sticky Ban Panel"
+ set category = "Admin"
+
+ if(!check_rights(R_BAN))
+ return
+
+ holder.stickyban_show()
+
\ No newline at end of file
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index cff4e611d65..b922b4979c8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -25,6 +25,9 @@
message_admins("[key_name_admin(usr)] rejected [key_name_admin(C.mob)]'s admin help")
log_admin("[key_name(usr)] rejected [key_name(C.mob)]'s admin help")
+
+ if(href_list["stickyban"])
+ stickyban(href_list["stickyban"],href_list)
if(href_list["makeAntag"])
switch(href_list["makeAntag"])
@@ -123,6 +126,17 @@
return
banduration = null
banjob = null
+ if(BANTYPE_ADMIN_PERMA)
+ if(!banckey || !banreason)
+ usr << "Not enough parameters (Requires ckey and reason)"
+ return
+ banduration = null
+ banjob = null
+ if(BANTYPE_ADMIN_TEMP)
+ if(!banckey || !banreason || !banduration)
+ usr << "Not enough parameters (Requires ckey, reason and duration)"
+ return
+ banjob = null
var/mob/playermob
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
new file mode 100644
index 00000000000..5fcfa3a12c3
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -0,0 +1,477 @@
+// Examples
+/*
+ -- Will call the proc for all computers in the world, thats dir is 2.
+ CALL ex_act(1) ON /obj/machinery/computer IN world WHERE dir == 2
+ -- Will open a window with a list of all the closets in the world, with a link to VV them.
+ SELECT /obj/structure/closet/secure_closet/security/cargo IN world WHERE icon_off == "secoff"
+ -- Will change all the tube lights to green
+ UPDATE /obj/machinery/light IN world SET color = "#0F0" WHERE icon_state == "tube1"
+ -- Will delete all pickaxes. "IN world" is not required.
+ DELETE /obj/item/weapon/pickaxe
+ -- Will flicker the lights once, then turn all mobs green. The semicolon is important to separate the consecutive querys, but is not required for standard one-query use
+ CALL flicker(1) ON /obj/machinery/light; UPDATE /mob SET color = "#00cc00"
+
+ --You can use operators other than ==, such as >, <=, != and etc..
+
+*/
+
+/client/proc/SDQL2_query(query_text as message)
+ set category = "Debug"
+
+ if(!check_rights(R_PROCCALL)) //Shouldn't happen... but just to be safe.
+ message_admins("ERROR: Non-admin [key_name_admin(usr)] attempted to execute a SDQL query!")
+ log_admin("Non-admin [key_name(usr)] attempted to execute a SDQL query!")
+
+ if(!query_text || length(query_text) < 1)
+ return
+
+ //world << query_text
+
+ var/list/query_list = SDQL2_tokenize(query_text)
+
+ if(!query_list || query_list.len < 1)
+ return
+
+ var/list/querys = SDQL_parse(query_list)
+
+ if(!querys || querys.len < 1)
+ return
+
+ var/query_log = "executed SDQL query: \"[query_text]\"."
+ message_admins("[key_name_admin(usr)] [query_log]")
+ query_log = "[key_name(usr)] [query_log]"
+ log_admin(query_log)
+
+ for(var/list/query_tree in querys)
+ var/list/from_objs = list()
+ var/list/select_types = list()
+
+ switch(query_tree[1])
+ if("explain")
+ SDQL_testout(query_tree["explain"])
+ return
+
+ if("call")
+ if("on" in query_tree)
+ select_types = query_tree["on"]
+ else
+ return
+
+ if("select", "delete", "update")
+ select_types = query_tree[query_tree[1]]
+
+ from_objs = SDQL_from_objs(query_tree["from"])
+
+ var/list/objs = list()
+
+ for(var/type in select_types)
+ var/char = copytext(type, 1, 2)
+
+ if(char == "/" || char == "*")
+ for(var/from in from_objs)
+ objs += SDQL_get_all(type, from)
+
+ else if(char == "'" || char == "\"")
+ objs += locate(copytext(type, 2, length(type)))
+
+ if("where" in query_tree)
+ var/objs_temp = objs
+ objs = list()
+ for(var/datum/d in objs_temp)
+ if(SDQL_expression(d, query_tree["where"]))
+ objs += d
+
+ switch(query_tree[1])
+ if("call")
+ var/list/call_list = query_tree["call"]
+ var/list/args_list = query_tree["args"]
+
+ for(var/datum/d in objs)
+ for(var/v in call_list)
+ // To stop any procs which sleep from executing slowly.
+ if(d)
+ if(hascall(d, v))
+ spawn() call(d, v)(arglist(args_list)) // Spawn in case the function sleeps.
+
+ if("delete")
+ for(var/datum/d in objs)
+ del d
+
+ if("select")
+ var/text = ""
+ for(var/datum/t in objs)
+ text += "\ref[t]"
+ if(istype(t, /atom))
+ var/atom/a = t
+
+ if(a.x)
+ text += ": [t] at ([a.x], [a.y], [a.z]) "
+
+ else if(a.loc && a.loc.x)
+ text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z]) "
+
+ else
+ text += ": [t] "
+
+ else
+ text += ": [t] "
+
+ usr << browse(text, "window=SDQL-result")
+
+ if("update")
+ if("set" in query_tree)
+ var/list/set_list = query_tree["set"]
+ for(var/datum/d in objs)
+ var/list/vals = list()
+ for(var/v in set_list)
+ if(v in d.vars)
+ vals += v
+ vals[v] = SDQL_expression(d, set_list[v])
+
+ if(istype(d, /turf))
+ for(var/v in vals)
+ if(v == "x" || v == "y" || v == "z")
+ continue
+
+ d.vars[v] = vals[v]
+
+ else
+ for(var/v in vals)
+ d.vars[v] = vals[v]
+
+/proc/SDQL_parse(list/query_list)
+ var/datum/SDQL_parser/parser = new()
+ var/list/querys = list()
+ var/list/query_tree = list()
+ var/pos = 1
+ var/querys_pos = 1
+ var/do_parse = 0
+
+ for(var/val in query_list)
+ if(val == ";")
+ do_parse = 1
+ else if(pos >= query_list.len)
+ query_tree += val
+ do_parse = 1
+
+ if(do_parse)
+ parser.query = query_tree
+ var/list/parsed_tree
+ parsed_tree = parser.parse()
+ if(parsed_tree.len > 0)
+ querys.len = querys_pos
+ querys[querys_pos] = parsed_tree
+ querys_pos++
+ else //There was an error so don't run anything, and tell the user which query has errored.
+ usr << "Parsing error on [querys_pos]\th query. Nothing was executed."
+ return list()
+ query_tree = list()
+ do_parse = 0
+ else
+ query_tree += val
+ pos++
+
+ qdel(parser)
+
+ return querys
+
+
+
+/proc/SDQL_testout(list/query_tree, indent = 0)
+ var/spaces = ""
+ for(var/s = 0, s < indent, s++)
+ spaces += " "
+
+ for(var/item in query_tree)
+ if(istype(item, /list))
+ usr << "[spaces]("
+ SDQL_testout(item, indent + 1)
+ usr << "[spaces])"
+
+ else
+ usr << "[spaces][item]"
+
+ if(!isnum(item) && query_tree[item])
+
+ if(istype(query_tree[item], /list))
+ usr << "[spaces] ("
+ SDQL_testout(query_tree[item], indent + 2)
+ usr << "[spaces] )"
+
+ else
+ usr << "[spaces] [query_tree[item]]"
+
+/proc/SDQL_from_objs(list/tree)
+ if("world" in tree)
+ return list(world)
+
+ var/list/out = list()
+
+ for(var/type in tree)
+ var/char = copytext(type, 1, 2)
+
+ if(char == "/")
+ out += SDQL_get_all(type, world)
+
+ else if(char == "'" || char == "\"")
+ out += locate(copytext(type, 2, length(type)))
+
+ return out
+
+/proc/SDQL_get_all(type, location)
+ var/list/out = list()
+
+ if(type == "*")
+ for(var/datum/d in location)
+ out += d
+
+ return out
+
+ type = text2path(type)
+
+ if(ispath(type, /mob))
+ for(var/mob/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /turf))
+ for(var/turf/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /obj))
+ for(var/obj/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /area))
+ for(var/area/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /atom))
+ for(var/atom/d in location)
+ if(istype(d, type))
+ out += d
+
+ else
+ for(var/datum/d in location)
+ if(istype(d, type))
+ out += d
+
+ return out
+
+/proc/SDQL_expression(datum/object, list/expression, start = 1)
+ var/result = 0
+ var/val
+
+ for(var/i = start, i <= expression.len, i++)
+ var/op = ""
+
+ if(i > start)
+ op = expression[i]
+ i++
+
+ var/list/ret = SDQL_value(object, expression, i)
+ val = ret["val"]
+ i = ret["i"]
+
+ if(op != "")
+ switch(op)
+ if("+")
+ result += val
+ if("-")
+ result -= val
+ if("*")
+ result *= val
+ if("/")
+ result /= val
+ if("&")
+ result &= val
+ if("|")
+ result |= val
+ if("^")
+ result ^= val
+ if("=", "==")
+ result = (result == val)
+ if("!=", "<>")
+ result = (result != val)
+ if("<")
+ result = (result < val)
+ if("<=")
+ result = (result <= val)
+ if(">")
+ result = (result > val)
+ if(">=")
+ result = (result >= val)
+ if("and", "&&")
+ result = (result && val)
+ if("or", "||")
+ result = (result || val)
+ else
+ usr << "SDQL2: Unknown op [op]"
+ result = null
+ else
+ result = val
+
+ return result
+
+/proc/SDQL_value(datum/object, list/expression, start = 1)
+ var/i = start
+ var/val = null
+
+ if(i > expression.len)
+ return list("val" = null, "i" = i)
+
+ if(istype(expression[i], /list))
+ val = SDQL_expression(object, expression[i])
+
+ else if(expression[i] == "!")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = !ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "~")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = ~ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "-")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = -ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "null")
+ val = null
+
+ else if(isnum(expression[i]))
+ val = expression[i]
+
+ else if(copytext(expression[i], 1, 2) in list("'", "\""))
+ val = copytext(expression[i], 2, length(expression[i]))
+
+ else
+ val = SDQL_var(object, expression, i)
+ i = expression.len
+
+ return list("val" = val, "i" = i)
+
+/proc/SDQL_var(datum/object, list/expression, start = 1)
+
+ if(expression[start] in object.vars)
+
+ if(start < expression.len && expression[start + 1] == ".")
+ return SDQL_var(object.vars[expression[start]], expression[start + 2])
+
+ else
+ return object.vars[expression[start]]
+
+ else
+ return null
+
+/proc/SDQL2_tokenize(query_text)
+
+ var/list/whitespace = list(" ", "\n", "\t")
+ var/list/single = list("(", ")", ",", "+", "-", ".", ";")
+ var/list/multi = list(
+ "=" = list("", "="),
+ "<" = list("", "=", ">"),
+ ">" = list("", "="),
+ "!" = list("", "="))
+
+ var/word = ""
+ var/list/query_list = list()
+ var/len = length(query_text)
+
+ for(var/i = 1, i <= len, i++)
+ var/char = copytext(query_text, i, i + 1)
+
+ if(char in whitespace)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ else if(char in single)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ query_list += char
+
+ else if(char in multi)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ var/char2 = copytext(query_text, i + 1, i + 2)
+
+ if(char2 in multi[char])
+ query_list += "[char][char2]"
+ i++
+
+ else
+ query_list += char
+
+ else if(char == "'")
+ if(word != "")
+ usr << "SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again."
+ return null
+
+ word = "'"
+
+ for(i++, i <= len, i++)
+ char = copytext(query_text, i, i + 1)
+
+ if(char == "'")
+ if(copytext(query_text, i + 1, i + 2) == "'")
+ word += "'"
+ i++
+
+ else
+ break
+
+ else
+ word += char
+
+ if(i > len)
+ usr << "SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"[query_text]\". Please check your syntax, and try again."
+ return null
+
+ query_list += "[word]'"
+ word = ""
+
+ else if(char == "\"")
+ if(word != "")
+ usr << "SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again."
+ return null
+
+ word = "\""
+
+ for(i++, i <= len, i++)
+ char = copytext(query_text, i, i + 1)
+
+ if(char == "\"")
+ if(copytext(query_text, i + 1, i + 2) == "'")
+ word += "\""
+ i++
+
+ else
+ break
+
+ else
+ word += char
+
+ if(i > len)
+ usr << "SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"[query_text]\". Please check your syntax, and try again."
+ return null
+
+ query_list += "[word]\""
+ word = ""
+
+ else
+ word += char
+
+ if(word != "")
+ query_list += word
+ return query_list
+
\ No newline at end of file
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
new file mode 100644
index 00000000000..007453a980d
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -0,0 +1,530 @@
+//I'm pretty sure that this is a recursive [s]descent[/s] ascent parser.
+//Spec
+//////////
+//
+// query : select_query | delete_query | update_query | call_query | explain
+// explain : 'EXPLAIN' query
+//
+// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
+// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
+//
+// select_list : select_item [',' select_list]
+// select_item : '*' | select_function | object_type
+// select_function : count_function
+// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
+//
+// from_list : from_item [',' from_list]
+// from_item : 'world' | object_type
+//
+// call_function : ['(' [arguments] ')']
+// arguments : expression [',' arguments]
+//
+// object_type : | string
+//
+// assignments : assignment, [',' assignments]
+// assignment : '=' expression
+// variable : | '.' variable
+//
+// bool_expression : expression comparitor expression [bool_operator bool_expression]
+// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
+// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
+// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+// value : variable | string | number | 'null'
+// unary_operator : '!' | '-' | '~'
+// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
+// bool_operator : 'AND' | '&&' | 'OR' | '||'
+//
+// string : ''' ''' | '"' '"'
+// number :
+//
+//////////
+
+/datum/SDQL_parser
+ var/query_type
+ var/error = 0
+
+ var/list/query
+ var/list/tree
+
+ var/list/select_functions = list("count")
+ var/list/boolean_operators = list("and", "or", "&&", "||")
+ var/list/unary_operators = list("!", "-", "~")
+ var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
+ var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
+
+/datum/SDQL_parser/New(query_list)
+ query = query_list
+
+/datum/SDQL_parser/proc/parse_error(error_message)
+ error = 1
+ usr << "SQDL2 Parsing Error: [error_message]"
+ return query.len + 1
+
+/datum/SDQL_parser/proc/parse()
+ tree = list()
+ query(1, tree)
+
+ if(error)
+ return list()
+ else
+ return tree
+
+/datum/SDQL_parser/proc/token(i)
+ if(i <= query.len)
+ return query[i]
+
+ else
+ return null
+
+/datum/SDQL_parser/proc/tokens(i, num)
+ if(i + num <= query.len)
+ return query.Copy(i, i + num)
+
+ else
+ return null
+
+/datum/SDQL_parser/proc/tokenl(i)
+ return lowertext(token(i))
+
+/datum/SDQL_parser/proc
+
+//query: select_query | delete_query | update_query
+ query(i, list/node)
+ query_type = tokenl(i)
+
+ switch(query_type)
+ if("select")
+ select_query(i, node)
+
+ if("delete")
+ delete_query(i, node)
+
+ if("update")
+ update_query(i, node)
+
+ if("call")
+ call_query(i, node)
+
+ if("explain")
+ node += "explain"
+ node["explain"] = list()
+ query(i + 1, node["explain"])
+
+
+// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+ select_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "select"
+ node["select"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+ delete_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "delete"
+ node["delete"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
+ update_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "update"
+ node["update"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) != "set")
+ i = parse_error("UPDATE has misplaced SET")
+
+ var/list/set_assignments = list()
+ i = assignments(i + 1, set_assignments)
+
+ node += "set"
+ node["set"] = set_assignments
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
+ call_query(i, list/node)
+ var/list/func = list()
+ var/list/arguments = list()
+ i = call_function(i + 1, func, arguments)
+
+ node += "call"
+ node["call"] = func
+ node["args"] = arguments
+
+ if(tokenl(i) != "on")
+ return i
+
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "on"
+ node["on"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//select_list: select_item [',' select_list]
+ select_list(i, list/node)
+ i = select_item(i, node)
+
+ if(token(i) == ",")
+ i = select_list(i + 1, node)
+
+ return i
+
+
+//from_list: from_item [',' from_list]
+ from_list(i, list/node)
+ i = from_item(i, node)
+
+ if(token(i) == ",")
+ i = from_list(i + 1, node)
+
+ return i
+
+
+//assignments: assignment, [',' assignments]
+ assignments(i, list/node)
+ i = assignment(i, node)
+
+ if(token(i) == ",")
+ i = assignments(i + 1, node)
+
+ return i
+
+
+//select_item: '*' | select_function | object_type
+ select_item(i, list/node)
+
+ if(token(i) == "*")
+ node += "*"
+ i++
+
+ else if(tokenl(i) in select_functions)
+ i = select_function(i, node)
+
+ else
+ i = object_type(i, node)
+
+ return i
+
+
+//from_item: 'world' | object_type
+ from_item(i, list/node)
+
+ if(token(i) == "world")
+ node += "world"
+ i++
+
+ else
+ i = object_type(i, node)
+
+ return i
+
+
+//bool_expression: expression [bool_operator bool_expression]
+ bool_expression(i, list/node)
+
+ var/list/bool = list()
+ i = expression(i, bool)
+
+ node[++node.len] = bool
+
+ if(tokenl(i) in boolean_operators)
+ i = bool_operator(i, node)
+ i = bool_expression(i, node)
+
+ return i
+
+
+//assignment: '=' expression
+ assignment(i, list/node)
+
+ node += token(i)
+
+ if(token(i + 1) == "=")
+ var/varname = token(i)
+ node[varname] = list()
+
+ i = expression(i + 2, node[varname])
+
+ else
+ parse_error("Assignment expected, but no = found")
+
+ return i
+
+
+//variable: | '.' variable
+ variable(i, list/node)
+ var/list/L = list(token(i))
+ node[++node.len] = L
+
+ if(token(i + 1) == ".")
+ L += "."
+ i = variable(i + 2, L)
+
+ else
+ i++
+
+ return i
+
+
+//object_type: | string
+ object_type(i, list/node)
+
+ if(copytext(token(i), 1, 2) == "/")
+ node += token(i)
+
+ else
+ i = string(i, node)
+
+ return i + 1
+
+
+//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+ comparitor(i, list/node)
+
+ if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
+ node += token(i)
+
+ else
+ parse_error("Unknown comparitor [token(i)]")
+
+ return i + 1
+
+
+//bool_operator: 'AND' | '&&' | 'OR' | '||'
+ bool_operator(i, list/node)
+
+ if(tokenl(i) in list("and", "or", "&&", "||"))
+ node += token(i)
+
+ else
+ parse_error("Unknown comparitor [token(i)]")
+
+ return i + 1
+
+
+//string: ''' ''' | '"' '"'
+ string(i, list/node)
+
+ if(copytext(token(i), 1, 2) in list("'", "\""))
+ node += token(i)
+
+ else
+ parse_error("Expected string but found '[token(i)]'")
+
+ return i + 1
+
+
+//call_function: ['(' [arguments] ')']
+ call_function(i, list/node, list/arguments)
+ if(length(tokenl(i)))
+ node += token(i++)
+ if(token(i) != "(")
+ parse_error("Expected ( but found '[token(i)]'")
+ else if(token(i + 1) != ")")
+ do
+ i = expression(i + 1, arguments)
+ if(token(i) == ",")
+ continue
+ while(token(i) && token(i) != ")")
+ else
+ i++
+ else
+ parse_error("Expected a function but found nothing")
+ return i + 1
+
+
+//select_function: count_function
+ select_function(i, list/node)
+
+ parse_error("Sorry, function calls aren't available yet")
+
+ return i
+
+
+//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
+ expression(i, list/node)
+
+ if(token(i) in unary_operators)
+ i = unary_expression(i, node)
+
+ else if(token(i) == "(")
+ var/list/expr = list()
+
+ i = expression(i + 1, expr)
+
+ if(token(i) != ")")
+ parse_error("Missing ) at end of expression.")
+
+ else
+ i++
+
+ node[++node.len] = expr
+
+ else
+ i = value(i, node)
+
+ if(token(i) in binary_operators)
+ i = binary_operator(i, node)
+ i = expression(i, node)
+
+ else if(token(i) in comparitors)
+ i = binary_operator(i, node)
+
+ var/list/rhs = list()
+ i = expression(i, rhs)
+
+ node[++node.len] = rhs
+
+
+ return i
+
+
+//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
+ unary_expression(i, list/node)
+
+ if(token(i) in unary_operators)
+ var/list/unary_exp = list()
+
+ unary_exp += token(i)
+ i++
+
+ if(token(i) in unary_operators)
+ i = unary_expression(i, unary_exp)
+
+ else if(token(i) == "(")
+ var/list/expr = list()
+
+ i = expression(i + 1, expr)
+
+ if(token(i) != ")")
+ parse_error("Missing ) at end of expression.")
+
+ else
+ i++
+
+ unary_exp[++unary_exp.len] = expr
+
+ else
+ i = value(i, unary_exp)
+
+ node[++node.len] = unary_exp
+
+
+ else
+ parse_error("Expected unary operator but found '[token(i)]'")
+
+ return i
+
+
+//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
+ binary_operator(i, list/node)
+
+ if(token(i) in (binary_operators + comparitors))
+ node += token(i)
+
+ else
+ parse_error("Unknown binary operator [token(i)]")
+
+ return i + 1
+
+
+//value: variable | string | number | 'null'
+ value(i, list/node)
+
+ if(token(i) == "null")
+ node += "null"
+ i++
+
+ else if(isnum(text2num(token(i))))
+ node += text2num(token(i))
+ i++
+
+ else if(copytext(token(i), 1, 2) in list("'", "\""))
+ i = string(i, node)
+
+ else
+ i = variable(i, node)
+
+ return i
+/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 69999e89940..198e5c8a042 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -92,7 +92,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
//send this msg to all admins
var/admin_number_afk = 0
var/list/modholders = list()
- var/list/banholders = list()
var/list/adminholders = list()
for(var/client/X in admins)
if(check_rights(R_MOD|R_MENTOR, 0, X.mob))
@@ -103,8 +102,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(X.is_afk())
admin_number_afk++
adminholders += X
- if(check_rights(R_BAN, 0, X.mob))
- banholders += X
switch(selected_type)
if("Question")
@@ -113,15 +110,14 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
- else
- if(adminholders.len)
- for(var/client/X in adminholders)
- if(X.prefs.sound & SOUND_ADMINHELP)
- X << 'sound/effects/adminhelp.ogg'
- X << msg
- else if("Player Complaint")
- if(banholders.len)
- for(var/client/X in banholders)
+ if(adminholders.len)
+ for(var/client/X in adminholders)
+ if(X.prefs.sound & SOUND_ADMINHELP)
+ X << 'sound/effects/adminhelp.ogg'
+ X << msg
+ if("Player Complaint")
+ if(adminholders.len)
+ for(var/client/X in adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 8277b49081d..93cff752e0b 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -214,37 +214,22 @@
*/
log_admin("PM: [key_name(src)]->[key_name(C)]: [msg]")
-
-
- var/list/modholders = list()
- var/list/banholders = list()
- var/list/adminholders = list()
- for(var/client/X in admins)
- if(check_rights(R_MOD|R_MENTOR, 0, X.mob))
- modholders += X
- if(check_rights(R_ADMIN, 0, X.mob))
- adminholders += X
- if(check_rights(R_BAN, 0, X.mob))
- banholders += X
-
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
//check client/X is an admin and isn't the sender or recipient
if(X == C || X == src)
continue
- if(X.key!=key && X.key!=C.key)
+ if(X.key != key && X.key != C.key)
switch(type)
if("Question")
- if(check_rights(R_MOD|R_MENTOR, 0, X.mob))
- X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]" //inform X
- else if(!modholders.len && check_rights(R_ADMIN, 0, X.mob))
- X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]" //Any admins in backup of mod question
+ if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob))
+ X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]"
if("Player Complaint")
- if(check_rights(R_BAN, 0, X.mob))
- X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]" //There should always be at least 1 person with +BAN on
+ if(check_rights(R_ADMIN|R_MOD, 0, X.mob))
+ X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]"
else
if(check_rights(R_ADMIN|R_MOD, 0, X.mob))
- X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]" //If there's no type, send to all admins.
+ X << "[type]: [key_name(src, X, 0, type)]->[key_name(C, X, 0, type)]: \blue [msg]"
/client/proc/cmd_admin_irc_pm()
if(prefs.muted & MUTE_ADMINHELP)
diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm
deleted file mode 100644
index 18a796a0b08..00000000000
--- a/code/modules/admin/verbs/check_customitem_activity.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-var/checked_for_inactives = 0
-var/inactive_keys = "None "
-
-/client/proc/check_customitem_activity()
- set category = "Admin"
- set name = "Check activity of players with custom items"
-
- var/dat = "Inactive players with custom items "
- dat += " "
- dat += "The list below contains players with custom items that have not logged\
- in for the past two months, or have not logged in since this system was implemented.\
- This system requires the feedback SQL database to be properly setup and linked. "
- dat += " "
- dat += "Populating this list is done automatically, but must be manually triggered on a per\
- round basis. Populating the list may cause a lag spike, so use it sparingly. "
- dat += ""
- if(checked_for_inactives)
- dat += inactive_keys
- dat += ""
- dat += "This system was implemented on March 1 2013, and the database a few days before that. Root server access is required to add or disable access to specific custom items. "
- else
- dat += "Populate list (requires an active database connection) "
-
- usr << browse(dat, "window=inactive_customitems;size=600x480")
-
-/proc/populate_inactive_customitems_list(var/client/C)
- //set background = 1
-
- if(checked_for_inactives)
- return
-
- establish_db_connection()
- if(!dbcon.IsConnected())
- return
-
- //grab all ckeys associated with custom items
- var/list/ckeys_with_customitems = list()
-
- var/file = file2text("config/custom_items.txt")
- var/lines = text2list(file, "\n")
-
- for(var/line in lines)
- // split & clean up
- var/list/Entry = text2list(line, ":")
- for(var/i = 1 to Entry.len)
- Entry[i] = trim(Entry[i])
-
- if(Entry.len < 1)
- continue
-
- var/cur_key = Entry[1]
- if(!ckeys_with_customitems.Find(cur_key))
- ckeys_with_customitems.Add(cur_key)
-
- //run a query to get all ckeys inactive for over 2 months
- var/list/inactive_ckeys = list()
- if(ckeys_with_customitems.len)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM [format_table_name("player")] WHERE datediff(Now(), lastseen) > 60")
- query_inactive.Execute()
- while(query_inactive.NextRow())
- var/cur_ckey = query_inactive.item[1]
- //if the ckey has a custom item attached, output it
- if(ckeys_with_customitems.Find(cur_ckey))
- ckeys_with_customitems.Remove(cur_ckey)
- inactive_ckeys[cur_ckey] = "last seen on [query_inactive.item[2]]"
-
- //if there are ckeys left over, check whether they have a database entry at all
- if(ckeys_with_customitems.len)
- for(var/cur_ckey in ckeys_with_customitems)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[cur_ckey]'")
- query_inactive.Execute()
- if(!query_inactive.RowCount())
- inactive_ckeys += cur_ckey
-
- if(inactive_ckeys.len)
- inactive_keys = ""
- for(var/cur_key in inactive_ckeys)
- if(inactive_ckeys[cur_key])
- inactive_keys += "[cur_key] - [inactive_ckeys[cur_key]] "
- else
- inactive_keys += "[cur_key] - no database entry "
-
- checked_for_inactives = 1
- if(C)
- C.check_customitem_activity()
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 453e6d81f69..b448099f635 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -2,31 +2,33 @@
set category = "Special Verbs"
set name = "Dsay" //Gave this shit a shorter name so you only have to time out "dsay" rather than "dead say" to use it --NeoFite
set hidden = 1
- if(!src.holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_ADMIN|R_MOD))
return
+
if(!src.mob)
return
+
if(prefs.muted & MUTE_DEADCHAT)
- src << "\red You cannot send DSAY messages (muted)."
+ src << "You cannot send DSAY messages (muted)."
return
if(!(prefs.toggles & CHAT_DEAD))
- src << "\red You have deadchat muted."
+ src << "You have deadchat muted."
return
- if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
+ if (handle_spam_prevention(msg,MUTE_DEADCHAT))
return
var/stafftype = null
- if (src.holder.rights & R_MENTOR)
+ if (check_rights(R_MENTOR, 0))
stafftype = "MENTOR"
- if (src.holder.rights & R_MOD)
+ if (check_rights(R_MOD, 0))
stafftype = "MOD"
- if (src.holder.rights & R_ADMIN)
+ if (check_rights(R_ADMIN, 0))
stafftype = "ADMIN"
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 2dd0e2adb71..8fc24a175cd 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -1,7 +1,9 @@
/client/proc/Debug2()
set category = "Debug"
set name = "Debug-Game"
- if(!check_rights(R_DEBUG)) return
+
+ if(!check_rights(R_DEBUG))
+ return
if(Debug2)
Debug2 = 0
@@ -28,7 +30,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Advanced ProcCall"
- if(!check_rights(R_DEBUG)) return
+ if(!check_rights(R_PROCCALL))
+ return
spawn(0)
var/target = null
@@ -80,11 +83,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!target)
usr << "Error: callproc(): owner of proc no longer exists."
return
+ message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
- log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
+ message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
+ log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
usr << "[procname] returned: [returnval ? returnval : "null"]"
@@ -94,7 +99,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Atom ProcCall"
- if(!check_rights(R_DEBUG))
+ if(!check_rights(R_PROCCALL))
return
var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
@@ -112,7 +117,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!A || !IsValidSrc(A))
usr << "Error: callproc_datum(): owner of proc no longer exists."
return
- log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
+ message_admins("[key_name_admin(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
+ log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
spawn()
var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
@@ -180,6 +186,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/Cell()
set category = "Debug"
set name = "Air Status in Location"
+
+ if(!check_rights(R_DEBUG))
+ return
+
if(!mob)
return
var/turf/T = mob.loc
@@ -201,6 +211,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_robotize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Robot"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -216,6 +229,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_animalize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Simple Animal"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -238,6 +254,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Event"
set name = "Make pAI"
set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI"
+
+ if(!check_rights(R_SPAWN))
+ return
var/list/available = list()
for(var/mob/C in mob_list)
@@ -264,6 +283,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_alienize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Alien"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -281,6 +303,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_slimeize(var/mob/M in mob_list)
set category = "Event"
set name = "Make slime"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -298,6 +323,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_super(var/mob/M in mob_list)
set category = "Event"
set name = "Make Superhero"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -312,102 +340,14 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
else
alert("Invalid mob")
-/*
-/client/proc/cmd_admin_monkeyize(var/mob/M in world)
- set category = "Event"
- set name = "Make Monkey"
-
- if(!ticker)
- alert("Wait until the game starts")
- return
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/target = M
- log_admin("[key_name(src)] is attempting to monkeyize [M.key].")
- spawn(10)
- target.monkeyize()
- else
- alert("Invalid mob")
-
-/client/proc/cmd_admin_changelinginize(var/mob/M in world)
- set category = "Event"
- set name = "Make Changeling"
-
- if(!ticker)
- alert("Wait until the game starts")
- return
- if(istype(M, /mob/living/carbon/human))
- log_admin("[key_name(src)] has made [M.key] a changeling.")
- spawn(10)
- M.absorbed_dna[M.real_name] = M.dna.Clone()
- M.make_changeling()
- if(M.mind)
- M.mind.special_role = "Changeling"
- else
- alert("Invalid mob")
-*/
-/*
-/client/proc/cmd_admin_abominize(var/mob/M in world)
- set category = null
- set name = "Make Abomination"
-
- usr << "Ruby Mode disabled. Command aborted."
- return
- if(!ticker)
- alert("Wait until the game starts.")
- return
- if(istype(M, /mob/living/carbon/human))
- log_admin("[key_name(src)] has made [M.key] an abomination.")
-
- // spawn(10)
- // M.make_abomination()
-
-*/
-/*
-/client/proc/make_cultist(var/mob/M in world) // -- TLE, modified by Urist
- set category = "Event"
- set name = "Make Cultist"
- set desc = "Makes target a cultist"
- if(!cultwords["travel"])
- runerandom()
- if(M)
- if(M.mind in ticker.mode.cult)
- return
- else
- if(alert("Spawn that person a tome?",,"Yes","No")=="Yes")
- M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie. A tome, a message from your new master, appears on the ground."
- new /obj/item/weapon/tome(M.loc)
- else
- M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie."
- var/glimpse=pick("1","2","3","4","5","6","7","8")
- switch(glimpse)
- if("1")
- M << "\red You remembered one thing from the glimpse... [cultwords["travel"]] is travel..."
- if("2")
- M << "\red You remembered one thing from the glimpse... [cultwords["blood"]] is blood..."
- if("3")
- M << "\red You remembered one thing from the glimpse... [cultwords["join"]] is join..."
- if("4")
- M << "\red You remembered one thing from the glimpse... [cultwords["hell"]] is Hell..."
- if("5")
- M << "\red You remembered one thing from the glimpse... [cultwords["destroy"]] is destroy..."
- if("6")
- M << "\red You remembered one thing from the glimpse... [cultwords["technology"]] is technology..."
- if("7")
- M << "\red You remembered one thing from the glimpse... [cultwords["self"]] is self..."
- if("8")
- M << "\red You remembered one thing from the glimpse... [cultwords["see"]] is see..."
-
- if(M.mind)
- M.mind.special_role = "Cultist"
- ticker.mode.cult += M.mind
- src << "Made [M] a cultist."
-*/
-
//TODO: merge the vievars version into this or something maybe mayhaps
/client/proc/cmd_debug_del_all()
set category = "Debug"
set name = "Del-All"
+ if(!check_rights(R_DEBUG))
+ return
+
// to prevent REALLY stupid deletions
var/blocked = list(/mob/living, /mob/living/carbon, /mob/living/carbon/human, /mob/dead, /mob/dead/observer, /mob/living/silicon, /mob/living/silicon/robot, /mob/living/silicon/ai)
var/hsbitem = input(usr, "Choose an object to delete.", "Delete:") as null|anything in subtypesof(/obj) + subtypesof(/mob) - blocked
@@ -422,6 +362,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_debug_make_powernets()
set category = "Debug"
set name = "Make Powernets"
+
+ if(!check_rights(R_DEBUG))
+ return
+
makepowernets()
log_admin("[key_name(src)] has remade the powernet. makepowernets() called.")
message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.", 0)
@@ -430,6 +374,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_grantfullaccess(var/mob/M in mob_list)
set category = "Admin"
set name = "Grant Full Access"
+
+ if(!check_rights(R_EVENT))
+ return
if (!ticker)
alert("Wait until the game starts")
@@ -463,7 +410,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set name = "Assume direct control"
set desc = "Direct intervention"
- if(!check_rights(R_DEBUG|R_ADMIN)) return
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
if(M.ckey)
if(alert("This mob is being controlled by [M.ckey]. Are you sure you wish to assume control of it? [M.ckey] will be made a ghost.",,"Yes","No") != "Yes")
return
@@ -482,6 +431,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_areatest()
set category = "Mapping"
set name = "Test areas"
+
+ if(!check_rights(R_DEBUG))
+ return
var/list/areas_all = list()
var/list/areas_with_APC = list()
@@ -570,9 +522,14 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in mob_list)
set category = "Event"
set name = "Select equipment"
+
+ if(!check_rights(R_EVENT))
+ return
+
if(!ishuman(M))
alert("Invalid mob")
return
+
//log_admin("[key_name(src)] has alienized [M.key].")
var/list/dresspacks = list(
"strip",
@@ -1106,11 +1063,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return
/client/proc/startSinglo()
-
set category = "Debug"
set name = "Start Singularity"
set desc = "Sets up the singularity and all machines to get power flowing through the station"
+ if(!check_rights(R_DEBUG))
+ return
+
if(alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Yes","No") != "Yes")
return
@@ -1160,6 +1119,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Debug Mob Lists"
set desc = "For when you just gotta know"
+
+ if(!check_rights(R_DEBUG))
+ return
switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Silicons","Clients","Respawnable Mobs"))
if("Players")
@@ -1181,6 +1143,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_toggle_block(var/mob/M,var/block)
+ if(!check_rights(R_SPAWN))
+ return
+
if(!ticker)
alert("Wait until the game starts")
return
@@ -1194,4 +1159,3 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!")
else
alert("Invalid mob")
-
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index 177f5f49f34..6c5db7cd1e6 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -1,6 +1,9 @@
/client/proc/air_status(turf/target as turf)
set category = "Debug"
set name = "Display Air Status"
+
+ if(!check_rights(R_DEBUG))
+ return
if(!isturf(target))
return
@@ -15,11 +18,22 @@
usr << "\blue @[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("\red BURNING"):(null)]"
for(var/datum/gas/trace_gas in GM.trace_gases)
usr << "[trace_gas.type]: [trace_gas.moles]"
+
+ message_admins("[key_name_admin(usr)] has checked the air status of [T]")
+ log_admin("[key_name(usr)] has checked the air status of [T]")
+
feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/fix_next_move()
set category = "Debug"
set name = "Unfreeze Everyone"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ message_admins("[key_name_admin(usr)] has unfrozen everyone")
+ log_admin("[key_name(usr)] has unfrozen everyone")
+
var/largest_move_time = 0
var/largest_click_time = 0
var/mob/largest_move_mob = null
@@ -42,15 +56,20 @@
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]")
M.next_move = 1
M.next_click = 0
+
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1)
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1)
message_admins("world.time = [world.time]", 1)
+
feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/radio_report()
set category = "Debug"
set name = "Radio report"
+
+ if(!check_rights(R_DEBUG))
+ return
var/filters = list(
"1" = "RADIO_TO_AIRALARM",
@@ -83,15 +102,22 @@
output += " [device] "
usr << browse(output,"window=radioreport")
+
+ message_admins("[key_name_admin(usr)] has generated a radio report")
+ log_admin("[key_name(usr)] has generated a radio report")
+
feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/reload_admins()
set name = "Reload Admins"
set category = "Debug"
- if(!check_rights(R_SERVER)) return
+ if(!check_rights(R_SERVER))
+ return
- message_admins("[usr] manually reloaded admins")
+ message_admins("[key_name_admin(usr)] has manually reloaded admins")
+ log_admin("[key_name(usr)] has manually reloaded admins")
+
load_admins()
feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -100,15 +126,24 @@
set name = "Print Jobban Log"
set desc = "This spams all the active jobban entries for the current round to standard output."
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
usr << "Jobbans active in this round."
for(var/t in jobban_keylist)
usr << "[t]"
+
+ message_admins("[key_name_admin(usr)] has printed the jobban log")
+ log_admin("[key_name(usr)] has printed the jobban log")
/client/proc/print_jobban_old_filter()
set name = "Search Jobban Log"
set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output."
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
var/filter = input("Contains what?","Filter") as text|null
if(!filter)
@@ -118,3 +153,6 @@
for(var/t in jobban_keylist)
if(findtext(t, filter))
usr << "[t]"
+
+ message_admins("[key_name_admin(usr)] has searched the jobban log for [filter]")
+ log_admin("[key_name(usr)] has searched the jobban log for [filter]")
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 5acf6c21b44..cc7f9f1befa 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -40,14 +40,15 @@ var/intercom_range_display_status = 0
/client/proc/camera_view()
set category = "Mapping"
set name = "Camera Range Display"
+
+ if(!check_rights(R_DEBUG))
+ return
if(camera_range_display_status)
camera_range_display_status = 0
else
camera_range_display_status = 1
-
-
for(var/obj/effect/debugging/camera_range/C in world)
del(C)
@@ -56,15 +57,12 @@ var/intercom_range_display_status = 0
new/obj/effect/debugging/camera_range(C.loc)
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-
/client/proc/sec_camera_report()
set category = "Mapping"
set name = "Camera Report"
-
- if(!master_controller)
- alert(usr,"Master_controller not found.","Sec Camera Report")
- return 0
+
+ if(!check_rights(R_DEBUG))
+ return
var/list/obj/machinery/camera/CL = list()
@@ -101,6 +99,9 @@ var/intercom_range_display_status = 0
/client/proc/intercom_view()
set category = "Mapping"
set name = "Intercom Range Display"
+
+ if(!check_rights(R_DEBUG))
+ return
if(intercom_range_display_status)
intercom_range_display_status = 0
@@ -119,26 +120,24 @@ var/intercom_range_display_status = 0
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/list/admin_verbs_show_debug_verbs = list(
- /client/proc/camera_view, //-errorage
- /client/proc/sec_camera_report, //-errorage
- /client/proc/intercom_view, //-errorage
+ /client/proc/camera_view,
+ /client/proc/sec_camera_report,
+ /client/proc/intercom_view,
/client/proc/Cell, //More air things
/client/proc/atmosscan, //check plumbing
/client/proc/powerdebug, //check power
/client/proc/count_objects_on_z_level,
/client/proc/count_objects_all,
- /client/proc/cmd_assume_direct_control, //-errorage
+ /client/proc/cmd_assume_direct_control,
/client/proc/startSinglo,
/client/proc/ticklag,
/client/proc/cmd_admin_grantfullaccess,
-// /client/proc/splash,
/client/proc/cmd_admin_areatest,
/client/proc/cmd_admin_rejuvenate,
/datum/admins/proc/show_traitor_panel,
/client/proc/print_jobban_old,
/client/proc/print_jobban_old_filter,
/client/proc/forceEvent,
- ///client/proc/cmd_admin_rejuvenate,
/client/proc/nanomapgen_DumpImage
)
@@ -146,7 +145,8 @@ var/list/admin_verbs_show_debug_verbs = list(
set category = "Debug"
set name = "Debug verbs"
- if(!check_rights(R_DEBUG)) return
+ if(!check_rights(R_DEBUG))
+ return
verbs += admin_verbs_show_debug_verbs
@@ -155,6 +155,10 @@ var/list/admin_verbs_show_debug_verbs = list(
/client/proc/count_objects_on_z_level()
set category = "Mapping"
set name = "Count Objects On Level"
+
+ if(!check_rights(R_DEBUG))
+ return
+
var/level = input("Which z-level?","Level?") as text
if(!level) return
var/num_level = text2num(level)
@@ -182,22 +186,16 @@ var/list/admin_verbs_show_debug_verbs = list(
if(B.z == num_level)
count++
atom_list += A
- /*
- var/atom/temp_atom
- for(var/i = 0; i <= (atom_list.len/10); i++)
- var/line = ""
- for(var/j = 1; j <= 10; j++)
- if(i*10+j <= atom_list.len)
- temp_atom = atom_list[i*10+j]
- line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
- world << line*/
- world << "There are [count] objects of type [type_path] on z-level [num_level]"
+ world << "There are [count] objects of type [type_path] on z-level [num_level]."
feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/count_objects_all()
set category = "Mapping"
set name = "Count Objects All"
+
+ if(!check_rights(R_DEBUG))
+ return
var/type_text = input("Which type path?","") as text
if(!type_text) return
@@ -209,15 +207,6 @@ var/list/admin_verbs_show_debug_verbs = list(
for(var/atom/A in world)
if(istype(A,type_path))
count++
- /*
- var/atom/temp_atom
- for(var/i = 0; i <= (atom_list.len/10); i++)
- var/line = ""
- for(var/j = 1; j <= 10; j++)
- if(i*10+j <= atom_list.len)
- temp_atom = atom_list[i*10+j]
- line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
- world << line*/
- world << "There are [count] objects of type [type_path] in the game world"
+ world << "There are [count] objects of type [type_path] in the game world."
feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index f0532fbd254..134cc9ff3f5 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -323,8 +323,12 @@ var/list/forbidden_varedit_object_types = list(
for(var/p in forbidden_varedit_object_types)
if( istype(O,p) )
- usr << "\red It is forbidden to edit this object's variables."
+ usr << "It is forbidden to edit this object's variables."
return
+
+ if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key"))
+ usr << "You cannot edit ckeys on client objects."
+ return
var/class
var/variable
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 37110c3c237..e047a9c6497 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1,8 +1,8 @@
/client/proc/cmd_admin_drop_everything(mob/M as mob in mob_list)
set category = null
set name = "Drop Everything"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_DEBUG|R_ADMIN))
return
var/confirm = alert(src, "Make [M] drop everything?", "Message", "Yes", "No")
@@ -19,9 +19,10 @@
/client/proc/cmd_admin_prison(mob/M as mob in mob_list)
set category = "Admin"
set name = "Prison"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_ADMIN))
return
+
if (ismob(M))
if(istype(M, /mob/living/silicon/ai))
alert("The AI can't be sent to prison you jerk!", null, null, null, null, null)
@@ -47,9 +48,11 @@
set category = "Event"
set name = "Subtle Message"
- if(!ismob(M)) return
+ if(!ismob(M))
+ return
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/msg = input("Message:", text("Subtle PM to [M.key]")) as text
@@ -67,8 +70,9 @@
/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are.
set category = "Admin"
set name = "Check new Players"
- if(!holder)
- src << "Only staff members may use this command."
+
+ if(!check_rights(R_MENTOR|R_MOD|R_ADMIN))
+ return
var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All")
@@ -99,7 +103,8 @@
set category = "Event"
set name = "Global Narrate"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
@@ -114,7 +119,8 @@
set category = "Event"
set name = "Direct Narrate"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if(!M)
M = input("Direct narrate to who?", "Active Players") as null|anything in get_mob_with_client_list()
@@ -135,9 +141,10 @@
/client/proc/cmd_admin_godmode(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Godmode"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_ADMIN))
return
+
M.status_flags ^= GODMODE
usr << "\blue Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]"
@@ -148,7 +155,8 @@
proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
if(automute)
- if(!config.automute_on) return
+ if(!config.automute_on)
+ return
else
if(!usr || !usr.client)
return
@@ -157,7 +165,8 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
return
if(!M.client)
usr << "Error: cmd_admin_mute: This mob doesn't have a client tied to it."
- if(!M.client) return
+ if(!M.client)
+ return
var/muteunmute
var/mute_string
@@ -195,9 +204,10 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
/client/proc/cmd_admin_add_random_ai_law()
set category = "Event"
set name = "Add Random AI Law"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_EVENT))
return
+
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
log_admin("[key_name(src)] has added a random AI law.")
@@ -209,105 +219,14 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
new /datum/event/ion_storm(0, announce_ion_laws)
feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-//I use this proc for respawn character too. /N
-/proc/create_xeno(ckey)
- if(!ckey)
- var/list/candidates = list()
- for(var/mob/M in player_list)
- if(M.stat != DEAD) continue //we are not dead!
- if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium
- if(jobban_isbanned(M, "alien") || jobban_isbanned(M, "Syndicate")) continue //we are jobbanned
- if(M.client.is_afk()) continue //we are afk
- if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to
- candidates += M.ckey
- if(candidates.len)
- ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates
- else
- usr << "Error: create_xeno(): no suitable candidates."
- if(!istext(ckey)) return 0
-
- var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva")
- var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin)
- var/mob/living/carbon/alien/new_xeno
- switch(alien_caste)
- if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen/large(spawn_here)
- if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here)
- if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here)
- if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here)
- if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here)
- else return 0
-
- new_xeno.ckey = ckey
- message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
- return 1
-
-/*
-Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly
-Ccomp's first proc.
-*/
-
-/client/proc/get_ghosts(var/notify = 0,var/what = 2)
- // what = 1, return ghosts ass list.
- // what = 2, return mob list
-
- var/list/mobs = list()
- var/list/ghosts = list()
- var/list/sortmob = sortAtom(mob_list) // get the mob list.
- /var/any=0
- for(var/mob/dead/observer/M in sortmob)
- mobs.Add(M) //filter it where it's only ghosts
- any = 1 //if no ghosts show up, any will just be 0
- if(!any)
- if(notify)
- src << "There doesn't appear to be any ghosts for you to select."
- return
-
- for(var/mob/M in mobs)
- var/name = M.name
- ghosts[name] = M //get the name of the mob for the popup list
- if(what==1)
- return ghosts
- else
- return mobs
-/*
-
-/client/proc/allow_character_respawn()
- set category = "Special Verbs"
- set name = "Allow player to respawn"
- set desc = "Let's the player bypass the 30 minute wait to respawn or allow them to re-enter their corpse."
- if(!holder)
- src << "Only administrators may use this command."
- var/list/ghosts= get_ghosts(1,1)
-
- var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts
- if(!target)
- src << "Hrm, appears you didn't select a ghost" // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error.
- return
-
- var/mob/dead/observer/G = ghosts[target]
- if(G.has_enabled_antagHUD && config.antag_hud_restricted)
- var/response = alert(src, "Are you sure you wish to allow this individual to play?","Ghost has used AntagHUD","Yes","No")
- if(response == "No") return
- G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb.
- timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure
- there won't be an autopsy.
- */
- G.has_enabled_antagHUD = 2
- G.can_reenter_corpse = 1
-
- G:show_message(text("\blue You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead."), 1)
- log_admin("[key_name(usr)] allowed [key_name(G)] to bypass the 30 minute respawn limit")
- message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit", 1)
-
-
/client/proc/toggle_antagHUD_use()
set category = "Server"
set name = "Toggle antagHUD usage"
set desc = "Toggles antagHUD usage for observers"
- if(!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_SERVER))
+ return
+
var/action=""
if(config.antag_hud_allowed)
for(var/mob/dead/observer/g in get_ghosts())
@@ -333,14 +252,14 @@ Ccomp's first proc.
log_admin("[key_name(usr)] has [action] antagHUD usage for observers")
message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1)
-
-
/client/proc/toggle_antagHUD_restrictions()
set category = "Server"
set name = "Toggle antagHUD Restrictions"
set desc = "Restricts players that have used antagHUD from being able to join this round."
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_SERVER))
+ return
+
var/action=""
if(config.antag_hud_restricted)
for(var/mob/dead/observer/g in get_ghosts())
@@ -360,7 +279,6 @@ Ccomp's first proc.
log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1)
-*/
/*
If a guy was gibbed and you want to revive him, this is a good way to do so.
@@ -371,9 +289,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Respawn Character"
set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into."
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_SPAWN))
return
+
var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", ""))
if(!input)
return
@@ -519,71 +438,70 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return new_character
-/client/proc/toggle_antagHUD_use()
- set category = "Server"
- set name = "Toggle antagHUD usage"
- set desc = "Toggles antagHUD usage for observers"
+//I use this proc for respawn character too. /N
+/proc/create_xeno(ckey)
+ if(!ckey)
+ var/list/candidates = list()
+ for(var/mob/M in player_list)
+ if(M.stat != DEAD) continue //we are not dead!
+ if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium
+ if(jobban_isbanned(M, "alien") || jobban_isbanned(M, "Syndicate")) continue //we are jobbanned
+ if(M.client.is_afk()) continue //we are afk
+ if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to
+ candidates += M.ckey
+ if(candidates.len)
+ ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates
+ else
+ usr << "Error: create_xeno(): no suitable candidates."
+ if(!istext(ckey)) return 0
- if(!holder)
- src << "Only administrators may use this command."
- var/action=""
- if(config.antag_hud_allowed)
- for(var/mob/dead/observer/g in get_ghosts())
- if(!g.client.holder) //Remove the verb from non-admin ghosts
- g.verbs -= /mob/dead/observer/verb/toggle_antagHUD
- if(g.antagHUD)
- g.antagHUD = 0 // Disable it on those that have it enabled
- g.has_enabled_antagHUD = 2 // We'll allow them to respawn
- g << "\red The Administrator has disabled AntagHUD "
- config.antag_hud_allowed = 0
- src << "\red AntagHUD usage has been disabled"
- action = "disabled"
+ var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva")
+ var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin)
+ var/mob/living/carbon/alien/new_xeno
+ switch(alien_caste)
+ if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen/large(spawn_here)
+ if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here)
+ if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here)
+ if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here)
+ if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here)
+ else return 0
+
+ new_xeno.ckey = ckey
+ message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
+ return 1
+
+
+/client/proc/get_ghosts(var/notify = 0,var/what = 2)
+ // what = 1, return ghosts ass list.
+ // what = 2, return mob list
+
+ var/list/mobs = list()
+ var/list/ghosts = list()
+ var/list/sortmob = sortAtom(mob_list) // get the mob list.
+ /var/any=0
+ for(var/mob/dead/observer/M in sortmob)
+ mobs.Add(M) //filter it where it's only ghosts
+ any = 1 //if no ghosts show up, any will just be 0
+ if(!any)
+ if(notify)
+ src << "There doesn't appear to be any ghosts for you to select."
+ return
+
+ for(var/mob/M in mobs)
+ var/name = M.name
+ ghosts[name] = M //get the name of the mob for the popup list
+ if(what==1)
+ return ghosts
else
- for(var/mob/dead/observer/g in get_ghosts())
- if(!g.client.holder) // Add the verb back for all non-admin ghosts
- g.verbs += /mob/dead/observer/verb/toggle_antagHUD
- g << "\blue The Administrator has enabled AntagHUD " // Notify all observers they can now use AntagHUD
- config.antag_hud_allowed = 1
- action = "enabled"
- src << "\blue AntagHUD usage has been enabled"
-
-
- log_admin("[key_name(usr)] has [action] antagHUD usage for observers")
- message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1)
-
-
-/client/proc/toggle_antagHUD_restrictions()
- set category = "Server"
- set name = "Toggle antagHUD Restrictions"
- set desc = "Restricts players that have used antagHUD from being able to join this round."
- if(!holder)
- src << "Only administrators may use this command."
- var/action=""
- if(config.antag_hud_restricted)
- for(var/mob/dead/observer/g in get_ghosts())
- g << "\blue The administrator has lifted restrictions on joining the round if you use AntagHUD"
- action = "lifted restrictions"
- config.antag_hud_restricted = 0
- src << "\blue AntagHUD restrictions have been lifted"
- else
- for(var/mob/dead/observer/g in get_ghosts())
- g << "\red The administrator has placed restrictions on joining the round if you use AntagHUD"
- g << "\red Your AntagHUD has been disabled, you may choose to re-enabled it but will be under restrictions "
- g.antagHUD = 0
- g.has_enabled_antagHUD = 0
- action = "placed restrictions"
- config.antag_hud_restricted = 1
- src << "\red AntagHUD restrictions have been enabled"
-
- log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
- message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1)
-
+ return mobs
+
/client/proc/cmd_admin_add_freeform_ai_law()
set category = "Event"
set name = "Add Custom AI law"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_EVENT))
return
+
var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
if(!input)
return
@@ -601,9 +519,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Rejuvenate"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_REJUVINATE))
return
+
if(!mob)
return
if(!istype(M))
@@ -619,7 +538,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Event"
set name = "Create Command Report"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null
var/customname = input(usr, "Pick a title for the report.", "Title") as text|null
@@ -647,12 +567,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
message_admins("[key_name_admin(src)] has created a command report", 1)
feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in view())
set category = "Admin"
set name = "Delete"
- if (!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_ADMIN))
return
if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes")
@@ -669,19 +588,20 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "List free slots"
- if (!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_ADMIN))
return
+
if(job_master)
for(var/datum/job/job in job_master.occupations)
src << "[job.title]: [job.total_positions]"
feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in view())
set category = "Event"
set name = "Explosion"
- if(!check_rights(R_DEBUG|R_EVENT)) return
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null
if(devastation == null) return
@@ -707,11 +627,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
return
-/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in view())
set category = "Special Verbs"
set name = "EM Pulse"
- if(!check_rights(R_DEBUG|R_EVENT)) return
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null) return
@@ -733,7 +654,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Gib"
- if(!check_rights(R_ADMIN|R_EVENT)) return
+ if(!check_rights(R_ADMIN|R_EVENT))
+ return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
@@ -754,6 +676,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Gibself"
set category = "Event"
+ if(!check_rights(R_ADMIN|R_EVENT))
+ return
+
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm == "Yes")
if (istype(mob, /mob/dead/observer)) // so they don't spam gibs everywhere
@@ -764,115 +689,29 @@ Traitors and the like can also be revived with the previous role mostly intact.
log_admin("[key_name(usr)] used gibself.")
message_admins("\blue [key_name_admin(usr)] used gibself.", 1)
feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/*
-/client/proc/cmd_manual_ban()
- set name = "Manual Ban"
- set category = "Special Verbs"
- if(!authenticated || !holder)
- src << "Only administrators may use this command."
- return
- var/mob/M = null
- switch(alert("How would you like to ban someone today?", "Manual Ban", "Key List", "Enter Manually", "Cancel"))
- if("Key List")
- var/list/keys = list()
- for(var/mob/M in world)
- keys += M.client
- var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in keys
- if(!selection)
- return
- M = selection:mob
- if ((M.client && M.client.holder && (M.client.holder.level >= holder.level)))
- alert("You cannot perform this action. You must be of a higher administrative rank!")
- return
-
- switch(alert("Temporary Ban?",,"Yes","No"))
- if("Yes")
- var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num
- if(!mins)
- return
- if(mins >= 525600) mins = 525599
- var/reason = input(usr,"Reason?","reason","Griefer") as text
- if(!reason)
- return
- if(M)
- AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins)
- M << "\redYou have been banned by [usr.client.ckey].\nReason: [reason]."
- M << "\red This is a temporary ban, it will be removed in [mins] minutes."
- M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
- log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
- message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
- world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=[mins]&server=[replacetext(config.server_name, "#", "")]")
- del(M.client)
- del(M)
- else
-
- if("No")
- var/reason = input(usr,"Reason?","reason","Griefer") as text
- if(!reason)
- return
- AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0)
- M << "\redYou have been banned by [usr.client.ckey].\nReason: [reason]."
- M << "\red This is a permanent ban."
- M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
- log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
- message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
- world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=perma&server=[replacetext(config.server_name, "#", "")]")
- del(M.client)
- del(M)
-*/
-
-/client/proc/update_world()
- // If I see anyone granting powers to specific keys like the code that was here,
- // I will both remove their SVN access and permanently ban them from my servers.
- return
/client/proc/cmd_admin_check_contents(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Check Contents"
+
+ if(!check_rights(R_ADMIN))
+ return
var/list/L = M.get_contents()
for(var/t in L)
usr << "[t]"
feedback_add_details("admin_verb","CC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/* This proc is DEFERRED. Does not do anything.
-/client/proc/cmd_admin_remove_plasma()
- set category = "Debug"
- set name = "Stabilize Atmos."
- if(!holder)
- src << "Only administrators may use this command."
- return
- feedback_add_details("admin_verb","STATM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-// DEFERRED
- spawn(0)
- for(var/turf/T in view())
- T.poison = 0
- T.oldpoison = 0
- T.tmppoison = 0
- T.oxygen = 755985
- T.oldoxy = 755985
- T.tmpoxy = 755985
- T.co2 = 14.8176
- T.oldco2 = 14.8176
- T.tmpco2 = 14.8176
- T.n2 = 2.844e+006
- T.on2 = 2.844e+006
- T.tn2 = 2.844e+006
- T.tsl_gas = 0
- T.osl_gas = 0
- T.sl_gas = 0
- T.temp = 293.15
- T.otemp = 293.15
- T.ttemp = 293.15
-*/
-
/client/proc/toggle_view_range()
set category = "Special Verbs"
set name = "Change View Range"
set desc = "switches between 1x and custom views"
+
+ if(!check_rights(R_ADMIN))
+ return
if(view == world.view)
- view = input("Select view range:", "View Range", 9) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
+ view = input("Select view range:", "View Range", world.view) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
else
view = world.view
@@ -882,14 +721,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_call_shuttle()
-
set category = "Admin"
set name = "Call Shuttle"
if ((!( ticker ) || !emergency_shuttle.location()))
return
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
@@ -924,7 +763,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Cancel Shuttle"
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
@@ -945,7 +785,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
if (!ticker)
return
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle
@@ -956,6 +797,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Attack Log"
+ if(!check_rights(R_ADMIN))
+ return
+
usr << text("\red Attack Log for []", mob)
for(var/t in M.attack_log)
usr << t
@@ -967,7 +811,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Make Everyone Random"
set desc = "Make everyone have a random appearance. You can only use this before rounds!"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if (ticker && ticker.mode)
usr << "Nope you can't do this, the game's already started. This only works before rounds!"
@@ -995,13 +840,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
ticker.random_players = 1
feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
/client/proc/toggle_random_events()
set category = "Event"
set name = "Toggle random events on/off"
set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if(!config.allow_random_events)
config.allow_random_events = 1
@@ -1018,7 +863,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Toggle ERT"
set desc = "Toggle the station's ability to call a response team."
- if(!check_rights(R_EVENT)) return
+ if(!check_rights(R_EVENT))
+ return
if(ticker.mode.ert_disabled)
ticker.mode.ert_disabled = 0
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index 3e2910fa556..ce914b6c407 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -207,7 +207,7 @@
dead_mob_list -= C
living_mob_list += C
C.stat = CONSCIOUS
- C.tod = null
+ C.timeofdeath = 0
C.setToxLoss(0)
C.setOxyLoss(0)
C.setCloneLoss(0)
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index b23d5e7e01e..4fef768e368 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -41,11 +41,9 @@ proc/createRandomZlevel()
var/file = file(map)
if(isfile(file))
maploader.load_map(file)
- // Initialize air for the away mission's turfs
if(air_master)
air_master.setup_allturfs(block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)))
- create_lighting_overlays(world.maxz)
- log_to_dd("away mission loaded: [map]")
+ log_to_dd("Away mission loaded: [map]")
for(var/obj/effect/landmark/L in landmarks_list)
if (L.name != "awaystart")
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index cbfa50f0759..da4c7e33572 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -60,7 +60,7 @@
//adv. hotkey mode vars, code using them in /interface/interface.dm//
/////////////////////////////////////////////////////////////////////
- var/hotkeytype = "QWERTY" //what set of hotkeys is in use(defaulting to QWERTY because I can't be bothered to ake this save on SQL)
+ var/hotkeytype = "QWERTY" //what set of hotkeys is in use(defaulting to QWERTY because I can't be bothered to make this save on SQL)
var/hotkeyon = 0 //is the hotkey on?
var/hotkeylist = list( //list defining hotkey types, look at lists in place for structure if adding any if the future
@@ -69,7 +69,10 @@
"off" = "macro"),
"AZERTY" = list(
"on" = "AZERTYon",
- "off" = "AZERTYoff")
+ "off" = "AZERTYoff"),
+ "Cyborg" = list(
+ "on" = "borghotkeymode",
+ "off" = "borgmacro")
)
var/reset_stretch = 0 //Used by things that fiddle with client's stretch-to-fit.
\ No newline at end of file
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 5212d6e84e8..cc3b54b6bde 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -272,7 +272,7 @@
if(holder)
add_admin_verbs()
- admin_memo_output("Show", 0)
+ admin_memo_output("Show", 0, 1)
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
@@ -282,15 +282,20 @@
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db()
+
+ if (ckey in clientmessages)
+ for (var/message in clientmessages[ckey])
+ src << message
+ clientmessages.Remove(ckey)
if (config && config.autoconvert_notes)
convert_notes_sql(ckey)
send_resources()
- //////////////
- //DISCONNECT//
- //////////////
+//////////////
+//DISCONNECT//
+//////////////
/client/Del()
if(holder)
holder.owner = null
diff --git a/code/modules/client/message.dm b/code/modules/client/message.dm
new file mode 100644
index 00000000000..6406a7d051a
--- /dev/null
+++ b/code/modules/client/message.dm
@@ -0,0 +1,9 @@
+var/list/clientmessages = list()
+
+proc/addclientmessage(var/ckey, var/message)
+ ckey = ckey(ckey)
+ if (!ckey || !message)
+ return
+ if (!(ckey in clientmessages))
+ clientmessages[ckey] = list()
+ clientmessages[ckey] += message
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 06ac7184749..210b1ddea65 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -367,7 +367,7 @@ datum/preferences
dat += " Eyes "
dat += "Change Color
__
"
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins
+ if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins
dat += " Body Color "
dat += "Change Color
__
"
@@ -1028,7 +1028,7 @@ datum/preferences
if(species == "Human")
s_tone = random_skin_tone()
if("s_color")
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Wryn" || species == "Vulpkanin")
+ if(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Wyrn", "Vulpkanin", "Machine"))
r_skin = rand(0,255)
g_skin = rand(0,255)
b_skin = rand(0,255)
@@ -1115,6 +1115,8 @@ datum/preferences
b_hair = 0//hex2num(copytext(new_hair, 6, 8))
s_tone = 0
+
+ body_accessory = null //no vulpatail on humans damnit
if("speciesprefs")//oldvox code
speciesprefs = !speciesprefs
@@ -1268,7 +1270,7 @@ datum/preferences
s_tone = 35 - max(min( round(new_s_tone), 220),1)
if("skin")
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People"|| species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user))
+ if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user))
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null
if(new_skin)
r_skin = hex2num(copytext(new_skin, 2, 4))
diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm
index 38006797487..98c26df8ec8 100644
--- a/code/modules/client/preferences_mysql.dm
+++ b/code/modules/client/preferences_mysql.dm
@@ -264,10 +264,10 @@
job_karma_high='[job_karma_high]',
job_karma_med='[job_karma_med]',
job_karma_low='[job_karma_low]',
- flavor_text='[sql_sanitize_text(flavor_text)]',
- med_record='[sql_sanitize_text(med_record)]',
- sec_record='[sql_sanitize_text(sec_record)]',
- gen_record='[sql_sanitize_text(gen_record)]',
+ flavor_text='[sql_sanitize_text(html_decode(flavor_text))]',
+ med_record='[sql_sanitize_text(html_decode(med_record))]',
+ sec_record='[sql_sanitize_text(html_decode(sec_record))]',
+ gen_record='[sql_sanitize_text(html_decode(gen_record))]',
player_alt_titles='[playertitlelist]',
be_special='[be_special]',
disabilities='[disabilities]',
@@ -321,7 +321,7 @@
'[job_medsci_high]', '[job_medsci_med]', '[job_medsci_low]',
'[job_engsec_high]', '[job_engsec_med]', '[job_engsec_low]',
'[job_karma_high]', '[job_karma_med]', '[job_karma_low]',
- '[sql_sanitize_text(flavor_text)]', '[sql_sanitize_text(med_record)]', '[sql_sanitize_text(sec_record)]', '[sql_sanitize_text(gen_record)]',
+ '[sql_sanitize_text(html_encode(flavor_text))]', '[sql_sanitize_text(html_encode(med_record))]', '[sql_sanitize_text(html_encode(sec_record))]', '[sql_sanitize_text(html_encode(gen_record))]',
'[playertitlelist]', '[be_special]',
'[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]',
'[socks]', '[body_accessory]')
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 32b99189599..7bfa16b8ba8 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -5,7 +5,7 @@
desc = "A special containment suit designed to protect a plasmaman's volatile body from outside exposure and quickly extinguish it in emergencies."
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank)
slowdown = 0
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20)
+ armor = list(melee = 0, bullet = 0, laser = 0 ,energy = 0, bomb = 0, bio = 100, rad = 20)
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
@@ -16,9 +16,9 @@
icon_state = "plasmaman_suit"
item_state = "plasmaman_suit"
- var/next_extinguish=0
- var/extinguish_cooldown=10 SECONDS
- var/extinguishes_left=10 // Yeah yeah, reagents, blah blah blah. This should be simple.
+ var/next_extinguish = 0
+ var/extinguish_cooldown = 10 SECONDS
+ var/extinguishes_left = 10 // Yeah yeah, reagents, blah blah blah. This should be simple.
/obj/item/clothing/suit/space/eva/plasmaman/examine(mob/user)
..(user)
@@ -46,35 +46,26 @@
var/base_state = "plasmaman_helmet"
var/brightness_on = 4 //luminosity when on
var/on = 0
- var/no_light=0 // Disable the light on the atmos suit
action_button_name = "Toggle Helmet Light"
/obj/item/clothing/head/helmet/space/eva/plasmaman/attack_self(mob/user)
if(!isturf(user.loc))
- user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities.
- return
- if(no_light)
+ user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
return
+ toggle_light(user)
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/proc/toggle_light(mob/user)
on = !on
icon_state = "[base_state][on]"
- if(on) user.set_light(user.luminosity + brightness_on)
- else user.set_light(user.luminosity - brightness_on)
- user.update_inv_head()
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/pickup(mob/user)
- if(on)
- user.set_light(user.luminosity + brightness_on)
-// user.UpdateLuminosity()
+ if(on)
+ set_light(brightness_on)
+ else
set_light(0)
-/obj/item/clothing/head/helmet/space/eva/plasmaman/dropped(mob/user)
- if(on)
- user.set_light(user.luminosity - brightness_on)
-// user.UpdateLuminosity()
- set_light(brightness_on)
-
-
+ if(istype(user,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_head()
// ENGINEERING
/obj/item/clothing/suit/space/eva/plasmaman/assistant
@@ -305,7 +296,7 @@
/obj/item/clothing/suit/space/eva/plasmaman/nuclear
name = "blood red plasmaman suit"
icon_state = "plasmaman_Nukeops"
- armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60)
+ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs)
siemens_coefficient = 0.6
@@ -313,20 +304,5 @@
name = "blood red plasmaman helmet"
icon_state = "plasmaman_Nukeops_helmet0"
base_state = "plasmaman_Nukeops_helmet"
- armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60)
+ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
siemens_coefficient = 0.6
- var/obj/machinery/camera/camera
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/attack_self(mob/user)
- if(camera)
- ..(user)
- else
- camera = new /obj/machinery/camera(src)
- camera.network = list("NUKE")
- cameranet.removeCamera(camera)
- camera.c_tag = user.name
- user << "User scanned as [camera.c_tag]. Camera activated."
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/examine(mob/user)
- if(..(user, 1))
- user << "This helmet has a built-in camera. It's [camera ? "" : "in"]active."
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index b3c5d19b6d7..8f1703a3325 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -27,20 +27,24 @@
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
)
- attack_self(mob/user)
- if(!isturf(user.loc))
- user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities.
- return
- on = !on
- icon_state = "rig[on]-[_color]"
-// item_state = "rig[on]-[color]"
+/obj/item/clothing/head/helmet/space/rig/attack_self(mob/user)
+ if(!isturf(user.loc))
+ user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
+ return
+ toggle_light(user)
- if(on) set_light(brightness_on)
- else set_light(0)
+/obj/item/clothing/head/helmet/space/rig/proc/toggle_light(mob/user)
+ on = !on
+ icon_state = "rig[on]-[_color]"
- if(istype(user,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- H.update_inv_head()
+ if(on)
+ set_light(brightness_on)
+ else
+ set_light(0)
+
+ if(istype(user,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_head()
/obj/item/clothing/suit/space/rig
name = "hardsuit"
@@ -98,7 +102,7 @@
else
M << "Your suit's helmet deploys with a hiss."
//TODO: Species check, skull damage for forcing an unfitting helmet on?
- helmet.loc = H
+ helmet.forceMove(H)
H.equip_to_slot(helmet, slot_head)
helmet.flags |= NODROP
@@ -107,7 +111,7 @@
M << "You are unable to deploy your suit's magboots as \the [H.shoes] are in the way."
else
M << "Your suit's boots deploy with a hiss."
- boots.loc = H
+ boots.forceMove(H)
H.equip_to_slot(boots, slot_shoes)
boots.flags |= NODROP
@@ -122,7 +126,7 @@
if(helmet && H.head == helmet)
helmet.flags &= ~NODROP
H.unEquip(helmet)
- helmet.loc = src
+ helmet.forceMove(src)
if(boots)
H = boots.loc
@@ -130,58 +134,15 @@
if(boots && H.shoes == boots)
boots.flags &= ~NODROP
H.unEquip(boots)
- boots.loc = src
-
-/*
-/obj/item/clothing/suit/space/rig/verb/get_mounted_device()
-
- set name = "Deploy Mounted Device"
- set category = "Object"
- set src in usr
-
- if(!can_mount)
- verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
- verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
- return
-
- if(!istype(usr, /mob/living)) return
- if(usr.stat) return
-
- if(active_device)
- usr << "You already have \the [active_device] deployed."
- return
-
- if(!mounted_devices.len)
- usr << "You do not have any devices mounted on \the [src]."
- return
-
-/obj/item/clothing/suit/space/rig/verb/stow_mounted_device()
-
- set name = "Stow Mounted Device"
- set category = "Object"
- set src in usr
-
- if(!can_mount)
- verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
- verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
- return
-
- if(!istype(usr, /mob/living)) return
-
- if(usr.stat) return
-
- if(!active_device)
- usr << "You have no device currently deployed."
- return
-*/
-
+ boots.forceMove(src)
+
/obj/item/clothing/suit/space/rig/verb/toggle_helmet()
-
set name = "Toggle Helmet"
set category = "Object"
set src in usr
- if(!istype(src.loc,/mob/living)) return
+ if(!isliving(usr))
+ return
if(!helmet)
usr << "There is no helmet installed."
@@ -197,23 +158,22 @@
helmet.flags &= ~NODROP
H.unEquip(helmet)
helmet.loc = src
- H << "\blue You retract your hardsuit helmet."
+ H << "You retract your hardsuit helmet."
else
if(H.head)
- H << "\red You cannot deploy your helmet while wearing another helmet."
+ H << "You cannot deploy your helmet while wearing another helmet."
return
//TODO: Species check, skull damage for forcing an unfitting helmet on?
helmet.loc = H
helmet.pickup(H)
H.equip_to_slot(helmet, slot_head)
helmet.flags |= NODROP
- H << "\blue You deploy your hardsuit helmet, sealing you off from the world."
+ H << "You deploy your hardsuit helmet, sealing you off from the world."
H.update_inv_head()
/obj/item/clothing/suit/space/rig/attackby(obj/item/W as obj, mob/user as mob, params)
-
- if(!istype(user,/mob/living)) return
-
+ if(!isliving(user))
+ return
if(istype(src.loc,/mob/living))
user << "How do you propose to modify a hardsuit while it is being worn?"
@@ -230,7 +190,7 @@
if(!boots)
user << "\The [src] does not have any boots installed."
else
- user << "You detatch \the [boots] from \the [src]'s boot mounts."
+ user << "You detach \the [boots] from \the [src]'s boot mounts."
boots.loc = get_turf(src)
boots = null
return
@@ -338,8 +298,9 @@
/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user)
if(!isturf(user.loc))
- user << "You cannot toggle your helmet while in this [user.loc]" //To prevent some lighting anomalities.
+ user << "You cannot toggle your helmet while in this [user.loc]." //To prevent some lighting anomalities.
return
+
on = !on
if(on)
user << "You switch your helmet to travel mode. It will allow you to stand in zero pressure environments, at the cost of speed and armor."
@@ -484,7 +445,6 @@
heat_protection = HEAD //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
-
/obj/item/clothing/suit/space/rig/atmos
desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding."
icon_state = "rig-atmos"
diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm
index e7e1e299f27..93c9733eae0 100644
--- a/code/modules/customitems/item_spawning.dm
+++ b/code/modules/customitems/item_spawning.dm
@@ -62,6 +62,7 @@
Item.loc = get_turf(M.loc)
HackProperties(Item,propadjust)
+ M.regenerate_icons()
// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
/proc/HackProperties(var/mob/living/carbon/human/M,var/obj/item/I,var/script)
diff --git a/code/modules/DetectiveWork/detective_work.dm b/code/modules/detective_work/detective_work.dm
similarity index 100%
rename from code/modules/DetectiveWork/detective_work.dm
rename to code/modules/detective_work/detective_work.dm
diff --git a/code/modules/DetectiveWork/evidence.dm b/code/modules/detective_work/evidence.dm
similarity index 100%
rename from code/modules/DetectiveWork/evidence.dm
rename to code/modules/detective_work/evidence.dm
diff --git a/code/modules/DetectiveWork/footprints_and_rag.dm b/code/modules/detective_work/footprints_and_rag.dm
similarity index 100%
rename from code/modules/DetectiveWork/footprints_and_rag.dm
rename to code/modules/detective_work/footprints_and_rag.dm
diff --git a/code/modules/DetectiveWork/scanner.dm b/code/modules/detective_work/scanner.dm
similarity index 100%
rename from code/modules/DetectiveWork/scanner.dm
rename to code/modules/detective_work/scanner.dm
diff --git a/code/modules/garbage collection/__gc_info.dm b/code/modules/garbage_collection/__gc_info.dm
similarity index 100%
rename from code/modules/garbage collection/__gc_info.dm
rename to code/modules/garbage_collection/__gc_info.dm
diff --git a/code/modules/garbage collection/garbage_collector.dm b/code/modules/garbage_collection/garbage_collector.dm
similarity index 100%
rename from code/modules/garbage collection/garbage_collector.dm
rename to code/modules/garbage_collection/garbage_collector.dm
diff --git a/code/modules/garbage collection/gc_testing.dm b/code/modules/garbage_collection/gc_testing.dm
similarity index 100%
rename from code/modules/garbage collection/gc_testing.dm
rename to code/modules/garbage_collection/gc_testing.dm
diff --git a/code/modules/genetics2/computer.dm b/code/modules/genetics2/computer.dm
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/code/modules/genetics2/genetree.dm b/code/modules/genetics2/genetree.dm
deleted file mode 100644
index aa8d1ba7571..00000000000
--- a/code/modules/genetics2/genetree.dm
+++ /dev/null
@@ -1,63 +0,0 @@
-// Management of available genes.
-
-/datum/genetree
- var/list/sectors=list()
- var/list/dependencies=list()
- var/list/dependants=list()
- var/obj/machinery/networked/biomass_controller/biomass = null
-
-/datum/genetree/New(var/obj/machinery/networked/biomass_controller/holder)
- biomass = holder
- // Build list of all sectors
- for(var/typepath in subtypesof(/datum/genetic_sector))
- var/datum/genetic_sector/sector = new typepath
- sectors[sector.id]=sector
-
- if(sector.prerequisites.len > 0)
- sector.locked=1
-
- // Make list of things that depend on this sector.
- dependencies[sector.id]=sector.prerequisites
-
- // Generate reverse dependencies
- for(var/dependee in sector.prerequisites)
- if(!(dependee in dependants))
- dependants[dependee]=list(sector.id)
- else
- var/list/D = dependants[dependee]
- D.Add(sector.name)
-
-/datum/genetree/proc/IsActive(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- return sector.active
-
-/datum/genetree/proc/CanActivateSector(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- for(var/dep in sector.prerequisites)
- if(!IsActive(sector.id))
- return 0
- return biomass.available >= sector.required_biomass
-
-// Does NOT check for biomass
-/datum/genetree/proc/ActivateSector(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- sector.active = 1
- sector.OnActivate()
- for(var/subsect in dependants[sname])
- var/datum/genetic_sector/subsector = sectors[subsect]
- subsector.locked=0
-
-/datum/genetree/proc/CheckSectors()
- var/sectors_changed=0
- for(var/sname in sectors)
- var/datum/genetic_sector/sector = sectors[sname]
- var/pstate=sector.active
- sector.active=1
- for(var/prereq in sector.prerequisites)
- if(!IsActive(prereq))
- sector.active=0
- break
- if(pstate != sector.active)
- sectors_changed = 1
- if(sectors_changed)
- CheckSectors()
\ No newline at end of file
diff --git a/code/modules/genetics2/sectors.dm b/code/modules/genetics2/sectors.dm
deleted file mode 100644
index aec12619180..00000000000
--- a/code/modules/genetics2/sectors.dm
+++ /dev/null
@@ -1,110 +0,0 @@
-var/global/current_sector_id=0
-/datum/genetic_sector
- var/name = "UNKNOWN SECTOR"
- var/desc = "LOLIDK"
-
- var/id = ""
- var/uniqid = "" // 3-char ID, shown when locked.
- var/list/prerequisites = list()
- var/list/blocks_txt = list()
- var/list/blocks = list() // DO NOT FUCKING USE THIS
- var/required_biomass = 0 // In hominids (/mob/living/carbon)
- var/time_required = 300 // Decaseconds required to unlock
- var/time_researched = 0
- var/active=0 // Accessible
- var/locked=0 // Cannot be purchased (yet)
-
-/datum/genetic_sector/New()
- uniqid = add_zero2("[current_sector_id++]",3)
-
- // Set blocks
- for(var/blockname in blocks_txt)
- var/block = assigned_blocks[blockname]
- if(block)
- blocks += block
-
-///////////////////////////////////////
-// SECTORS
-///////////////////////////////////////
-
-/datum/genetic_sector/metabolism
- id = "metabolism"
- name = "Metabolism"
- desc = "Grants access to areas of DNA that affect how the body controls its temperature."
- required_biomass = 1
- time_required = 30 SECONDS
- blocks_txt=list(
- "COLD",
- "FIRE",
- "IMMOLATE",
- "SOBER",
- "MELT",
- "FAT"
- )
-
-/datum/genetic_sector/mind
- id = "mind"
- name = "Mental Aptitude"
- desc = "Reveals parts of DNA that affect mental capabilities"
- required_biomass = 2
- time_required = 30 SECONDS
- blocks_txt=list(
- "PSYRESIST",
- "HALLUCINATION",
- "TWITCH",
- "EPILEPSY",
- )
-
-/datum/genetic_sector/teleability
- id = "teleability"
- name = "Teleability"
- desc = "Activates unused portions of the brain that can affect people a great distance away."
- prerequisites = list("mind")
- required_biomass = 4
- time_required = 1 MINUTES
- blocks_txt = list(
- "REMOTEVIEW",
- "REMOTETALK",
- "CRYO",
- "EMPATH"
- )
-
-/datum/genetic_sector/telekinesis
- id = "telekinesis"
- name = "Telekinesis"
- desc = "Activates unused portions of the brain that can affect objects a great distance away."
- prerequisites = list("teleability")
- required_biomass = 5
- time_required = 2 MINUTES
- blocks_txt = list(
- "TELE",
- "FAKE"
- )
-
-/datum/genetic_sector/senses
- id = "senses"
- name = "Senses"
- desc = "Accesses genes that affect vision and hearing."
- prerequisites = list("mind")
- required_biomass = 4
- time_required = 30 SECONDS
- blocks_txt = list(
- "XRAY",
- "BLIND",
- "GLASSES",
- "EMPATH",
- "DEAF"
- )
-
-/datum/genetic_sector/respiration
- id = "respiration"
- name = "Respiration"
- desc = "Mess around with genes that affect breathing and lungs."
- prerequisites = list("metabolism")
- time_required = 1 MINUTES
- required_biomass = 4
- blocks_txt = list(
- "NOBREATH",
- "COUGH",
- "INCREASERUN",
- )
\ No newline at end of file
diff --git a/code/modules/icon generation/Bluespaced.dm b/code/modules/icon generation/Bluespaced.dm
deleted file mode 100644
index 697b9e97196..00000000000
--- a/code/modules/icon generation/Bluespaced.dm
+++ /dev/null
@@ -1,243 +0,0 @@
-/proc/bsi_cast_ray(icon/I, list/start, list/end)
-
- if(abs(start[1] - end[1]) > abs(start[2] - end[2]))
- var/dist = abs(start[1] - end[1]) * 2
-
- for(var/i = 1, i <= dist, i++)
- var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist)))
- var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist)))
-
- if(I.GetPixel(x, y) != null)
- return list(x, y)
-
- else
- var/dist = abs(start[2] - end[2]) * 2
-
- for(var/i = 1, i <= dist, i++)
- var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist)))
- var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist)))
-
- if(I.GetPixel(x, y) != null)
- return list(x, y)
-
- return null
-
-/proc/bsi_split_colors(color)
- if(color == null)
- return list(0, 0, 0, 0)
-
- var/list/colors = list(0, 0, 0, 0)
- colors[1] = hex2num(copytext(color, 2, 4))
- colors[2] = hex2num(copytext(color, 4, 6))
- colors[3] = hex2num(copytext(color, 6, 8))
- colors[4] = (length(color) > 7)? hex2num(copytext(color, 8, 10)) : 255
-
- return colors
-
-/proc/bsi_spread(icon/I, list/start_point)
- var/list/queue = list()
- queue[++queue.len] = start_point
-
- var/i = 0
-
- while(i++ < length(queue))
- var/x = queue[i][1]
- var/y = queue[i][2]
-
- var/list/pixel = bsi_split_colors(I.GetPixel(x, y))
- if(pixel[4] == 0)
- continue
-
- var/list/n = (y < I.Height())? bsi_split_colors(I.GetPixel(x, y + 1)) : list(0, 0, 0, 0)
- var/list/s = (y > 1)? bsi_split_colors(I.GetPixel(x, y - 1)) : list(0, 0, 0, 0)
- var/list/e = (x < I.Width())? bsi_split_colors(I.GetPixel(x + 1, y)) : list(0, 0, 0, 0)
- var/list/w = (x > 1)? bsi_split_colors(I.GetPixel(x - 1, y)) : list(0, 0, 0, 0)
-
- var/value = (i == 1)? 16 : max(n[1] - 1, e[1] - 1, s[1] - 1, w[1] - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(value <= pixel[1])
- continue
-
- var/v2 = 256 - ((16 - value) * (16 - value))
-
- I.DrawBox(rgb(value, v2, pixel[4] - v2, pixel[4]), x, y)
-
- if(n[4] != 0 && n[1] < value - 1)
- queue[++queue.len] = list(x, y + 1)
-
- if(s[4] != 0 && s[1] < value - 1)
- queue[++queue.len] = list(x, y - 1)
-
- if(e[4] != 0 && e[1] < value - 1)
- queue[++queue.len] = list(x + 1, y)
-
- if(w[4] != 0 && w[1] < value - 1)
- queue[++queue.len] = list(x - 1, y)
-
-
-
-
-
-/proc/bsi_generate_mask(icon/source, state)
- var/icon/mask = icon(source, state)
-
- mask.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 1, 1,
- 0, 0, 0, 0)
-
- var/hits = 0
-
- for(var/i = 1, i <= 10, i++)
- var/point1
- var/point2
-
- if(prob(50))
- if(prob(50))
- point1 = list(rand(1, mask.Width()), mask.Height())
- point2 = list(rand(1, mask.Width()), 1)
-
- else
- point2 = list(rand(1, mask.Width()), mask.Height())
- point1 = list(rand(1, mask.Width()), 1)
-
- else
- if(prob(50))
- point1 = list(mask.Width(), rand(1, mask.Height()))
- point2 = list(1, rand(1, mask.Height()))
-
- else
- point2 = list(mask.Width(), rand(1, mask.Height()))
- point1 = list(1, rand(1, mask.Height()))
-
- var/hit = bsi_cast_ray(mask, point1, point2)
-
- if(hit == null)
- continue
-
- hits++
-
- bsi_spread(mask, hit)
-
- if(prob(20 + hits * 20))
- break
-
- if(hits == 0)
- return null
-
- else
- return mask
-
-/proc/generate_bluespace_icon(icon/source, state)
-
- var/icon/mask = bsi_generate_mask(source, state)
-
- if(mask == null)
- return source
-
- var/icon/unaffected = icon(mask)
- unaffected.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 0, 0, 0, 0,
- 255, 255, 255, 0)
-
- var/icon/temp = icon(source, state) //Mask already contains the original alpha values, avoid squaring them
- temp.MapColors(
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 255)
-
- unaffected.Blend(temp, ICON_MULTIPLY)
-
- var/icon/bluespaced = icon(mask)
- bluespaced.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 1, 0)
-
- bluespaced.Blend(icon(source, state), ICON_MULTIPLY)
-
- var/list/frames = list(
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
-
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
-
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
- )
-
- var/list/colors = list(
- list( 75, 75, 75, 0),
- list( 25, 25, 25, 0),
- list( 75, 75, 75, 0),
- list( 25, 25, 75, 0),
- list( 75, 75, 300, 0),
- list( 25, 25, 300, 0),
- list(255, 255, 255, 0),
- list( 0, 0, 0, 255),
- list( 0, 0, 0, 0),
- list( 0, 0, 0, 0),
- )
-
- for(var/i = 1, i <= rand(1, 5), i++)
- var/f = rand(1, length(frames))
-
- if(frames[f][2] > 1)
- frames[f][2]--
- frames.Insert(f, 0)
-
- frames[f] = list(0.8, 1)
-
- var/icon/result = generate_color_animation(bluespaced, colors, frames)
- result.Blend(unaffected, ICON_UNDERLAY)
-
- return result
-
-
-
-/atom/verb/test()
- set src in view()
- src.icon = generate_bluespace_icon(src.icon, src.icon_state)
-
-/mob/verb/bluespam()
- for(var/turf/t in view(5))
- var/obj/s = new /obj/square(t)
- s.icon = generate_bluespace_icon(s.icon, s.icon_state)
-
diff --git a/code/modules/icon generation/Icon_color_animation.dm b/code/modules/icon generation/Icon_color_animation.dm
deleted file mode 100644
index 1be1bfa28a9..00000000000
--- a/code/modules/icon generation/Icon_color_animation.dm
+++ /dev/null
@@ -1,96 +0,0 @@
-//----------------------------------------
-//
-// Return a copy of the provided icon,
-// after calling MapColors on it. The
-// color values are linearily interpolated
-// between the pairs provided, based on
-// the ratio argument.
-//
-//----------------------------------------
-
-/proc/MapColors_interpolate(icon/input, ratio,
- rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2,
- gr1, gg1, gb1, ga1, gr2, gg2, gb2, ga2,
- br1, bg1, bb1, ba1, br2, bg2, bb2, ba2,
- ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2,
- zr1, zg1, zb1, za1, zr2, zg2, zb2, za2)
- var/r = ratio
- var/i = 1 - ratio
- var/icon/I = icon(input)
-
- I.MapColors(
- (rr1 * r + rr2 * i) / 255.0, (rg1 * r + rg2 * i) / 255.0, (rb1 * r + rb2 * i) / 255.0, (ra1 * r + ra2 * i) / 255.0,
- (gr1 * r + gr2 * i) / 255.0, (gg1 * r + gg2 * i) / 255.0, (gb1 * r + gb2 * i) / 255.0, (ga1 * r + ga2 * i) / 255.0,
- (br1 * r + br2 * i) / 255.0, (bg1 * r + bg2 * i) / 255.0, (bb1 * r + bb2 * i) / 255.0, (ba1 * r + ba2 * i) / 255.0,
- (ar1 * r + ar2 * i) / 255.0, (ag1 * r + ag2 * i) / 255.0, (ab1 * r + ab2 * i) / 255.0, (aa1 * r + aa2 * i) / 255.0,
- (zr1 * r + zr2 * i) / 255.0, (zg1 * r + zg2 * i) / 255.0, (zb1 * r + zb2 * i) / 255.0, (za1 * r + za2 * i) / 255.0)
-
- return I
-
-
-
-
-//----------------------------------------
-//
-// Extension of the above that takes a
-// list of lists of color values, rather
-// than a large number of arguments.
-//
-//----------------------------------------
-
-/proc/MapColors_interpolate_list(icon/I, ratio, list/colors)
- var/list/c[10]
-
- //Provide default values for any missing colors (without altering the original list
- for(var/i = 1, i <= 10, i++)
- c[i] = list(0, 0, 0, (i == 7 || i == 8)? 255 : 0)
-
- if(istype(colors[i], /list))
- for(var/j = 1, j <= 4, j++)
- if(j <= length(colors[i]) && isnum(colors[i][j]))
- c[i][j] = colors[i][j]
-
- return MapColors_interpolate(I, ratio,
- colors[ 1][1], colors[ 1][2], colors[ 1][3], colors[ 1][4], // Red 1
- colors[ 2][1], colors[ 2][2], colors[ 2][3], colors[ 2][4], // Red 2
- colors[ 3][1], colors[ 3][2], colors[ 3][3], colors[ 3][4], // Green 1
- colors[ 4][1], colors[ 4][2], colors[ 4][3], colors[ 4][4], // Green 2
- colors[ 5][1], colors[ 5][2], colors[ 5][3], colors[ 5][4], // Blue 1
- colors[ 6][1], colors[ 6][2], colors[ 6][3], colors[ 6][4], // Blue 2
- colors[ 7][1], colors[ 7][2], colors[ 7][3], colors[ 7][4], // Alpha 1
- colors[ 8][1], colors[ 8][2], colors[ 8][3], colors[ 8][4], // Alpha 2
- colors[ 9][1], colors[ 9][2], colors[ 9][3], colors[ 9][4], // Added 1
- colors[10][1], colors[10][2], colors[10][3], colors[10][4]) // Added 2
-
-
-
-
-
-//----------------------------------------
-//
-// Take the source image, and return an animated
-// version, that transitions between the provided
-// color mappings, according to the provided
-// pattern.
-//
-// Colors should be in a format suitable for
-// MapColors_interpolate_list, and frames should
-// be a list of 'frames', where each frame is itself
-// a list, element 1 being the ratio of the first
-// color to the second, and element 2 being how
-// long the frame lasts, in tenths of a second.
-//
-//----------------------------------------
-
-/proc/generate_color_animation(icon/icon, list/colors, list/frames)
- var/icon/out = icon('icons/effects/uristrunes.dmi', "")
- var/frame_num = 1
-
- for(var/frame in frames)
- var/icon/I = MapColors_interpolate_list(icon, frame[1], colors)
- out.Insert(I, "", 2, frame_num++, 0, frame[2])
-
- return out
-
-
-
diff --git a/code/modules/icon generation/Uristrunes.dm b/code/modules/icon generation/Uristrunes.dm
deleted file mode 100644
index d9c129df8ed..00000000000
--- a/code/modules/icon generation/Uristrunes.dm
+++ /dev/null
@@ -1,268 +0,0 @@
-//----------------------------------------
-//
-// Take a source icon, convert into a mask,
-// then create a border around it.
-//
-// The output then uses the colors and
-// alpha values provided.
-//
-//----------------------------------------
-
-/proc/create_border_image(icon/input, border_color = "#000000", fill_color = "#000000", border_alpha = 255, fill_alpha = 255)
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
- I.Blend(input, ICON_OVERLAY)
-
- //Discard the image
- I.MapColors(0, 0, 0, 0, //-\ Ignore
- 0, 0, 0, 0, //--> The
- 0, 0, 0, 0, //-/ Colors
- 0,255, 0, 1, //Keep alpha channel, any pixel with non-zero alpha gets max green channel
- 0, 0, 0, 0)
-
- //Loop over the image, calculating the border value, and storing it in the red channel
- //Store border's alpha in the blue channel
- for(var/x = 1, x <= 32, x++)
- for(var/y = 1, y <= 32, y++)
- var/p = I.GetPixel(x, y)
-
- if(p == null)
- var/n = I.GetPixel(x, y + 1)
- var/s = I.GetPixel(x, y - 1)
- var/e = I.GetPixel(x + 1, y)
- var/w = I.GetPixel(x - 1, y)
- var/ne = I.GetPixel(x + 1, y + 1)
- var/se = I.GetPixel(x + 1, y - 1)
- var/nw = I.GetPixel(x - 1, y + 1)
- var/sw = I.GetPixel(x - 1, y - 1)
-
- var/sum_adj = ((n == "#00ff00"? 1 : 0) \
- + (s == "#00ff00"? 1 : 0) \
- + (e == "#00ff00"? 1 : 0) \
- + (w == "#00ff00"? 1 : 0))
-
- var/sum_diag = ((ne == "#00ff00"? 1 : 0) \
- + (se == "#00ff00"? 1 : 0) \
- + (nw == "#00ff00"? 1 : 0) \
- + (sw == "#00ff00"? 1 : 0))
-
-
- if(sum_adj)
- I.DrawBox(rgb(255, 0, 200, 0), x, y)
-
- else if(sum_diag)
- I.DrawBox(rgb(255, 0, 100, 0), x, y)
-
- else
- I.DrawBox(rgb(0, 0, 0, 0), x, y)
-
- else if(p != "#00ff00")
- var/a = 255
-
- if(length(p) == 9) // "#rrggbbaa", we want the aa
- a = hex2num(copytext(p, 8))
-
- I.DrawBox(rgb(255 - a, a, 255 - a, a), x, y)
-
- //Map the red and green channels to the desired output colors
- I.MapColors(border_color, fill_color, rgb(0, 0, 0, border_alpha), rgb(0, 0, 0, fill_alpha), "#00000000")
-
- return I
-
-
-
-
-//----------------------------------------
-//
-// Take a source icon, convert into a mask,
-// and border. Color them according to args,
-// and animate.
-//
-//----------------------------------------
-
-/proc/animate_rune_full(icon/input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2, or1, og1, ob1, oa1, or2, og2, ob2, oa2, frames)
-
- var/list/colors[10]
- colors[ 1] = list(rr1, rg1, rb1, ra1) //Rune color 1
- colors[ 2] = list(rr2, rg2, rb2, ra2) //Rune color 2
- colors[ 3] = list(br1, bg1, bb1, ba1) //Border color 1
- colors[ 4] = list(br2, bg2, bb2, ba2) //Border color 2
- colors[ 5] = list( 0, 0, 0, 0) //Unused
- colors[ 6] = list( 0, 0, 0, 0) //Unused
- colors[ 7] = list(ar1, ag1, ab1, aa1) //Alpha color 1
- colors[ 8] = list(ar2, ag2, ab2, aa2) //Alpha color 2
- colors[ 9] = list(or1, og1, ob1, oa1) //Added color 1
- colors[10] = list(or2, og2, ob2, oa2) //Added color 2
-
- var/icon/base = create_border_image(input, "#00ff0000", "#ff000000")
-
- return generate_color_animation(base, colors, frames)
-
-
-
-
-//----------------------------------------
-//
-// Calls the above, but accepts colors in
-// the form of "#RRGGBBAA", and provides
-// default values.
-//
-// Main limit is that it doesn't accept
-// negative values, which you probably
-// don't need anyway. Also missing a few
-// color inputs, which would also be rarely
-// used.
-//
-//----------------------------------------
-
-
-/proc/animate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000", rune_color2 = "#00000000", border_color2 = "#d8380000", alpha = 255, alpha2 = 255, frames = rune_animation)
- var/rr1 = hex2num(copytext(rune_color, 2, 4))
- var/rg1 = hex2num(copytext(rune_color, 4, 6))
- var/rb1 = hex2num(copytext(rune_color, 6, 8))
- var/ra1 = hex2num(copytext(rune_color, 8, 10))
- var/rr2 = hex2num(copytext(rune_color2, 2, 4))
- var/rg2 = hex2num(copytext(rune_color2, 4, 6))
- var/rb2 = hex2num(copytext(rune_color2, 6, 8))
- var/ra2 = hex2num(copytext(rune_color2, 8, 10))
- var/br1 = hex2num(copytext(border_color, 2, 4))
- var/bg1 = hex2num(copytext(border_color, 4, 6))
- var/bb1 = hex2num(copytext(border_color, 6, 8))
- var/ba1 = hex2num(copytext(border_color, 8, 10))
- var/br2 = hex2num(copytext(border_color2, 2, 4))
- var/bg2 = hex2num(copytext(border_color2, 4, 6))
- var/bb2 = hex2num(copytext(border_color2, 6, 8))
- var/ba2 = hex2num(copytext(border_color2, 8, 10))
-
- return animate_rune_full(input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, 0, 0, 0, alpha, 0, 0, 0, alpha2, 0, 0, 0, 0, 0, 0, 0, 0, frames)
-
-
-/proc/inanimate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000")
- var/icon/base = create_border_image(input, "#00ff0000", "#ff000000")
-
- base.MapColors(rune_color, border_color, "#00000000", "#000000ff", "#00000000")
-
- return base
-
-var/list/rune_animation = list(
- list(0.000, 5),
- list(0.020, 1),
- list(0.050, 1),
- list(0.090, 1),
- list(0.140, 1),
- list(0.200, 1),
- list(0.270, 1),
- list(0.340, 1),
- list(0.420, 1),
- list(0.500, 1),
- list(0.590, 1),
- list(0.675, 1),
- list(0.750, 1),
- list(0.900, 1),
- list(1.000, 6),
- list(0.875, 1),
- list(0.750, 1),
- list(0.625, 1),
- list(0.500, 1),
- list(0.375, 1),
- list(0.250, 1),
- list(0.125, 1),
- )
-
-/var/list/rune_cache = list()
-
-/proc/get_rune(rune_bits, animated = 0)
- var/lookup = "[rune_bits]-[animated]"
-
- if(lookup in rune_cache)
- return rune_cache[lookup]
-
- var/icon/base = icon('icons/effects/uristrunes.dmi', "")
-
- for(var/i = 0, i < 10, i++)
- if(rune_bits & (1 << i))
- base.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/icon/result
-
- if(animated == 1)
- result = animate_rune(base)
-
- else
- result = inanimate_rune(base)
-
- rune_cache[lookup] = result
- return result
-
-
-
-
-
-// Testing procs and Fun procs
-
-
-
-
-/mob/verb/create_rune()
- var/obj/o = new(locate(x, y, z))
- o.icon = get_rune(rand(1, 1023), 1)
-
-/mob/verb/runes_15x15()
- for(var/turf/t in range(7))
- var/obj/o = new /obj(t)
- o.icon = get_rune(rand(1, 1023), 1)
-
-
-/*
-/mob/verb/create_rune_custom(rune as num, color1 as color, border1 as color, color2 as color, border2 as color, alpha1 as num, alpha2 as num)
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
-
- for(var/i = 0, i < 10, i++)
- if(rune & (1 << i))
- I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/obj/o = new(locate(x, y, z))
- o.icon = animate_rune(I, color1, border1, color2, border2, alpha1, alpha2)
-
-/mob/verb/spam()
- for(var/turf/t in range(4))
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
-
- var/rune = rand(1, 1023)
- for(var/i = 0, i < 10, i++)
- if(rune & (1 << i))
- I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/obj/o = new(t)
- o.icon = animate_rune_full(I, rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- 0, 0, 0, rand(0, 255),
- 0, 0, 0, rand(0, 255),
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- list(
- list(0.000, 5),
- list(0.020, 1),
- list(0.050, 1),
- list(0.090, 1),
- list(0.140, 1),
- list(0.200, 1),
- list(0.270, 1),
- list(0.340, 1),
- list(0.420, 1),
- list(0.500, 1),
- list(0.590, 1),
- list(0.675, 1),
- list(0.750, 1),
- list(0.900, 1),
- list(1.000, 6),
- list(0.875, 1),
- list(0.750, 1),
- list(0.625, 1),
- list(0.500, 1),
- list(0.375, 1),
- list(0.250, 1),
- list(0.125, 1),
- ))
-*/
\ No newline at end of file
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index e355194ddfc..e81ade4287a 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -571,7 +571,7 @@
playsound(src,'sound/weapons/resonator_blast.ogg',50,1)
if(creator)
for(var/mob/living/L in src.loc)
- add_logs(creator, L, "used a resonator field on", object="resonator")
+ add_logs(L, creator, "used a resonator field on", object="resonator")
L << "The [src.name] ruptured with you in it!"
L.adjustBruteLoss(resonance_damage)
else
@@ -656,7 +656,7 @@
return
..()
-/mob/living/simple_animal/hostile/mining_drone/death()
+/mob/living/simple_animal/hostile/mining_drone/Die()
..()
visible_message("[src] is destroyed!")
new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc)
@@ -707,11 +707,11 @@
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
var/obj/item/weapon/ore/O
for(O in src.loc)
- O.loc = src
+ O.forceMove(src)
for(var/dir in alldirs)
var/turf/T = get_step(src,dir)
for(O in T)
- O.loc = src
+ O.forceMove(src)
return
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre()
@@ -719,7 +719,7 @@
return
for(var/obj/item/weapon/ore/O in contents)
contents -= O
- O.loc = src.loc
+ O.forceMove(loc)
return
/mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss()
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 7cdbe6ebd50..18025f89b1e 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -17,3 +17,7 @@
/mob/camera/Destroy()
..()
return QDEL_HINT_HARDDEL_NOW
+
+/mob/camera/Login()
+ ..()
+ update_interface()
diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm
index e5041e959c1..f6fcac54798 100644
--- a/code/modules/mob/dead/observer/login.dm
+++ b/code/modules/mob/dead/observer/login.dm
@@ -2,4 +2,6 @@
..()
if (ghostimage)
ghostimage.icon_state = src.icon_state
- updateghostimages()
\ No newline at end of file
+ updateghostimages()
+
+ update_interface()
\ No newline at end of file
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index 8f2cfc88a03..5a104fbfb53 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -3,6 +3,20 @@
#define BLOODCRAWL_EAT 2
/mob/living/proc/phaseout(var/obj/effect/decal/cleanable/B)
+
+ if(iscarbon(src))
+ var/mob/living/carbon/C = src
+ if(C.l_hand || C.r_hand)
+ C << "You may not hold items while blood crawling!"
+ return 0
+ var/obj/item/weapon/bloodcrawl/B1 = new(C)
+ var/obj/item/weapon/bloodcrawl/B2 = new(C)
+ B1.icon_state = "bloodhand_left"
+ B2.icon_state = "bloodhand_right"
+ C.put_in_hands(B1)
+ C.put_in_hands(B2)
+ C.regenerate_icons()
+
var/mob/living/kidnapped = null
var/turf/mobloc = get_turf(src.loc)
var/turf/bloodloc = get_turf(B.loc)
@@ -29,10 +43,11 @@
if(istype(src.pulling, /mob/living/))
var/mob/living/victim = src.pulling
if(victim.stat == CONSCIOUS)
- src.visible_message("[victim] kicks free of \the [src] at the last second!")
+ src.visible_message("[victim] kicks free of [B] just before entering it!")
else
victim.loc = holder///holder
- src.visible_message("\The [src] drags [victim] into [B]!")
+ victim.emote("scream")
+ src.visible_message("[src] drags [victim] into [B]!")
kidnapped = victim
flick("jaunt",animation)
src.loc = holder
@@ -44,32 +59,44 @@
sleep(6)
if (animation)
qdel(animation)
- playsound(get_turf(src),'sound/misc/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/misc/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/misc/Demon_consume.ogg', 100, 1)
- sleep(30)
- src << "You devour [kidnapped]. Your health is fully restored."
- src.adjustBruteLoss(-1000)
- src.adjustFireLoss(-1000)
- src.adjustOxyLoss(-1000)
- src.adjustToxLoss(-1000)
- kidnapped.ghostize()
- qdel(kidnapped)
- if (istype(src, /mob/living/simple_animal/slaughter)) //rason, do not want humans to get this
+ for(var/i = 3; i > 0; i--)
+ playsound(get_turf(src),'sound/misc/Demon_consume.ogg', 100, 1)
+ sleep(30)
+ if (kidnapped)
+ src << "You devour [kidnapped]. Your health is fully restored."
+ src.adjustBruteLoss(-1000)
+ src.adjustFireLoss(-1000)
+ src.adjustOxyLoss(-1000)
+ src.adjustToxLoss(-1000)
- var/mob/living/simple_animal/slaughter/demon = src
- demon.devoured++
+ if (istype(src, /mob/living/simple_animal/slaughter)) //rason, do not want humans to get this
+
+ var/mob/living/simple_animal/slaughter/demon = src
+ demon.devoured++
+ kidnapped << "You feel teeth sink into your flesh, and the--"
+ kidnapped.adjustBruteLoss(1000)
+ kidnapped.forceMove(src)
+ demon.consumed_mobs.Add(kidnapped)
+ else
+ kidnapped.ghostize()
+ qdel(kidnapped)
+ else
+ src << "You happily devour... nothing? Your meal vanished at some point!"
else
sleep(6)
if (animation)
qdel(animation)
src.notransform = 0
+/obj/item/weapon/bloodcrawl
+ name = "blood crawl"
+ desc = "You are unable to hold anything while in this form."
+ icon = 'icons/effects/blood.dmi'
+ flags = NODROP
+
/mob/living/proc/phasein(var/obj/effect/decal/cleanable/B)
if(src.notransform)
- src << "Finish eating first!"
+ src << "Finish eating first!"
else
var/atom/movable/overlay/animation = new /atom/movable/overlay( B.loc )
animation.name = "odd blood"
@@ -80,19 +107,34 @@
animation.layer = 5
animation.master = B.loc
animation.dir = src.dir
- flick("jauntup",animation)
- src.loc = B.loc
+ B.visible_message("[B] starts to bubble...")
+ if(!do_after(src, 20, target = B))
+ return
+ if(!B)
+ return
+ src.forceMove(B)
src.client.eye = src
- if (prob(25))
+ if (prob(25) && istype(src, /mob/living/simple_animal/slaughter))
var/list/voice = list('sound/hallucinations/behind_you1.ogg','sound/hallucinations/im_here1.ogg','sound/hallucinations/turn_around1.ogg','sound/hallucinations/i_see_you1.ogg')
playsound(get_turf(src), pick(voice),50, 1, -1)
src.visible_message("\The [src] rises out of \the [B]!")
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1)
+ flick("jauntup",animation)
qdel(src.holder)
src.holder = null
- sleep(6)
+ if(iscarbon(src))
+ var/mob/living/carbon/C = src
+ for(var/obj/item/weapon/bloodcrawl/BC in C)
+ C.flags = null
+ C.unEquip(BC)
+ qdel(BC)
+ var/oldcolor = src.color
+ src.color = B.color
+ sleep(6)//wait for animation to finish
if(animation)
qdel(animation)
+ spawn(30)
+ src.color = oldcolor
/obj/effect/decal/cleanable/blood/CtrlClick(mob/living/user)
..()
diff --git a/code/modules/mob/living/carbon/alien/alien_defenses.dm b/code/modules/mob/living/carbon/alien/alien_defenses.dm
index 8d0c36bc05d..ed98e221993 100644
--- a/code/modules/mob/living/carbon/alien/alien_defenses.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defenses.dm
@@ -35,7 +35,7 @@ In all, this is a lot like the monkey code. /N
visible_message("[M.name] bites [src]!", \
"[M.name] bites [src]!")
adjustBruteLoss(damage)
- add_logs(M, src, "attacked", admin=0)
+ add_logs(src, M, "attacked", admin=0)
updatehealth()
else
M << "[name] is too injured for that."
@@ -67,4 +67,4 @@ In all, this is a lot like the monkey code. /N
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
adjustBruteLoss(damage)
- updatehealth()
+ updatehealth()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm
index 40303b03543..693763e4960 100644
--- a/code/modules/mob/living/carbon/alien/death.dm
+++ b/code/modules/mob/living/carbon/alien/death.dm
@@ -53,7 +53,7 @@
if(client) blind.layer = 0
update_icons()
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
index a80a0d5892c..69d1eb600dc 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm
index 67edcfd04ca..574b617ca58 100644
--- a/code/modules/mob/living/carbon/alien/larva/death.dm
+++ b/code/modules/mob/living/carbon/alien/larva/death.dm
@@ -9,8 +9,8 @@
update_canmove()
if(client) blind.layer = 0
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
living_mob_list -= src
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm
index 12ad431f3c3..134350e2517 100644
--- a/code/modules/mob/living/carbon/alien/larva/emote.dm
+++ b/code/modules/mob/living/carbon/alien/larva/emote.dm
@@ -1,5 +1,7 @@
/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null)
-
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm
index 17bf26de838..efcfac98624 100644
--- a/code/modules/mob/living/carbon/brain/death.dm
+++ b/code/modules/mob/living/carbon/brain/death.dm
@@ -11,8 +11,8 @@
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0) //mind. ?
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) //mind. ?
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm
index 0441eb00ac4..054a9b6e71c 100644
--- a/code/modules/mob/living/carbon/brain/emote.dm
+++ b/code/modules/mob/living/carbon/brain/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return
diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm
index ff2b98d430f..bc0226f4597 100644
--- a/code/modules/mob/living/carbon/human/appearance.dm
+++ b/code/modules/mob/living/carbon/human/appearance.dm
@@ -110,7 +110,7 @@
return 1
/mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue)
- if(red == r_skin && green == g_skin && blue == b_skin || !(species.flags & HAS_SKIN_COLOR))
+ if(red == r_skin && green == g_skin && blue == b_skin || !(species.bodyflags & HAS_SKIN_COLOR))
return
r_skin = red
@@ -122,7 +122,7 @@
return 1
/mob/living/carbon/human/proc/change_skin_tone(var/tone)
- if(s_tone == tone || !(species.flags & HAS_SKIN_TONE))
+ if(s_tone == tone || !(species.bodyflags & HAS_SKIN_TONE))
return
s_tone = tone
@@ -182,4 +182,3 @@
valid_facial_hairstyles += facialhairstyle
return valid_facial_hairstyles
-
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index a9cf1ea1094..4307c6cbd0b 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -133,8 +133,8 @@
update_canmove()
if(client) blind.layer = 0
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
if(ticker && ticker.mode)
// log_to_dd("k")
sql_report_death(src)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index a3212ca2510..f7e988f3a70 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
@@ -17,8 +20,6 @@
if (I.implanted)
I.trigger(act, src)
-
-
//Emote Cooldown System (it's so simple!)
// proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
var/on_CD = 0
@@ -42,9 +43,12 @@
if(on_CD == 1) // Check if we need to suppress the emote attempt.
return // Suppress emote, you're still cooling off.
- //--FalseIncarnate
switch(act)
+ if("me") //OKAY SO RANT TIME, THIS FUCKING HAS TO BE HERE OR A SHITLOAD OF THINGS BREAK
+ return custom_emote(m_type, message) //DO YOU KNOW WHY SHIT BREAKS? BECAUSE SO MUCH OLDCODE CALLS mob.emote("me",1,"whatever_the_fuck_it_wants_to_emote")
+ //WHO THE FUCK THOUGHT THAT WAS A GOOD FUCKING IDEA!?!?
+
if("ping")
var/M = null
if(param)
@@ -330,7 +334,7 @@
m_type = 2
if ("deathgasp")
- message = "[src] seizes up and falls limp, \his eyes dead and lifeless..."
+ message = "[src] [species.death_message]"
m_type = 1
if ("giggle")
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0e943d8c257..1b1964a000f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -10,6 +10,11 @@
var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna=0)
+
+ if(!dna)
+ dna = new /datum/dna(null)
+ // Species name is handled by set_species()
+
if(!species)
if(new_species)
set_species(new_species,1)
@@ -36,9 +41,6 @@
..()
- if(dna)
- dna.real_name = real_name
-
prev_gender = gender // Debug for plural genders
make_blood()
@@ -46,8 +48,10 @@
faction |= "\ref[M]"
// Set up DNA.
- if(!delay_ready_dna)
+ if(!delay_ready_dna && dna)
dna.ready_dna(src)
+ dna.real_name = real_name
+ sync_organ_dna() //this shouldn't be necessaaaarrrryyyyyyyy
UpdateAppearance()
/mob/living/carbon/human/Destroy()
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index 4f404d1f314..c0587ddee86 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -22,15 +22,6 @@
update_revive()
return
-/mob/living/carbon/human/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair)
- stat = CONSCIOUS
- dead_mob_list -= src
- living_mob_list |= src
- mob_list |= src
- ear_deaf = 0
- tod = 0
- timeofdeath = 0
-
/mob/living/carbon/human/adjustBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index eead644cc58..ef88db4a6dc 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -84,4 +84,4 @@
var/fire_dmi = 'icons/mob/OnFire.dmi'
var/fire_sprite = "Standing"
- var/datum/body_accessory/body_accessory = null
+ var/datum/body_accessory/body_accessory = null
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index f61318e09c6..b54c7f5ee36 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -24,20 +24,10 @@
if(wear_suit)
tally += wear_suit.slowdown
- if(!buckled || (buckled && !istype(buckled, /obj/structure/stool/bed/chair/wheelchair)))
+ if(!buckled)
if(shoes)
tally += shoes.slowdown
- if(buckled && istype(buckled, /obj/structure/stool/bed/chair/wheelchair))
- for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm"))
- var/obj/item/organ/external/E = get_organ(organ_name)
- if(!E || (E.status & ORGAN_DESTROYED))
- tally += 4
- else if(E.status & ORGAN_SPLINTED)
- tally += 0.5
- else if(E.status & ORGAN_BROKEN)
- tally += 1.5
-
if(shock_stage >= 10) tally += 3
if(back)
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index 8889e5370da..7654b0d2e3b 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -144,4 +144,9 @@
//New are added for reagents to random organs.
for(var/datum/reagent/A in reagents.reagent_list)
var/obj/item/organ/O = pick(organs)
- O.trace_chemicals[A.name] = 100
\ No newline at end of file
+ O.trace_chemicals[A.name] = 100
+
+/mob/living/carbon/human/proc/sync_organ_dna()
+ var/list/all_bits = internal_organs|organs
+ for(var/obj/item/organ/O in all_bits)
+ O.set_dna(dna)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 875a3a85260..8967e1519d6 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -768,7 +768,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
light_amount = T.get_lumcount()*10
if(light_amount > species.light_dam && !incorporeal_move) //if there's enough light, start dying
if(species.light_effect_amp)
- adjustFireLoss(5) //This gets doubled by Shadowling's innate fire weakness, so it ends up being 10.
+ adjustFireLoss(4.7) //This gets multiplied by 1.5 due to Shadowling's innate fire weakness, so it ends up being about 7.
else
adjustFireLoss(1)
adjustBruteLoss(1)
@@ -968,7 +968,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
var/obj/item/organ/vision
if(species.vision_organ)
vision = internal_organs_by_name[species.vision_organ]
-
+
if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
eye_blind = 0
blinded = 0
@@ -977,7 +977,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
eye_blind = 1
blinded = 1
eye_blurry = 1
- else
+ else
//blindness
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
blinded = 1
@@ -987,7 +987,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
eye_blurry = max(eye_blurry-3, 0)
blinded = 1
-
+
//blurry sight
if(vision.is_bruised()) // Vision organs impaired? Permablurry.
eye_blurry = 1
@@ -1220,13 +1220,17 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(ANTAGHUD)
process_antag_hud(src)
-
-
-
else if(!seer)
see_in_dark = species.darksight
see_invisible = SEE_INVISIBLE_LIVING
-
+
+ if(vision_type)
+ see_in_dark = max(see_in_dark, vision_type.see_in_dark, species.darksight)
+ see_invisible = vision_type.see_invisible
+ if(vision_type.light_sensitive)
+ weakeyes = 1
+ sight |= vision_type.sight_flags
+
if(see_override) //Override all
see_invisible = see_override
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm
index 14372e6c976..28862cf6cfc 100644
--- a/code/modules/mob/living/carbon/human/login.dm
+++ b/code/modules/mob/living/carbon/human/login.dm
@@ -5,5 +5,6 @@
src << "You can ventcrawl! Use alt+click on vents to quickly travel about the station."
update_pipe_vision()
update_hud()
- ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them.
+ if(ticker && ticker.mode)
+ ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them.
return
diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm
index d8487e8d795..c7c6f49bd57 100644
--- a/code/modules/mob/living/carbon/human/species/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/monkey.dm
@@ -17,6 +17,7 @@
ventcrawler = 1
show_ssd = 0
eyes = "blank_eyes"
+ death_message = "lets out a faint chimper as it collapses and stops moving..."
tail = "chimptail"
bodyflags = FEET_PADDED | HAS_TAIL
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 09bd76f00eb..2f50a3a4d51 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -84,6 +84,9 @@
var/virus_immune
var/can_revive_by_healing // Determines whether or not this species can be revived by simply healing them
+ //Death vars.
+ var/death_message = "seizes up and falls limp, their eyes dead and lifeless..."
+
// Language/culture vars.
var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers.
var/language = "Galactic Common" // Default racial language, if any.
diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm
index b525919b5bc..9cd0301b885 100644
--- a/code/modules/mob/living/carbon/human/species/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station.dm
@@ -59,7 +59,7 @@
/datum/species/unathi/handle_death(var/mob/living/carbon/human/H)
H.stop_tail_wagging(1)
-
+
/datum/species/unathi/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown")
H.unEquip(H.shoes)
@@ -105,7 +105,7 @@
/datum/species/tajaran/handle_death(var/mob/living/carbon/human/H)
H.stop_tail_wagging(1)
-
+
/datum/species/tajaran/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown")
H.unEquip(H.shoes)
@@ -219,7 +219,7 @@
i++
newname += pick(vox_name_syllables)
return capitalize(newname)
-
+
/datum/species/vox/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime")
H.unEquip(H.wear_mask)
@@ -235,7 +235,7 @@
H.internal = H.l_hand
if (H.internals)
H.internals.icon_state = "internal1"
-
+
/*
/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H)
H.verbs += /mob/living/carbon/human/proc/leap
@@ -469,23 +469,24 @@
/datum/species/machine
name = "Machine"
name_plural = "Machines"
-
+
blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \
robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \
to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \
generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \
- inhuman in outlook and perspective."
-
+ inhuman in outlook and perspective."
+
icobase = 'icons/mob/human_races/r_machine.dmi'
deform = 'icons/mob/human_races/r_machine.dmi'
path = /mob/living/carbon/human/machine
default_language = "Galactic Common"
language = "Trinary"
unarmed_type = /datum/unarmed_attack/punch
-
+
eyes = "blank_eyes"
brute_mod = 2.5 // 100% * 2.5 * 0.6 (robolimbs) ~= 150%
burn_mod = 2.5 // So they take 50% extra damage from brute/burn overall.
+ death_message = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off..."
cold_level_1 = 50
cold_level_2 = -1
@@ -500,20 +501,21 @@
flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_DNA_RAD
clothing_flags = HAS_SOCKS
+ bodyflags = HAS_SKIN_COLOR
dietflags = 0 //IPCs can't eat, so no diet
blood_color = "#1F181F"
flesh_color = "#AAAAAA"
virus_immune = 1
can_revive_by_healing = 1
reagent_tag = PROCESS_SYN
-
+
has_organ = list(
"brain" = /obj/item/organ/mmi_holder/posibrain,
"cell" = /obj/item/organ/cell,
"optics" = /obj/item/organ/optical_sensor
)
- vision_organ = "optics"
+ vision_organ = "optics"
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/ipc),
"groin" = list("path" = /obj/item/organ/external/groin/ipc),
@@ -532,7 +534,7 @@
H.h_style = ""
spawn(100)
if(H) H.update_hair()
-
+
/datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H)
..()
- H.verbs += /mob/living/carbon/human/proc/change_monitor
\ No newline at end of file
+ H.verbs += /mob/living/carbon/human/proc/change_monitor
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4c99dd12895..86c2d79eb7b 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -238,15 +238,13 @@ var/global/list/damage_icon_parts = list()
var/hulk = (HULK in src.mutations)
var/skeleton = (SKELETON in src.mutations)
- var/g = (gender == FEMALE ? "f" : "m")
-
//CACHING: Generate an index key from visible bodyparts.
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
//Create a new, blank icon for our mob to use.
if(stand_icon)
qdel(stand_icon)
stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank")
- var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]"
+ var/icon_key = ""
var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"]
if(eyes)
@@ -265,6 +263,13 @@ var/global/list/damage_icon_parts = list()
else
icon_key += "1"
+ if(part)
+ icon_key += "[part.species.race_key]"
+ icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]"
+ icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]"
+ if(part.s_col)
+ icon_key += "[rgb(part.s_col[1], part.s_col[2], part.s_col[3])]"
+
icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]"
var/icon/base_icon
@@ -868,8 +873,8 @@ var/global/list/damage_icon_parts = list()
var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]")
I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension)
- overlays_standing[R_HAND_LAYER] = I
-
+ overlays_standing[R_HAND_LAYER] = I
+
if (handcuffed) drop_r_hand()
else
overlays_standing[R_HAND_LAYER] = null
diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm
index 2cbc139f5a1..3c95bea1a43 100644
--- a/code/modules/mob/living/carbon/metroid/emote.dm
+++ b/code/modules/mob/living/carbon/metroid/emote.dm
@@ -1,5 +1,6 @@
/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
-
+ if(stat)
+ return
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 6ead72a36f5..808f8b3e772 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -317,9 +317,16 @@
C.reagents.addiction_list.Cut()
hud_updateflag |= 1 << HEALTH_HUD
hud_updateflag |= 1 << STATUS_HUD
+
+/mob/living/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair)
+ stat = CONSCIOUS
+ dead_mob_list -= src
+ living_mob_list |= src
+ mob_list |= src
+ ear_deaf = 0
+ timeofdeath = 0
/mob/living/proc/rejuvenate()
-
// shut down various types of badness
setToxLoss(0)
setOxyLoss(0)
@@ -367,10 +374,9 @@
human_mob.decaylevel = 0
restore_all_organs()
- if(stat == 2)
+ if(stat == DEAD)
dead_mob_list -= src
living_mob_list += src
- tod = null
timeofdeath = 0
stat = CONSCIOUS
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index cf6204e710c..08a99c0dba2 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -34,8 +34,6 @@
var/atom/movable/cameraFollow = null
- var/tod = null // Time of death
-
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index d4fbd5c1ec0..9c3cac087a4 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -1,4 +1,3 @@
-
/mob/living/Login()
..()
//Mind updates
@@ -12,6 +11,8 @@
src << "You can ventcrawl! Use alt+click on vents to quickly travel about the station."
//Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways.
update_pipe_vision()
+
+ update_interface()
//Round specific stuff like hud updates
if(ticker && ticker.mode)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 286b2eebd64..5c41901fa21 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -1,9 +1,7 @@
-#define AI_CHECK_WIRELESS 1
-#define AI_CHECK_RADIO 2
-
var/list/ai_list = list()
var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/announcement,
+ /mob/living/silicon/ai/proc/ai_announcement_text,
/mob/living/silicon/ai/proc/ai_call_shuttle,
/mob/living/silicon/ai/proc/ai_camera_track,
/mob/living/silicon/ai/proc/ai_camera_list,
@@ -79,6 +77,7 @@ var/list/ai_verbs_default = list(
var/last_paper_seen = null
var/can_shunt = 1
var/last_announcement = ""
+ var/datum/announcement/priority/announcement
var/obj/machinery/bot/Bot
var/turf/waypoint //Holds the turf of the currently selected waypoint.
var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking.
@@ -97,6 +96,12 @@ var/list/ai_verbs_default = list(
src.verbs -= silicon_subsystems
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
+ announcement = new()
+ announcement.title = "A.I. Announcement"
+ announcement.announcement_type = "A.I. Announcement"
+ announcement.announcer = name
+ announcement.newscast = 1
+
var/list/possibleNames = ai_names
var/pickedName = null
@@ -210,6 +215,8 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/SetName(pickedName as text)
..()
+
+ announcement.announcer = name
if(eyeobj)
eyeobj.name = "[pickedName] (AI Eye)"
@@ -325,15 +332,35 @@ var/list/ai_verbs_default = list(
set name = "Show Crew Manifest"
set category = "AI Commands"
show_station_manifest()
+
+/mob/living/silicon/ai/var/message_cooldown = 0
+/mob/living/silicon/ai/proc/ai_announcement_text()
+ set category = "AI Commands"
+ set name = "Make Station Announcement"
+
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
+ return
+
+ if(message_cooldown)
+ src << "Please allow one minute to pass between announcements."
+ return
+
+ var/input = input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement") as message|null
+ if(!input)
+ return
+
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
+ return
+
+ announcement.Announce(input)
+ message_cooldown = 1
+ spawn(600)//One minute cooldown
+ message_cooldown = 0
/mob/living/silicon/ai/proc/ai_call_shuttle()
set name = "Call Emergency Shuttle"
set category = "AI Commands"
- if(src.stat == DEAD)
- src << "You can't call the shuttle because you are dead!"
- return
-
if(check_unable(AI_CHECK_WIRELESS))
return
@@ -356,11 +383,7 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/ai_cancel_call()
set name = "Recall Emergency Shuttle"
set category = "AI Commands"
-
- if(src.stat == 2)
- src << "You can't send the shuttle back because you are dead!"
- return
-
+
if(check_unable(AI_CHECK_WIRELESS))
return
@@ -394,10 +417,6 @@ var/list/ai_verbs_default = list(
set desc = "Create a vocal announcement by typing in the available words to create a sentence."
set category = "AI Commands"
- if(src.stat == 2)
- src << "You can't call make an announcement because you are dead!"
- return
-
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
@@ -838,7 +857,7 @@ var/list/ai_verbs_default = list(
set desc = "Change the message that's transmitted when a new crew member arrives on station."
set category = "AI Commands"
- var/newmsg = input("What would you like the arrival message to be? Use $name to substitute the crew member's name, and use $rank to substitute the crew member's rank.", "Change Arrival Message", arrivalmsg) as text
+ var/newmsg = input("What would you like the arrival message to be? List of options: $name, $rank, $species, $gender, $age", "Change Arrival Message", arrivalmsg) as text
if(newmsg != arrivalmsg)
arrivalmsg = newmsg
usr << "The arrival message has been successfully changed."
@@ -949,14 +968,14 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/check_unable(var/flags = 0)
if(stat == DEAD)
- usr << "\red You are dead!"
+ usr << "You are dead!"
return 1
if((flags & AI_CHECK_WIRELESS) && src.control_disabled)
- usr << "\red Wireless control is disabled!"
+ usr << "Wireless control is disabled!"
return 1
if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi)
- src << "\red System Error - Transceiver Disabled!"
+ src << "System Error - Transceiver Disabled!"
return 1
return 0
@@ -980,7 +999,3 @@ var/list/ai_verbs_default = list(
loc = card//Throw AI into the card.
src << "You have been downloaded to a mobile storage device. Remote device connection severed."
user << "Transfer successful: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
-
-#undef AI_CHECK_WIRELESS
-#undef AI_CHECK_RADIO
-
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index dfa05ddc5d0..fe96da3c35e 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -53,7 +53,7 @@
if (istype(loc, /obj/item/device/aicard))
loc.icon_state = "aicard-404"
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
return ..(gibbed)
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 96954d82d25..55eed0a2570 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -28,13 +28,19 @@ var/const/VOX_PATH = "sound/vox_fem/"
popup.open()
/mob/living/silicon/ai/proc/ai_announcement()
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
+ return
+
if(announcing_vox > world.time)
- src << "Please wait [round((announcing_vox - world.time) / 10)] seconds."
+ src << "Please wait [round((announcing_vox - world.time) / 10)] seconds."
return
- var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", src.last_announcement) as text
+ var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement) as message|null
last_announcement = message
+
+ if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
+ return
if(!message || announcing_vox > world.time)
return
@@ -54,7 +60,7 @@ var/const/VOX_PATH = "sound/vox_fem/"
incorrect_words += word
if(incorrect_words.len)
- src << "These words are not available on the announcement system: [english_list(incorrect_words)]."
+ src << "These words are not available on the announcement system: [english_list(incorrect_words)]."
return
announcing_vox = world.time + VOX_DELAY
diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm
index f7ead12e4cc..8c28d407ede 100644
--- a/code/modules/mob/living/silicon/emote.dm
+++ b/code/modules/mob/living/silicon/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm
index 8fccd74ff39..9cb442e3d37 100644
--- a/code/modules/mob/living/silicon/laws.dm
+++ b/code/modules/mob/living/silicon/laws.dm
@@ -12,7 +12,8 @@
/mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg)
laws_sanity_check()
laws.set_zeroth_law(law, law_borg)
- log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
/mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg)
..()
@@ -22,39 +23,43 @@
/mob/living/silicon/proc/add_ion_law(var/law)
laws_sanity_check()
laws.add_ion_law(law)
- log_and_message_admins("has given [src] the ion law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the ion law: [law]")
/mob/living/silicon/proc/add_inherent_law(var/law)
laws_sanity_check()
laws.add_inherent_law(law)
- log_and_message_admins("has given [src] the inherent law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the inherent law: [law]")
/mob/living/silicon/proc/add_supplied_law(var/number, var/law)
laws_sanity_check()
laws.add_supplied_law(number, law)
- log_and_message_admins("has given [src] the supplied law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the supplied law: [law]")
/mob/living/silicon/proc/delete_law(var/datum/ai_law/law)
laws_sanity_check()
laws.delete_law(law)
- log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0)
laws_sanity_check()
laws.clear_inherent_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the inherent laws of [src]")
/mob/living/silicon/proc/clear_ion_laws(var/silent = 0)
laws_sanity_check()
laws.clear_ion_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the ion laws of [src]")
/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0)
laws_sanity_check()
laws.clear_supplied_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the supplied laws of [src]")
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm
index a8eeac8cbb7..2fce92f2883 100644
--- a/code/modules/mob/living/silicon/pai/emote.dm
+++ b/code/modules/mob/living/silicon/pai/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
switch(act)
if ("help")
src << "ping, beep, buzz."
diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm
index d0469bc42dc..7eb1e62090c 100644
--- a/code/modules/mob/living/silicon/robot/component.dm
+++ b/code/modules/mob/living/silicon/robot/component.dm
@@ -1,14 +1,15 @@
// TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system
-/datum/robot_component/var/name
-/datum/robot_component/var/installed = 0
-/datum/robot_component/var/powered = 0
-/datum/robot_component/var/toggled = 1
-/datum/robot_component/var/brute_damage = 0
-/datum/robot_component/var/electronics_damage = 0
-/datum/robot_component/var/energy_consumption = 0
-/datum/robot_component/var/max_damage = 30
-/datum/robot_component/var/mob/living/silicon/robot/owner
+/datum/robot_component
+ var/name = "Component"
+ var/installed = 0
+ var/powered = 1
+ var/toggled = 1
+ var/brute_damage = 0
+ var/electronics_damage = 0
+ var/energy_consumption = 0
+ var/max_damage = 30
+ var/mob/living/silicon/robot/owner
// The actual device object that has to be installed for this.
/datum/robot_component/var/external_type = null
@@ -206,8 +207,8 @@
user << "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health - M.halloss]% functional"]"
user << "\t Key: Electronics/Brute"
user << "\t Damage Specifics: [BU] - [BR]"
- if(M.tod && M.stat == DEAD)
- user << "Time of Disable: [M.tod]"
+ if(M.timeofdeath && M.stat == DEAD)
+ user << "Time of Disable: [M.timeofdeath]"
var/mob/living/silicon/robot/H = M
var/list/damaged = H.get_damaged_components(1,1,1)
user << "Localized Damage:"
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index cf9427242d8..cafb53d8621 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -62,8 +62,8 @@
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
update_icons()
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
sql_report_cyborg_death(src)
diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm
index 9c01f9ee5ec..45a086f0fe7 100644
--- a/code/modules/mob/living/silicon/robot/emote.dm
+++ b/code/modules/mob/living/silicon/robot/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/robot/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index 84b31b16766..6d030c026b8 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -1,9 +1,11 @@
/mob/living/silicon/robot/Login()
..()
+ if(client)
+ client.hotkeytype = "Cyborg"
regenerate_icons()
show_laws(0)
if(mind) ticker.mode.remove_cultist(mind)
if(mind) ticker.mode.remove_revolutionary(mind)
if(mind) ticker.mode.remove_thrall(mind,0)
if(mind) ticker.mode.remove_shadowling(mind)
- return
\ No newline at end of file
+ return
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 3f5ed10edc5..f355b00ff2f 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -377,6 +377,17 @@ var/list/robot_verbs_default = list(
updatename()
update_icons()
+//for borg hotkeys, here module refers to borg inv slot, not core module
+/mob/living/silicon/robot/verb/cmd_toggle_module(module as num)
+ set name = "Toggle Module"
+ set hidden = 1
+ toggle_module(module)
+
+/mob/living/silicon/robot/verb/cmd_unequip_module()
+ set name = "Unequip Module"
+ set hidden = 1
+ uneq_active()
+
// this verb lets cyborgs see the stations manifest
/mob/living/silicon/robot/verb/cmd_station_manifest()
set category = "Robot Commands"
@@ -729,20 +740,20 @@ var/list/robot_verbs_default = list(
else if(istype(W, /obj/item/borg/upgrade/))
var/obj/item/borg/upgrade/U = W
if(!opened)
- usr << "You must access the borgs internals!"
+ user << "You must access the borgs internals!"
else if(!src.module && U.require_module)
- usr << "The borg must choose a module before he can be upgraded!"
+ user << "The borg must choose a module before it can be upgraded!"
else if(U.locked)
- usr << "The upgrade is locked and cannot be used yet!"
+ user << "The upgrade is locked and cannot be used yet!"
else
+ if(!user.drop_item())
+ return
if(U.action(src))
- usr << "You apply the upgrade to [src]!"
- usr.drop_item()
- U.loc = src
+ user << "You apply the upgrade to [src]."
+ U.forceMove(src)
else
- usr << "Upgrade error!"
-
-
+ user << "Upgrade error."
+
else
spark_system.start()
return ..()
@@ -1135,7 +1146,7 @@ var/list/robot_verbs_default = list(
S.dirt = 0
for(var/A in tile)
if(istype(A, /obj/effect))
- if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay))
+ if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm
index 9a1c713ab72..fa3dcfd2cfa 100644
--- a/code/modules/mob/living/silicon/subsystems.dm
+++ b/code/modules/mob/living/silicon/subsystems.dm
@@ -81,7 +81,7 @@
set name = "Law Manager"
set category = "Subsystems"
- law_manager.ui_interact(usr, state = self_state)
+ law_manager.ui_interact(usr, state = conscious_state)
/********************
* Power Monitor *
diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm
index f4d1dc0ffc2..95caf726186 100644
--- a/code/modules/mob/living/simple_animal/friendly/diona.dm
+++ b/code/modules/mob/living/simple_animal/friendly/diona.dm
@@ -249,7 +249,18 @@
return
/mob/living/simple_animal/diona/emote(var/act, var/m_type=1, var/message = null)
- if(stat) return
+ if(stat)
+ return
+
+ var/on_CD = 0
+ switch(act)
+ if("chirp")
+ on_CD = handle_emote_CD()
+ else
+ on_CD = 0
+
+ if(on_CD == 1)
+ return
switch(act) //IMPORTANT: Emotes MUST NOT CONFLICT anywhere along the chain.
if("chirp")
diff --git a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm b/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
index 4299af828dc..165b56a6f13 100644
--- a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
@@ -37,7 +37,13 @@
/mob/living/simple_animal/hostile/poison/bees/New()
..()
- update_bees()
+ var/bees = rand(2, 10)
+ for(var/i, i <= bees, i++)
+ var/N = rand(1, 4)
+ var/image/I = image(icon='icons/mob/animal.dmi',icon_state="bee_[N]", pixel_x = rand(-8, 8), pixel_y = rand(-8, 8))
+ overlays += I
+
+ //update_bees()
/mob/living/simple_animal/hostile/poison/bees/Die()
..()
@@ -47,7 +53,8 @@
/mob/living/simple_animal/hostile/poison/bees/Life()
..()
- update_bees()
+
+/* update_bees()
/mob/living/simple_animal/hostile/poison/bees/proc/update_bees()
while(overlays.len != health-1) //how many bees do we have in the swarm?
@@ -56,9 +63,9 @@
if(overlays.len < health-1)
overlays.Add(I)
if(overlays.len > health-1)
- overlays.Remove(I)
- poison_per_bite = health * 0.5 //each bee is half a toxin reagent
+ overlays.Remove(I) //REMOVING A RANDOM IMAGE FROM AN OVERLAYS LIST THAT DOES NOT CONTAIN THAT IMAGE
+ poison_per_bite = health * 0.5 //each bee is half a toxin reagent //WHAT A GREAT FUCKING PLAN
if(health > 1)
desc = "A buzzy swarm of [health] poisonous space bees, renowned for their aggressiveness"
else
- desc = "Although now lonely, this single space bee is still poisonous and very angry at you."
+ desc = "Although now lonely, this single space bee is still poisonous and very angry at you."*///NOVEL IDEA: INFINITE LOOP IMPLEMENTATION
diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
index a54b0e0e1e2..c1ad9d79f67 100644
--- a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
+++ b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
@@ -1,9 +1,9 @@
//////////////////The Monster
/mob/living/simple_animal/slaughter
- name = "Slaughter Demon"
- real_name = "Slaughter Demon"
- desc = "You should run."
+ name = "slaughter demon"
+ real_name = "slaughter demon"
+ desc = "A large, menacing creature covered in armored black scales. You should run."
speak = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri", "orkan", "allaq")
speak_emote = list("gurgles")
emote_hear = list("wails","screeches")
@@ -43,6 +43,7 @@
var/devoured = 0
+ var/list/consumed_mobs = list()
var/list/nearby_mortals = list()
var/cooldown = 0
@@ -61,6 +62,7 @@
src.mind.current.verbs += /mob/living/simple_animal/slaughter/proc/slaughterWhisper
src << src.playstyle_string
src << "You are not currently in the same plane of existence as the station. Ctrl+Click a blood pool to manifest."
+ src << 'sound/misc/demon_dies.ogg'
if(!(vialspawned))
var/datum/objective/slaughter/objective = new
var/datum/objective/demonFluff/fluffObjective = new
@@ -83,12 +85,19 @@
/mob/living/simple_animal/slaughter/Die()
..()
+ var/obj/effect/decal/cleanable/blood/innards = new (get_turf(src))
+ innards.icon = 'icons/obj/surgery.dmi'
+ innards.icon_state = "innards"
+ innards.name = "pile of viscera"
+ innards.desc = "A repulsive pile of guts and gore."
new /obj/effect/decal/cleanable/blood (src.loc)
new /obj/effect/gibspawner/generic(get_turf(src))
new /obj/effect/gibspawner/generic(get_turf(src))
+ new /obj/item/weapon/demonheart(src.loc)
playsound(get_turf(src),'sound/misc/demon_dies.ogg', 200, 1)
- new /obj/item/weapon/demonheart (src.loc)
- visible_message("The [src] screams in anger as its form collapes into a pool of viscera.")
+ visible_message("[src] screams in anger as it collapses into a puddle of viscera, its most recent meals spilling out of it.")
+ for(var/mob/living/M in consumed_mobs)
+ M.forceMove(get_turf(src))
ghostize()
qdel(src)
@@ -97,7 +106,7 @@
/mob/living/simple_animal/slaughter/phasein()
..()
speed = 0
- boost = world.time + 30
+ boost = world.time + 60
////////////////////The Powers
@@ -128,23 +137,28 @@
//////////The Loot
+//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
/obj/item/weapon/demonheart
- name = "demon's heart"
- desc = "It's still faintly beating with rage"
+ name = "demon heart"
+ desc = "Still it beats furiously, emanating an aura of utter hate."
icon = 'icons/obj/surgery.dmi'
- icon_state = "heart-on"
+ icon_state = "demon_heart"
origin_tech = "combat=5;biotech=8"
/obj/item/weapon/demonheart/attack_self(mob/living/user)
- visible_message("[user] feasts upon the [src].")
+ user.visible_message("[user] raises [src] to their mouth and tears into it with their teeth!", \
+ "An unnatural hunger consumes you. You raise [src] to your mouth and devour it!")
+ playsound(user, 'sound/misc/Demon_consume.ogg', 50, 1)
if(user.bloodcrawl == 0)
- user << "You absorb some of the demon's power!"
+ user.visible_message("[user]'s eyes flare a deep crimson!", \
+ "You feel a strange power seep into your body... you have absorbed the demon's blood-travelling powers!")
user.bloodcrawl = BLOODCRAWL
else if(user.bloodcrawl == 1)
- user << "You absorb some of the demon's power!"
user << "You feel diffr- CONSUME THEM! "
user.bloodcrawl = BLOODCRAWL_EAT
+ else
+ user <<"...and you don't feel any different."
qdel(src)
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index e72157aedfb..6d84dc30562 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -60,3 +60,28 @@
client.verbs |= H.species.abilities
CallHook("Login", list("client" = src.client, "mob" = src))
+
+// Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget().
+// Calling it in the overriden Login, such as /mob/living/Login() doesn't cause this.
+/mob/proc/update_interface()
+ if(client)
+ if(winget(src, "mainwindow.hotkey_toggle", "is-checked") == "true")
+ update_hotkey_mode()
+ else
+ update_normal_mode()
+
+/mob/proc/update_hotkey_mode()
+ var/hotkeyname = "hotkeymode"
+ if(client)
+ var/hotkeys = client.hotkeylist[client.hotkeytype]
+ hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]
+ client.hotkeyon = 1
+ winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0")
+
+/mob/proc/update_normal_mode()
+ var/hotkeyname = "macro"
+ if(client)
+ var/hotkeys = client.hotkeylist[client.hotkeytype]//get the list containing the hotkey names
+ hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]//get the name of the hotkey, to not clutter winset() to much
+ client.hotkeyon = 0
+ winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5")
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 221b8962ca8..a644ec9d7d3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -639,11 +639,6 @@ var/list/slot_equipment_priority = list( \
flavor_text = msg
-/mob/proc/warn_flavor_changed()
- if(flavor_text && flavor_text != "") // don't spam people that don't use it!
- src << "
OOC Warning:
"
- src << "Your flavor text is likely out of date! Change"
-
/mob/proc/print_flavor_text(var/shrink = 1)
if (flavor_text && flavor_text != "")
var/msg = replacetext(flavor_text, "\n", " ")
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 312f9fb3ff1..4bc62d88f81 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -201,6 +201,7 @@
var/area/lastarea = null
var/digitalcamo = 0 // Can they be tracked by the AI?
+ var/weakeyes //Are they vulnerable to flashes?
var/list/radar_blips = list() // list of screen objects, radar blips
var/radar_open = 0 // nonzero is radar is open
@@ -232,4 +233,6 @@
var/last_movement = -100 // Last world.time the mob actually moved of its own accord.
- var/resize = 1 //Badminnery resize
\ No newline at end of file
+ var/resize = 1 //Badminnery resize
+
+ var/datum/vision_override/vision_type = null //Vision override datum.
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 7e0fbb1389f..9a5ce12d904 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -505,13 +505,13 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
name = realname
for(var/mob/M in player_list)
- if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_MOD,0,M)) && (M.client.prefs.toggles & CHAT_DEAD))
+ if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && (M.client.prefs.toggles & CHAT_DEAD))
var/follow
var/lname
if(subject)
if(subject != M)
follow = "([ghost_follow_link(subject, ghost=M)]) "
- if(M.stat != DEAD && M.client.holder)
+ if(M.stat != DEAD && check_rights(R_ADMIN|R_MOD,0,M))
follow = "([admin_jump_link(subject, M.client.holder)]) "
var/mob/dead/observer/DM
if(istype(subject, /mob/dead/observer))
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 3830c9b2705..da87a2b7537 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -342,6 +342,9 @@
var/arrivalmessage = announcer.arrivalmsg
arrivalmessage = replacetext(arrivalmessage,"$name",character.real_name)
arrivalmessage = replacetext(arrivalmessage,"$rank",rank ? "[rank]" : "visitor")
+ arrivalmessage = replacetext(arrivalmessage,"$species",character.species.name)
+ arrivalmessage = replacetext(arrivalmessage,"$age",num2text(character.age))
+ arrivalmessage = replacetext(arrivalmessage,"$gender",character.gender == FEMALE ? "Female" : "Male")
announcer.say(";[arrivalmessage]")
else
if(character.mind)
@@ -469,11 +472,11 @@
if(client.prefs.disabilities & DISABILITY_FLAG_BLIND)
new_character.dna.SetSEState(BLINDBLOCK,1,1)
new_character.sdisabilities |= BLIND
-
+
if(client.prefs.disabilities & DISABILITY_FLAG_MUTE)
new_character.dna.SetSEState(MUTEBLOCK,1,1)
new_character.sdisabilities |= MUTE
-
+
chosen_species.handle_dna(new_character)
domutcheck(new_character)
@@ -509,7 +512,7 @@
proc/has_admin_rights()
- return client.holder.rights & R_ADMIN
+ return check_rights(R_ADMIN, 0, src)
proc/is_species_whitelisted(datum/species/S)
if(!S) return 1
diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm
new file mode 100644
index 00000000000..143bc24956f
--- /dev/null
+++ b/code/modules/nano/interaction/conscious.dm
@@ -0,0 +1,7 @@
+/*
+ This state only checks if user is conscious.
+*/
+/var/global/datum/topic_state/conscious_state/conscious_state = new()
+
+/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
+ return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE
diff --git a/code/modules/nano/modules/power_monitor.dm b/code/modules/nano/modules/power_monitor.dm
index 73651c7835d..d6df0229085 100644
--- a/code/modules/nano/modules/power_monitor.dm
+++ b/code/modules/nano/modules/power_monitor.dm
@@ -42,6 +42,7 @@
if(href_list["selectmonitor"])
if(issilicon(usr))
powermonitor = locate(href_list["selectmonitor"])
+ powermonitor.powernet = powermonitor.find_powernet() // Refresh the powernet of the monitor
return 1
if(href_list["return"])
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 1a5808ec7d3..a93d2a278a8 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -21,7 +21,8 @@ var/list/organ_cache = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
germ_level = 0
-
+ var/datum/dna/dna
+ var/datum/species/species
/obj/item/organ/Destroy()
if(!owner)
@@ -59,6 +60,12 @@ var/list/organ_cache = list()
max_damage = min_broken_damage * 2
if(istype(holder))
src.owner = holder
+ species = all_species["Human"]
+ if(holder.dna)
+ dna = holder.dna.Clone()
+ species = all_species[dna.species]
+ else
+ log_to_dd("[src] at [loc] spawned without a proper DNA.")
var/mob/living/carbon/human/H = holder
if(istype(H))
if(internal)
@@ -67,13 +74,19 @@ var/list/organ_cache = list()
if(E.internal_organs == null)
E.internal_organs = list()
E.internal_organs |= src
- if(H.dna)
+ if(dna)
if(!blood_DNA)
blood_DNA = list()
- blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
+ blood_DNA[dna.unique_enzymes] = dna.b_type
if(internal)
holder.internal_organs |= src
+/obj/item/organ/proc/set_dna(var/datum/dna/new_dna)
+ if(new_dna)
+ dna = new_dna.Clone()
+ blood_DNA.Cut()
+ blood_DNA[dna.unique_enzymes] = dna.b_type
+
/obj/item/organ/proc/die()
if(status & ORGAN_ROBOT)
return
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index 26ca1f5079a..e3e95e78df3 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -12,13 +12,25 @@ var/global/list/limb_icon_cache = list()
/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human)
s_tone = null
s_col = null
- if(status & ORGAN_ROBOT)
+ if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color
+ return
+ if(species && human.species && species.name != human.species.name)
return
if(!isnull(human.s_tone) && (human.species.bodyflags & HAS_SKIN_TONE))
s_tone = human.s_tone
if(human.species.bodyflags & HAS_SKIN_COLOR)
s_col = list(human.r_skin, human.g_skin, human.b_skin)
+/obj/item/organ/external/proc/sync_colour_to_dna()
+ s_tone = null
+ s_col = null
+ if(status & ORGAN_ROBOT)
+ return
+ if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE))
+ s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE)
+ if(species.flags & HAS_SKIN_COLOR)
+ s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B))
+
/obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human)
..()
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
@@ -34,11 +46,11 @@ var/global/list/limb_icon_cache = list()
overlays.Cut()
if(!owner)
return
-
- if(owner.species.has_organ["eyes"])
+
+ if(species.has_organ["eyes"])
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
- if(owner.species.eyes)
- var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', owner.species.eyes)
+ if(species.eyes)
+ var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes)
if(eyes)
eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD)
else
@@ -46,14 +58,14 @@ var/global/list/limb_icon_cache = list()
mob_icon.Blend(eyes_icon, ICON_OVERLAY)
overlays |= eyes_icon
- if(owner.lip_style && (owner.species && (owner.species.flags & HAS_LIPS)))
+ if(owner.lip_style && (species && (species.flags & HAS_LIPS)))
var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s")
overlays |= lip_icon
mob_icon.Blend(lip_icon, ICON_OVERLAY)
if(owner.f_style)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style]
- if(facial_hair_style && facial_hair_style.species_allowed && (owner.species.name in facial_hair_style.species_allowed))
+ if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed))
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
if(facial_hair_style.do_colouration)
facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD)
@@ -61,7 +73,7 @@ var/global/list/limb_icon_cache = list()
if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR)))
var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style]
- if(hair_style && (owner.species.name in hair_style.species_allowed))
+ if(hair_style && (species.name in hair_style.species_allowed))
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
if(hair_style.do_colouration)
hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD)
@@ -74,26 +86,29 @@ var/global/list/limb_icon_cache = list()
var/gender
if(force_icon)
mob_icon = new /icon(force_icon, "[icon_name]")
+ if(species && species.name == "Machine") //snowflake for IPC's, sorry.
+ if(s_col && s_col.len >= 3)
+ mob_icon.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD)
else
- if(!owner)
+ if(!dna)
mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]")
else
if(gendered_icon)
- if(owner.gender == FEMALE)
+ if(dna.GetUIState(DNA_UI_GENDER))
gender = "f"
else
gender = "m"
if(skeletal)
mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]")
- else if (status & ORGAN_ROBOT)
+ else if(status & ORGAN_ROBOT)
mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]")
else
if (status & ORGAN_MUTATED)
- mob_icon = new /icon(owner.species.deform, "[icon_name][gender ? "_[gender]" : ""]")
+ mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]")
else
- mob_icon = new /icon(owner.species.icobase, "[icon_name][gender ? "_[gender]" : ""]")
+ mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]")
if(status & ORGAN_DEAD)
mob_icon.ColorTone(rgb(10,50,0))
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 9e27818eb8b..c4170888d3d 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -60,6 +60,9 @@
consume(user)
return 1
+/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man!
+ return 0
+
/obj/singularity/blob_act(severity)
return
@@ -268,8 +271,6 @@
step(src, movement_dir)
-/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man!
- return 0
/obj/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0)
if(!direction)
@@ -360,18 +361,13 @@
/obj/singularity/proc/toxmob()
var/toxrange = 10
- var/toxdamage = 4
var/radiation = 15
var/radiationmin = 3
- if (src.energy>200)
- toxdamage = round(((src.energy-150)/50)*4,1)
- radiation = round(((src.energy-150)/50)*5,1)
- radiationmin = round((radiation/5),1)//
+ if (energy>200)
+ radiation += round((energy-150)/10,1)
+ radiationmin = round((radiation/5),1)
for(var/mob/living/M in view(toxrange, src.loc))
M.apply_effect(rand(radiationmin,radiation), IRRADIATE)
- toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad")))
- M.apply_effect(toxdamage, TOX)
- return
/obj/singularity/proc/combust_mobs()
@@ -382,6 +378,7 @@
C.IgniteMob()
return
+
/obj/singularity/proc/mezzer()
for(var/mob/living/carbon/M in oviewers(8, src))
if(istype(M, /mob/living/carbon/brain)) //Ignore brains
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index 4df92ceb7bd..4c7b51e5ac0 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -1,4 +1,28 @@
-/obj/machinery/compressor
+// TURBINE v2 AKA rev4407 Engine reborn!
+
+// How to use it? - Mappers
+//
+// This is a very good power generating mechanism. All you need is a blast furnace with soaring flames and output.
+// Not everything is included yet so the turbine can run out of fuel quiet quickly. The best thing about the turbine is that even
+// though something is on fire that passes through it, it won't be on fire as it passes out of it. So the exhaust fumes can still
+// containt unreacted fuel - plasma and oxygen that needs to be filtered out and re-routed back. This of course requires smart piping
+// For a computer to work with the turbine the compressor requires a comp_id matching with the turbine computer's id. This will be
+// subjected to a change in the near future mind you. Right now this method of generating power is a good backup but don't expect it
+// become a main power source unless some work is done. Have fun. At 50k RPM it generates 60k power. So more than one turbine is needed!
+//
+// - Numbers
+//
+// Example setup S - sparker
+// B - Blast doors into space for venting
+// *BBB****BBB* C - Compressor
+// S CT * T - Turbine
+// * ^ * * V * D - Doors with firedoor
+// **|***D**|** ^ - Fuel feed (Not vent, but a gas outlet)
+// | | V - Suction vent (Like the ones in atmos
+//
+
+
+/obj/machinery/power/compressor
name = "compressor"
desc = "The compressor stage of a gas turbine generator."
icon = 'icons/obj/pipes.dmi'
@@ -13,6 +37,8 @@
var/rpmtarget = 0
var/capacity = 1e6
var/comp_id = 0
+ var/efficiency
+
/obj/machinery/power/turbine
name = "gas turbine generator"
@@ -21,57 +47,116 @@
icon_state = "turbine"
anchored = 1
density = 1
- var/obj/machinery/compressor/compressor
+ var/opened = 0
+ var/obj/machinery/power/compressor/compressor
var/turf/simulated/outturf
var/lastgen
+ var/productivity = 1
/obj/machinery/computer/turbine_computer
- name = "Gas turbine control computer"
+ name = "gas turbine control computer"
desc = "A computer to remotely control a gas turbine"
- icon = 'icons/obj/computer.dmi'
- icon_state = "airtunnel0e"
- circuit = /obj/item/weapon/circuitboard/turbine_control
- anchored = 1
- density = 1
- var/obj/machinery/compressor/compressor
- var/list/obj/machinery/door/poddoor/doors
+ icon_screen = "turbinecomp"
+ icon_keyboard = "tech_key"
+ circuit = /obj/item/weapon/circuitboard/turbine_computer
+ var/obj/machinery/power/compressor/compressor
var/id = 0
- var/door_status = 0
// the inlet stage of the gas turbine electricity generator
-/obj/machinery/compressor/New()
+/obj/machinery/power/compressor/New()
..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/power_compressor(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 5)
+ RefreshParts()
+// The inlet of the compressor is the direction it faces
gas_contained = new
inturf = get_step(src, dir)
- spawn(5)
- turbine = locate() in get_step(src, get_dir(inturf, src))
- if(!turbine)
- stat |= BROKEN
+
+/obj/machinery/power/compressor/initialize()
+ ..()
+ locate_machinery()
+ if(!turbine)
+ stat |= BROKEN
#define COMPFRICTION 5e5
#define COMPSTARTERLOAD 2800
-/obj/machinery/compressor/process()
+
+// Crucial to make things work!!!!
+// OLD FIX - explanation given down below.
+// /obj/machinery/power/compressor/CanPass(atom/movable/mover, turf/target, height=0)
+// return !density
+
+/obj/machinery/power/compressor/locate_machinery()
+ if(turbine)
+ return
+ turbine = locate() in get_step(src, get_dir(inturf, src))
+ if(turbine)
+ turbine.locate_machinery()
+
+/obj/machinery/power/compressor/RefreshParts()
+ var/E = 0
+ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
+ E += M.rating
+ efficiency = E / 6
+
+/obj/machinery/power/compressor/attackby(obj/item/I, mob/user, params)
+ if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I))
+ return
+
+ if(default_change_direction_wrench(user, I))
+ turbine = null
+ inturf = get_step(src, dir)
+ locate_machinery()
+ if(turbine)
+ user << "Turbine connected."
+ stat &= ~BROKEN
+ else
+ user << "Turbine not connected."
+ stat |= BROKEN
+ return
+
+ if(exchange_parts(user, I))
+ return
+
+ default_deconstruction_crowbar(I)
+
+/obj/machinery/power/compressor/CanAtmosPass(turf/T)
+ return !density
+
+/obj/machinery/power/compressor/process()
+ if(!turbine)
+ stat = BROKEN
+ if(stat & BROKEN || panel_open)
+ return
if(!starter)
return
overlays.Cut()
- if(stat & BROKEN)
- return
- if(!turbine)
- stat |= BROKEN
- return
+
rpm = 0.9* rpm + 0.1 * rpmtarget
var/datum/gas_mixture/environment = inturf.return_air()
+
+ // It's a simplified version taking only 1/10 of the moles from the turf nearby. It should be later changed into a better version
+
var/transfer_moles = environment.total_moles()/10
//var/transfer_moles = rpm/10000*capacity
var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles)
gas_contained.merge(removed)
- rpm = max(0, rpm - (rpm*rpm)/COMPFRICTION)
+// RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy
+
+ rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION/efficiency))
if(starter && !(stat & NOPOWER))
@@ -83,7 +168,6 @@
rpmtarget = 0
-
if(rpm>50000)
overlays += image('icons/obj/pipes.dmi', "comp-o4", FLY_LAYER)
else if(rpm>10000)
@@ -94,35 +178,74 @@
overlays += image('icons/obj/pipes.dmi', "comp-o1", FLY_LAYER)
//TODO: DEFERRED
+// These are crucial to working of a turbine - the stats modify the power output. TurbGenQ modifies how much raw energy can you get from
+// rpms, TurbGenG modifies the shape of the curve - the lower the value the less straight the curve is.
+
+#define TURBPRES 9000000
+#define TURBGENQ 100000
+#define TURBGENG 0.5
+
/obj/machinery/power/turbine/New()
..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/power_turbine(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 5)
+ RefreshParts()
+// The outlet is pointed at the direction of the turbine component
outturf = get_step(src, dir)
- spawn(5)
- compressor = locate() in get_step(src, get_dir(outturf, src))
- if(!compressor)
- stat |= BROKEN
+/obj/machinery/power/turbine/initialize()
+ ..()
+ locate_machinery()
+ if(!compressor)
+ stat |= BROKEN
+/obj/machinery/power/turbine/RefreshParts()
+ var/P = 0
+ for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
+ P += C.rating
+ productivity = P / 6
-#define TURBPRES 9000000
-#define TURBGENQ 20000
-#define TURBGENG 0.8
+/obj/machinery/power/turbine/locate_machinery()
+ if(compressor)
+ return
+ compressor = locate() in get_step(src, get_dir(outturf, src))
+ if(compressor)
+ compressor.locate_machinery()
+
+/obj/machinery/power/turbine/CanAtmosPass(turf/T)
+ return !density
/obj/machinery/power/turbine/process()
+
+ if(!compressor)
+ stat = BROKEN
+
+ if((stat & BROKEN) || panel_open)
+ return
if(!compressor.starter)
return
overlays.Cut()
- if(stat & BROKEN)
- return
- if(!compressor)
- stat |= BROKEN
- return
- lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) *TURBGENQ
+
+ // This is the power generation function. If anything is needed it's good to plot it in EXCEL before modifying
+ // the TURBGENQ and TURBGENG values
+
+ lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) * TURBGENQ * productivity
add_avail(lastgen)
+
+ // Weird function but it works. Should be something else...
+
var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4
+
newrpm = max(0, newrpm)
if(!compressor.starter || newrpm > 1000)
@@ -133,24 +256,48 @@
var/datum/gas_mixture/removed = compressor.gas_contained.remove(oamount)
outturf.assume_air(removed)
+// If it works, put an overlay that it works!
+
if(lastgen > 100)
overlays += image('icons/obj/pipes.dmi', "turb-o", FLY_LAYER)
+ updateDialog()
- for(var/mob/M in viewers(1, src))
- if ((M.client && M.machine == src))
- src.interact(M)
- AutoUpdateAI(src)
+/obj/machinery/power/turbine/attack_hand(mob/user)
+
+ if(..())
+ return
+
+ interact(user)
+
+/obj/machinery/power/turbine/attackby(obj/item/I, mob/user, params)
+ if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I))
+ return
+
+ if(default_change_direction_wrench(user, I))
+ compressor = null
+ outturf = get_step(src, dir)
+ locate_machinery()
+ if(compressor)
+ user << "Compressor connected."
+ stat &= ~BROKEN
+ else
+ user << "Compressor not connected."
+ stat |= BROKEN
+ return
+
+ if(exchange_parts(user, I))
+ return
+
+ default_deconstruction_crowbar(I)
/obj/machinery/power/turbine/interact(mob/user)
- if ( (get_dist(src, user) > 1 ) || (stat & (NOPOWER|BROKEN)) && (!istype(user, /mob/living/silicon/ai)) )
- user.machine = null
+ if ( !Adjacent(user) || (stat & (NOPOWER|BROKEN)) && (!istype(user, /mob/living/silicon)) )
+ user.unset_machine(src)
user << browse(null, "window=turbine")
return
- user.machine = src
-
var/t = "Gas Turbine Generator
"
t += "Generated power : [round(lastgen)] W
"
@@ -162,43 +309,26 @@
t += "
Close"
t += ""
- user << browse(t, "window=turbine")
- onclose(user, "turbine")
+ var/datum/browser/popup = new(user, "turbine", name)
+ popup.set_content(t)
+ popup.open()
return
/obj/machinery/power/turbine/Topic(href, href_list)
- ..()
- if(stat & BROKEN)
+ if(..())
return
- if (usr.stat || usr.restrained() )
+
+ if( href_list["close"] )
+ usr << browse(null, "window=turbine")
+ usr.unset_machine(src)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- if(!istype(usr, /mob/living/silicon/ai))
- usr << "\red You don't have the dexterity to do this!"
- return
- if (( usr.machine==src && ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai)))
-
-
- if( href_list["close"] )
- usr << browse(null, "window=turbine")
- usr.machine = null
- return
-
- else if( href_list["str"] )
+ else if( href_list["str"] )
+ if(compressor)
compressor.starter = !compressor.starter
- spawn(0)
- for(var/mob/M in viewers(1, src))
- if ((M.client && M.machine == src))
- src.interact(M)
-
- else
- usr << browse(null, "window=turbine")
- usr.machine = null
-
- return
+ updateDialog()
@@ -207,107 +337,67 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// COMPUTER NEEDS A SERIOUS REWRITE.
-/obj/machinery/computer/turbine_computer/New()
+
+/obj/machinery/computer/turbine_computer/initialize()
..()
- spawn(5)
- for(var/obj/machinery/compressor/C in machines)
- if(id == C.comp_id)
- compressor = C
- doors = new /list()
- for(var/obj/machinery/door/poddoor/P in machines)
- if(P.id_tag == id)
- doors += P
+ spawn(10)
+ locate_machinery()
-/*
-/obj/machinery/computer/turbine_computer/attackby(I as obj, user as mob, params)
- if(istype(I, /obj/item/weapon/screwdriver))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- if(do_after(user, 20, target = src))
- if (src.stat & BROKEN)
- user << "\blue The broken glass falls out."
- var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
- PoolOrNew(/obj/item/weapon/shard, loc)
- var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A )
- for (var/obj/C in src)
- C.loc = src.loc
- M.id = src.id
- A.circuit = M
- A.state = 3
- A.icon_state = "3"
- A.anchored = 1
- del(src)
- else
- user << "\blue You disconnect the monitor."
- var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
- var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A )
- for (var/obj/C in src)
- C.loc = src.loc
- M.id = src.id
- A.circuit = M
- A.state = 4
- A.icon_state = "4"
- A.anchored = 1
- del(src)
- else
- src.attack_hand(user)
- return
-*/
+/obj/machinery/computer/turbine_computer/locate_machinery()
+ compressor = locate(/obj/machinery/power/compressor) in range(5, src)
/obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob)
- user.machine = src
+ if(..())
+ return
+
+ interact(user)
+
+/obj/machinery/computer/turbine_computer/interact(mob/user)
+
var/dat
- if(src.compressor)
- dat += {" Gas turbine remote control system
- \nTurbine status: [ src.compressor.starter ? "OffOn" : "OffOn"]
- \n
- \nTurbine speed: [src.compressor.rpm]rpm
- \nPower currently being generated: [src.compressor.turbine.lastgen]W
- \nInternal gas temperature: [src.compressor.gas_contained.temperature]K
- \nVent doors: [ src.door_status ? "ClosedOpen" : "ClosedOpen"]
- \nView
- \nClose
- \n
- \n"}
+ if(compressor && compressor.turbine)
+ dat += " Gas turbine remote control system"
+ if(compressor.stat || compressor.turbine.stat)
+ dat += "[compressor.stat ? "Compressor is inoperable " : "Turbine is inoperable"]"
+ else
+ dat += {"Turbine status: [ src.compressor.starter ? "OffOn" : "OffOn"]
+ \n
+ \nTurbine speed: [src.compressor.rpm]rpm
+ \nPower currently being generated: [src.compressor.turbine.lastgen]W
+ \nInternal gas temperature: [src.compressor.gas_contained.temperature]K
+ \nClose
+ \n
+ \n"}
else
- dat += "\redNo compatible attached compressor found."
+ dat += "There is [!compressor ? "no compressor" : " compressor[!compressor.turbine ? " but no turbine" : ""]"]. "
+ if(!compressor)
+ dat += "Search for compressor"
- user << browse(dat, "window=computer;size=400x500")
- onclose(user, "computer")
+ var/datum/browser/popup = new(user, "turbinecomputer", name)
+ popup.set_content(dat)
+ popup.open()
return
-
-
/obj/machinery/computer/turbine_computer/Topic(href, href_list)
if(..())
return
- if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
- usr.machine = src
- if( href_list["view"] )
- usr.client.eye = src.compressor
- else if( href_list["str"] )
- src.compressor.starter = !src.compressor.starter
- else if (href_list["doors"])
- for(var/obj/machinery/door/poddoor/D in src.doors)
- if (door_status == 0)
- spawn( 0 )
- D.open()
- door_status = 1
- else
- spawn( 0 )
- D.close()
- door_status = 0
- else if( href_list["close"] )
- usr << browse(null, "window=computer")
- usr.machine = null
- return
+ else if( href_list["str"] )
+ if(compressor && compressor.turbine)
+ compressor.starter = !compressor.starter
+ else if( href_list["close"] )
+ usr << browse(null, "window=turbinecomputer")
+ usr.unset_machine(src)
+ return
+ else if(href_list["search"])
+ locate_machinery()
- src.add_fingerprint(usr)
src.updateUsrDialog()
return
/obj/machinery/computer/turbine_computer/process()
src.updateDialog()
- return
\ No newline at end of file
+ return
diff --git a/code/modules/procedural mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerator.dm
rename to code/modules/procedural_mapping/mapGenerator.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModule.dm b/code/modules/procedural_mapping/mapGeneratorModule.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModule.dm
rename to code/modules/procedural_mapping/mapGeneratorModule.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModules/helpers.dm
rename to code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModules/nature.dm b/code/modules/procedural_mapping/mapGeneratorModules/nature.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModules/nature.dm
rename to code/modules/procedural_mapping/mapGeneratorModules/nature.dm
diff --git a/code/modules/procedural mapping/mapGeneratorReadme.dm b/code/modules/procedural_mapping/mapGeneratorReadme.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorReadme.dm
rename to code/modules/procedural_mapping/mapGeneratorReadme.dm
diff --git a/code/modules/procedural mapping/mapGenerators/asteroid.dm b/code/modules/procedural_mapping/mapGenerators/asteroid.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/asteroid.dm
rename to code/modules/procedural_mapping/mapGenerators/asteroid.dm
diff --git a/code/modules/procedural mapping/mapGenerators/nature.dm b/code/modules/procedural_mapping/mapGenerators/nature.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/nature.dm
rename to code/modules/procedural_mapping/mapGenerators/nature.dm
diff --git a/code/modules/procedural mapping/mapGenerators/syndicate.dm b/code/modules/procedural_mapping/mapGenerators/syndicate.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/syndicate.dm
rename to code/modules/procedural_mapping/mapGenerators/syndicate.dm
diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm
index 1f6f374aef0..8d33a9e2508 100644
--- a/code/modules/projectiles/guns/energy/temperature.dm
+++ b/code/modules/projectiles/guns/energy/temperature.dm
@@ -29,7 +29,7 @@
/obj/item/weapon/gun/energy/temperature/Destroy()
processing_objects.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob)
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 46bb04ee636..e0127fe9862 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -218,15 +218,17 @@
if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food/drinks))
src.beaker = B
- user.drop_item()
- B.loc = src
- user << "You set [B] on the machine."
- nanomanager.update_uis(src) // update all UIs attached to src
- if(!icon_beaker)
- icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
- icon_beaker.pixel_x = rand(-10,5)
- overlays += icon_beaker
- return
+ if(user.drop_item())
+ B.forceMove(src)
+ user << "You set [B] on the machine."
+ nanomanager.update_uis(src) // update all UIs attached to src
+ if(!icon_beaker)
+ icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
+ icon_beaker.pixel_x = rand(-10,5)
+ overlays += icon_beaker
+ return
+ else
+ user << "\The [B] is stuck to you!"
/obj/machinery/chem_dispenser/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob, params)
..()
@@ -591,6 +593,8 @@
if(!condi)
var/count = 1
if (href_list["createpatch_multiple"]) count = isgoodnumber(input("Select the number of patches to make.", 10, patchamount) as num)
+ if(!count || count <= 0)
+ return
if (count > 20) count = 20 //Pevent people from creating huge stacks of patches easily. Maybe move the number to defines?
var/amount_per_patch = reagents.total_volume/count
if (amount_per_patch > 40) amount_per_patch = 40
diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm
index a54072e9bbb..e79667be06e 100644
--- a/code/modules/reagents/newchem/medicine.dm
+++ b/code/modules/reagents/newchem/medicine.dm
@@ -633,6 +633,7 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T
if(method == TOUCH)
if(M.stat == DEAD)
M.health = M.maxHealth
+ M.update_revive()
M.visible_message("[M] seems to rise from the dead!")
if(istype(M, /mob/living/carbon))
if(method == INGEST)
@@ -648,13 +649,12 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T
M.visible_message("[M] doesn't appear to respond, perhaps try again later?")
if(!M.suiciding && !ghost && !(NOCLONE in M.mutations))
M.visible_message("[M] seems to rise from the dead!")
- M.stat = 1
M.setOxyLoss(0)
M.adjustBruteLoss(rand(0,15))
M.adjustToxLoss(rand(0,15))
M.adjustFireLoss(rand(0,15))
- dead_mob_list -= M
- living_mob_list |= list(M)
+ M.update_revive()
+ M.stat = UNCONSCIOUS
add_logs(M, M, "revived", object="strange reagent")
..()
return
diff --git a/code/modules/reagents/newchem/toxins.dm b/code/modules/reagents/newchem/toxins.dm
index 907ddc994b1..d5d20843759 100644
--- a/code/modules/reagents/newchem/toxins.dm
+++ b/code/modules/reagents/newchem/toxins.dm
@@ -15,7 +15,7 @@ datum/reagent/polonium
datum/reagent/polonium/on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
- M.apply_effect(8, IRRADIATE)
+ M.apply_effect(8, IRRADIATE, negate_armor = 1)
..()
return
@@ -304,19 +304,19 @@ datum/reagent/initropidril
datum/reagent/initropidril/on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
if(prob(33))
- M.adjustToxLoss(rand(5,25))
- if(prob(rand(5,10)))
- var/picked_option = rand(1,3)
- switch(picked_option)
+ switch(pick(1,2))
if(1)
M << "You feel horrendously weak!"
M.Stun(2)
- M.losebreath += 1
if(2)
+ M.adjustToxLoss(rand(5,25))
+ if(prob(10))
+ switch(pick(1,2))
+ if(1)
M << "You cannot breathe!"
M.losebreath += 5
M.adjustOxyLoss(10)
- if(3)
+ if(2)
var/mob/living/carbon/human/H = M
if(!H.heart_attack)
H.heart_attack = 1 // rip in pepperoni
@@ -712,7 +712,7 @@ datum/reagent/glowing_slurry/reaction_mob(var/mob/M, var/method=TOUCH, var/volum
datum/reagent/glowing_slurry/on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
- M.apply_effect(2*REM,IRRADIATE,0)
+ M.apply_effect(2*REM, IRRADIATE, 0, negate_armor = 1)
if(prob(15))
randmutb(M)
if(prob(5))
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index aeda3fcbec3..7f9c3ee3c98 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -63,7 +63,7 @@
/obj/item/weapon/reagent_containers/proc/reagentlist(var/obj/item/weapon/reagent_containers/snack) //Attack logs for regents in pills
var/data
- if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries
+ if(snack && snack.reagents && snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries
for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind
data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return data
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index f71462b4625..8c2a40815e6 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -1655,76 +1655,79 @@
var/monkey_type = "Monkey"
- New()
- ..()
- reagents.add_reagent("protein",10)
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/New()
+ ..()
+ reagents.add_reagent("protein",10)
- afterattack(obj/O as obj, mob/user as mob, proximity)
- if(!proximity) return
- if(istype(O,/obj/structure/sink) && !wrapped)
- user << "You place [name] under a stream of water..."
- loc = get_turf(O)
- return Expand()
- ..()
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/afterattack(obj/O as obj, mob/user as mob, proximity)
+ if(!proximity) return
+ if(istype(O,/obj/structure/sink) && !wrapped)
+ user << "You place [name] under a stream of water..."
+ if(loc == user)
+ user.unEquip(src)
+ forceMove(get_turf(src))
+ return Expand()
+ ..()
- attack_self(mob/user as mob)
- if(wrapped)
- Unwrap(user)
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/attack_self(mob/user as mob)
+ if(wrapped)
+ Unwrap(user)
/*
- On_Consume(var/mob/M)
- M << "Something inside of you suddently expands!"
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/On_Consume(var/mob/M)
+ M << "Something inside of you suddently expands!"
- if (istype(M, /mob/living/carbon/human))
- //Do not try to understand.
- var/obj/item/weapon/surprise = new/obj/item/weapon(M)
- var/mob/living/carbon/monkey/ook = new monkey_type(null) //no other way to get access to the vars, alas
- surprise.icon = ook.icon
- surprise.icon_state = ook.icon_state
- surprise.name = "malformed [ook.name]"
- surprise.desc = "Looks like \a very deformed [ook.name], a little small for its kind. It shows no signs of life."
- del(ook) //rip nullspace monkey
- surprise.transform *= 0.6
- surprise.add_blood(M)
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/E = H.get_organ("chest")
- E.fracture()
- for (var/obj/item/organ/I in E.internal_organs)
- I.take_damage(rand(I.min_bruised_damage, I.min_broken_damage+1))
+ if (istype(M, /mob/living/carbon/human))
+ //Do not try to understand.
+ var/obj/item/weapon/surprise = new/obj/item/weapon(M)
+ var/mob/living/carbon/monkey/ook = new monkey_type(null) //no other way to get access to the vars, alas
+ surprise.icon = ook.icon
+ surprise.icon_state = ook.icon_state
+ surprise.name = "malformed [ook.name]"
+ surprise.desc = "Looks like \a very deformed [ook.name], a little small for its kind. It shows no signs of life."
+ del(ook) //rip nullspace monkey
+ surprise.transform *= 0.6
+ surprise.add_blood(M)
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/external/E = H.get_organ("chest")
+ E.fracture()
+ for (var/obj/item/organ/I in E.internal_organs)
+ I.take_damage(rand(I.min_bruised_damage, I.min_broken_damage+1))
- if (!E.hidden && prob(60)) //set it snuggly
- E.hidden = surprise
- E.cavity = 0
- else //someone is having a bad day
- E.createwound(CUT, 30)
- E.embed(surprise)
- else if (issmall(M))
- M.visible_message("[M] suddenly tears in half!")
- var/mob/living/carbon/monkey/ook = new monkey_type(M.loc)
- ook.name = "malformed [ook.name]"
- ook.transform *= 0.6
- ook.add_blood(M)
- M.gib()
- ..()
+ if (!E.hidden && prob(60)) //set it snuggly
+ E.hidden = surprise
+ E.cavity = 0
+ else //someone is having a bad day
+ E.createwound(CUT, 30)
+ E.embed(surprise)
+ else if (issmall(M))
+ M.visible_message("[M] suddenly tears in half!")
+ var/mob/living/carbon/monkey/ook = new monkey_type(M.loc)
+ ook.name = "malformed [ook.name]"
+ ook.transform *= 0.6
+ ook.add_blood(M)
+ M.gib()
+ ..()
*/
- water_act(volume, temperature)
- if(volume >= 5) return Expand()
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature)
+ if(volume >= 5)
+ return Expand()
- proc/Expand()
- for(var/mob/M in viewers(src,7))
- M << "\red \The [src] expands!"
- var/mob/living/carbon/human/H = new (src)
- H.set_species(monkey_type)
- qdel(src)
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Expand()
+ for(var/mob/M in viewers(src,7))
+ M << "\red \The [src] expands!"
+ var/mob/living/carbon/human/H = new (src)
+ H.set_species(monkey_type)
+ qdel(src)
- proc/Unwrap(mob/user as mob)
- icon_state = "monkeycube"
- desc = "Just add water!"
- user << "You unwrap the cube."
- wrapped = 0
- return
+/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Unwrap(mob/user as mob)
+ icon_state = "monkeycube"
+ desc = "Just add water!"
+ user << "You unwrap the cube."
+ wrapped = 0
+ return
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped
desc = "Still wrapped in some paper."
diff --git a/code/modules/research/designs/janitorial_designs.dm b/code/modules/research/designs/janitorial_designs.dm
index 76a469d04e6..8c575425ebe 100644
--- a/code/modules/research/designs/janitorial_designs.dm
+++ b/code/modules/research/designs/janitorial_designs.dm
@@ -11,6 +11,26 @@
build_path = /obj/item/weapon/mop/advanced
category = list("Janitorial")
+/datum/design/blutrash
+ name = "Trashbag of Holding"
+ desc = "An advanced trashabg with bluespace properties; capable of holding a plethora of garbage."
+ id = "blutrash"
+ req_tech = list("materials" = 5, "bluespace" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_GOLD = 1500, MAT_URANIUM = 250, MAT_PLASMA = 1500)
+ build_path = /obj/item/weapon/storage/bag/trash/bluespace
+ category = list("Janitorial")
+
+/datum/design/buffer
+ name = "Floor Buffer Upgrade"
+ desc = "A floor buffer that can be attached to vehicular janicarts."
+ id = "buffer"
+ req_tech = list("materials" = 5, "engineering" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 200)
+ build_path = /obj/item/janiupgrade
+ category = list("Janitorial")
+
/datum/design/holosign
name = "Holographic Sign Projector"
desc = "A holograpic projector used to project various warning signs."
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 87da26bfdd1..5c392cc5e01 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -32,6 +32,36 @@
build_path = /obj/item/weapon/circuitboard/emitter
category = list ("Engineering Machinery")
+/datum/design/turbine_computer
+ name = "Computer Design (Power Turbine Console Board)"
+ desc = "The circuit board for a power turbine console."
+ id = "power_turbine_console"
+ req_tech = list("programming" = 4, "powerstorage" = 4, "engineering" = 4)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/turbine_computer
+ category = list ("Engineering Machinery")
+
+/datum/design/power_compressor
+ name = "Machine Design (Power Compressor Board)"
+ desc = "The circuit board for a power compressor."
+ id = "power_compressor"
+ req_tech = list("programming" = 4, "powerstorage" = 5, "engineering" = 4)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/power_compressor
+ category = list ("Engineering Machinery")
+
+/datum/design/power_turbine
+ name = "Machine Design (Power Turbine Board)"
+ desc = "The circuit board for a power turbine."
+ id = "power_turbine"
+ req_tech = list("programming" = 4, "powerstorage" = 4, "engineering" = 5)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/power_turbine
+ category = list ("Engineering Machinery")
+
/datum/design/telepad
name = "Machine Board (Telepad Board)"
desc = "Allows for the construction of circuit boards used to build a Telepad."
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index 8d4656ee7fc..0901f45f284 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -591,8 +591,8 @@
//~~~~~~~~Admin logging proc, aka the Powergamer Alarm~~~~~~~~
/obj/machinery/r_n_d/experimentor/proc/warn_admins(mob/user, ReactionName)
var/turf/T = get_turf(src)
- message_admins("Experimentor reaction: [ReactionName] generated by [key_name_admin(user)](?) (FLW) at ([T.x],[T.y],[T.z] - JMP)",0,1)
- log_game("Experimentor reaction: [ReactionName] generated by [key_name(user)] in ([T.x],[T.y],[T.z])")
+ message_admins("Experimentor reaction: [ReactionName] generated by [key_name_admin(user)] at ([T.x], [T.y], [T.z] - JMP)",0,1)
+ log_game("Experimentor reaction: [ReactionName] generated by [key_name(user)] in ([T.x], [T.y], [T.z])")
#undef SCANTYPE_POKE
#undef SCANTYPE_IRRADIATE
@@ -738,6 +738,6 @@
var/turf/T = get_turf(src)
var/log_msg = "[RelicType] relic used by [key_name(user)] in ([T.x],[T.y],[T.z])"
if(priority) //For truly dangerous relics that may need an admin's attention. BWOINK!
- message_admins("[RelicType] relic activated by [key_name_admin(user)](?) (FLW) in ([T.x],[T.y],[T.z] - JMP)",0,1)
+ message_admins("[RelicType] relic activated by [key_name_admin(user)] in ([T.x], [T.y], [T.z] - JMP)",0,1)
log_game(log_msg)
investigate_log(log_msg, "experimentor")
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 577397b70fc..9072217e4f7 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -184,7 +184,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(..())
return 1
- if(!allowed(usr))
+ if(!allowed(usr) && !isobserver(usr))
return 1
add_fingerprint(usr)
@@ -324,7 +324,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
use_power(250)
updateUsrDialog()
- else if(href_list["lock"]) //Lock the console from use by anyone without tox access.
+ else if(href_list["lock"]) //Lock the console from use by anyone without access.
if(src.allowed(usr))
screen = text2num(href_list["lock"])
else
@@ -606,7 +606,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
/obj/machinery/computer/rdconsole/attack_hand(mob/user as mob)
if(..())
return 1
- if(!allowed(user))
+ if(!allowed(user) && !isobserver(user))
user << "Access denied."
return 1
interact(user)
@@ -1115,26 +1115,26 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "
"
return dat
+
+/obj/machinery/computer/rdconsole/core
+ name = "Core R&D Console"
+ desc = "A console used to interface with R&D tools."
+ id = 1
/obj/machinery/computer/rdconsole/robotics
name = "Robotics R&D Console"
desc = "A console used to interface with R&D tools."
id = 2
req_access = list(access_robotics)
+
+/obj/machinery/computer/rdconsole/experiment
+ name = "E.X.P.E.R.I-MENTOR R&D Console"
+ desc = "A console used to interface with R&D tools."
+ id = 3
/obj/machinery/computer/rdconsole/mechanics
name = "Mechanics R&D Console"
desc = "A console used to interface with R&D tools."
id = 4
req_access = list(access_mechanic)
-
-/obj/machinery/computer/rdconsole/core
- name = "Core R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 1
-
-/obj/machinery/computer/rdconsole/experiment
- name = "E.X.P.E.R.I-MENTOR R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 3
\ No newline at end of file
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 67cf7cd9217..a520fe6ec92 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -335,16 +335,15 @@
emagged = 1
user << "\blue You you disable the security protocols"
src.updateUsrDialog()
-
-/obj/machinery/r_n_d/server/robotics
- name = "Robotics R&D Server"
- id_with_upload_string = "1;2"
- id_with_download_string = "1;2"
- server_id = 2
-
-
+
/obj/machinery/r_n_d/server/core
name = "Core R&D Server"
- id_with_upload_string = "1"
- id_with_download_string = "1"
+ id_with_upload_string = "1;3"
+ id_with_download_string = "1;3"
server_id = 1
+
+/obj/machinery/r_n_d/server/robotics
+ name = "Robotics and Mechanic R&D Server"
+ id_with_upload_string = "1;2;4"
+ id_with_download_string = "1;2;4"
+ server_id = 2
diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm
similarity index 96%
rename from code/modules/security levels/keycard authentication.dm
rename to code/modules/security_levels/keycard authentication.dm
index 7a9fd05da3e..0fbff9cd68a 100644
--- a/code/modules/security levels/keycard authentication.dm
+++ b/code/modules/security_levels/keycard authentication.dm
@@ -1,186 +1,186 @@
-/obj/machinery/keycard_auth
- name = "Keycard Authentication Device"
- desc = "This device is used to trigger station functions, which require more than one ID card to authenticate."
- icon = 'icons/obj/monitors.dmi'
- icon_state = "auth_off"
- var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made.
- var/event = ""
- var/screen = 1
- var/list/ert_chosen = list()
- var/confirmed = 0 //This variable is set by the device that confirms the request.
- var/confirm_delay = 20 //(2 seconds)
- var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device.
- var/obj/machinery/keycard_auth/event_source
- var/mob/event_triggered_by
- var/mob/event_confirmed_by
- var/ert_reason = "Reason for ERT"
- //1 = select event
- //2 = authenticate
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 6
- power_channel = ENVIRON
-
-/obj/machinery/keycard_auth/attack_ai(mob/user as mob)
- user << "The station AI is not to interact with these devices."
- return
-
-/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(stat & (NOPOWER|BROKEN))
- user << "This device is not powered."
- return
- if(istype(W,/obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/ID = W
- if(access_keycard_auth in ID.access)
- if(active == 1)
- //This is not the device that made the initial request. It is the device confirming the request.
- if(event_source)
- event_source.confirmed = 1
- event_source.event_confirmed_by = usr
- else if(screen == 2)
- if(event == "Emergency Response Team" && ert_reason == "Reason for ERT")
- user << "Supply a reason for calling the ERT first!"
- return
- event_triggered_by = usr
- broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices
-
-/obj/machinery/keycard_auth/power_change()
- if(powered(ENVIRON))
- stat &= ~NOPOWER
- icon_state = "auth_off"
- else
- stat |= NOPOWER
-
-/obj/machinery/keycard_auth/attack_hand(mob/user as mob)
- if(!user.IsAdvancedToolUser())
- return 0
- ui_interact(user)
-
-/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(user.stat || stat & (NOPOWER|BROKEN))
- user << "This device is not powered."
- return
- if(busy)
- user << "This device is busy."
- return
-
- user.set_machine(src)
-
- var/data[0]
- data["screen"] = screen
- data["event"] = event
- data["ertreason"] = ert_reason
-
- ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320)
- ui.set_initial_data(data)
- ui.open()
-
-/obj/machinery/keycard_auth/Topic(href, href_list)
- if(..())
- return
- if(busy)
- usr << "This device is busy."
- return
- if(usr.stat || stat & (BROKEN|NOPOWER))
- usr << "This device is without power."
- return
- if(href_list["triggerevent"])
- event = href_list["triggerevent"]
- screen = 2
- if(href_list["reset"])
- reset()
- if(href_list["ert"])
- ert_reason = input(usr, "Reason for ERT Call:", "", "")
-
- nanomanager.update_uis(src)
- add_fingerprint(usr)
- return
-
-/obj/machinery/keycard_auth/proc/reset()
- active = 0
- event = ""
- screen = 1
- confirmed = 0
- event_source = null
- icon_state = "auth_off"
- event_triggered_by = null
- event_confirmed_by = null
-
-/obj/machinery/keycard_auth/proc/broadcast_request()
- icon_state = "auth_on"
- for(var/obj/machinery/keycard_auth/KA in world)
- if(KA == src) continue
- KA.reset()
- spawn()
- KA.receive_request(src)
-
- sleep(confirm_delay)
- if(confirmed)
- confirmed = 0
- trigger_event(event)
- log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]")
- message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1)
- reset()
-
-/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source)
- if(stat & (BROKEN|NOPOWER))
- return
- event_source = source
- busy = 1
- active = 1
- icon_state = "auth_on"
-
- sleep(confirm_delay)
-
- event_source = null
- icon_state = "auth_off"
- active = 0
- busy = 0
-
-/obj/machinery/keycard_auth/proc/trigger_event()
- switch(event)
- if("Red Alert")
- set_security_level(SEC_LEVEL_RED)
- feedback_inc("alert_keycard_auth_red",1)
- if("Grant Emergency Maintenance Access")
- make_maint_all_access()
- feedback_inc("alert_keycard_auth_maintGrant",1)
- if("Revoke Emergency Maintenance Access")
- revoke_maint_all_access()
- feedback_inc("alert_keycard_auth_maintRevoke",1)
- if("Emergency Response Team")
- if(is_ert_blocked())
- usr << "\red All Emergency Response Teams are dispatched and can not be called at this time."
- return
-
- usr << "ERT request transmitted."
- if(admins.len)
- ERT_Announce(ert_reason , event_triggered_by)
- ert_reason = "Reason for ERT"
- feedback_inc("alert_keycard_auth_ert",1)
- else
- trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT.
-
-/obj/machinery/keycard_auth/proc/is_ert_blocked()
- return ticker.mode && ticker.mode.ert_disabled
-
-var/global/maint_all_access = 0
-
-/proc/make_maint_all_access()
- for(var/area/maintenance/A in world)
- for(var/obj/machinery/door/airlock/D in A)
- D.emergency = 1
- D.update_icon(0)
- minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.")
- maint_all_access = 1
-
-/proc/revoke_maint_all_access()
- for(var/area/maintenance/A in world)
- for(var/obj/machinery/door/airlock/D in A)
- D.emergency = 0
- D.update_icon(0)
- minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.")
+/obj/machinery/keycard_auth
+ name = "Keycard Authentication Device"
+ desc = "This device is used to trigger station functions, which require more than one ID card to authenticate."
+ icon = 'icons/obj/monitors.dmi'
+ icon_state = "auth_off"
+ var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made.
+ var/event = ""
+ var/screen = 1
+ var/list/ert_chosen = list()
+ var/confirmed = 0 //This variable is set by the device that confirms the request.
+ var/confirm_delay = 20 //(2 seconds)
+ var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device.
+ var/obj/machinery/keycard_auth/event_source
+ var/mob/event_triggered_by
+ var/mob/event_confirmed_by
+ var/ert_reason = "Reason for ERT"
+ //1 = select event
+ //2 = authenticate
+ anchored = 1.0
+ use_power = 1
+ idle_power_usage = 2
+ active_power_usage = 6
+ power_channel = ENVIRON
+
+/obj/machinery/keycard_auth/attack_ai(mob/user as mob)
+ user << "The station AI is not to interact with these devices."
+ return
+
+/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
+ if(stat & (NOPOWER|BROKEN))
+ user << "This device is not powered."
+ return
+ if(istype(W,/obj/item/weapon/card/id))
+ var/obj/item/weapon/card/id/ID = W
+ if(access_keycard_auth in ID.access)
+ if(active == 1)
+ //This is not the device that made the initial request. It is the device confirming the request.
+ if(event_source)
+ event_source.confirmed = 1
+ event_source.event_confirmed_by = usr
+ else if(screen == 2)
+ if(event == "Emergency Response Team" && ert_reason == "Reason for ERT")
+ user << "Supply a reason for calling the ERT first!"
+ return
+ event_triggered_by = usr
+ broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices
+
+/obj/machinery/keycard_auth/power_change()
+ if(powered(ENVIRON))
+ stat &= ~NOPOWER
+ icon_state = "auth_off"
+ else
+ stat |= NOPOWER
+
+/obj/machinery/keycard_auth/attack_hand(mob/user as mob)
+ if(!user.IsAdvancedToolUser())
+ return 0
+ ui_interact(user)
+
+/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ if(user.stat || stat & (NOPOWER|BROKEN))
+ user << "This device is not powered."
+ return
+ if(busy)
+ user << "This device is busy."
+ return
+
+ user.set_machine(src)
+
+ var/data[0]
+ data["screen"] = screen
+ data["event"] = event
+ data["ertreason"] = ert_reason
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320)
+ ui.set_initial_data(data)
+ ui.open()
+
+/obj/machinery/keycard_auth/Topic(href, href_list)
+ if(..())
+ return
+ if(busy)
+ usr << "This device is busy."
+ return
+ if(usr.stat || stat & (BROKEN|NOPOWER))
+ usr << "This device is without power."
+ return
+ if(href_list["triggerevent"])
+ event = href_list["triggerevent"]
+ screen = 2
+ if(href_list["reset"])
+ reset()
+ if(href_list["ert"])
+ ert_reason = input(usr, "Reason for ERT Call:", "", "")
+
+ nanomanager.update_uis(src)
+ add_fingerprint(usr)
+ return
+
+/obj/machinery/keycard_auth/proc/reset()
+ active = 0
+ event = ""
+ screen = 1
+ confirmed = 0
+ event_source = null
+ icon_state = "auth_off"
+ event_triggered_by = null
+ event_confirmed_by = null
+
+/obj/machinery/keycard_auth/proc/broadcast_request()
+ icon_state = "auth_on"
+ for(var/obj/machinery/keycard_auth/KA in world)
+ if(KA == src) continue
+ KA.reset()
+ spawn()
+ KA.receive_request(src)
+
+ sleep(confirm_delay)
+ if(confirmed)
+ confirmed = 0
+ trigger_event(event)
+ log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]")
+ message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1)
+ reset()
+
+/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ event_source = source
+ busy = 1
+ active = 1
+ icon_state = "auth_on"
+
+ sleep(confirm_delay)
+
+ event_source = null
+ icon_state = "auth_off"
+ active = 0
+ busy = 0
+
+/obj/machinery/keycard_auth/proc/trigger_event()
+ switch(event)
+ if("Red Alert")
+ set_security_level(SEC_LEVEL_RED)
+ feedback_inc("alert_keycard_auth_red",1)
+ if("Grant Emergency Maintenance Access")
+ make_maint_all_access()
+ feedback_inc("alert_keycard_auth_maintGrant",1)
+ if("Revoke Emergency Maintenance Access")
+ revoke_maint_all_access()
+ feedback_inc("alert_keycard_auth_maintRevoke",1)
+ if("Emergency Response Team")
+ if(is_ert_blocked())
+ usr << "\red All Emergency Response Teams are dispatched and can not be called at this time."
+ return
+
+ usr << "ERT request transmitted."
+ if(admins.len)
+ ERT_Announce(ert_reason , event_triggered_by)
+ ert_reason = "Reason for ERT"
+ feedback_inc("alert_keycard_auth_ert",1)
+ else
+ trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT.
+
+/obj/machinery/keycard_auth/proc/is_ert_blocked()
+ return ticker.mode && ticker.mode.ert_disabled
+
+var/global/maint_all_access = 0
+
+/proc/make_maint_all_access()
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 1
+ D.update_icon(0)
+ minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.")
+ maint_all_access = 1
+
+/proc/revoke_maint_all_access()
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 0
+ D.update_icon(0)
+ minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.")
maint_all_access = 0
\ No newline at end of file
diff --git a/code/modules/security levels/security levels.dm b/code/modules/security_levels/security levels.dm
similarity index 97%
rename from code/modules/security levels/security levels.dm
rename to code/modules/security_levels/security levels.dm
index 5ac35d1188e..051d7b502cf 100644
--- a/code/modules/security levels/security levels.dm
+++ b/code/modules/security_levels/security levels.dm
@@ -1,184 +1,184 @@
-/var/security_level = 0
-//0 = code green
-//1 = code blue
-//2 = code red
-//3 = gamma
-//4 = epsilon
-//5 = code delta
-
-//config.alert_desc_blue_downto
-/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg'))
-/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1)
-
-/proc/set_security_level(var/level)
- switch(level)
- if("green")
- level = SEC_LEVEL_GREEN
- if("blue")
- level = SEC_LEVEL_BLUE
- if("red")
- level = SEC_LEVEL_RED
- if("gamma")
- level = SEC_LEVEL_GAMMA
- if("epsilon")
- level = SEC_LEVEL_EPSILON
- if("delta")
- level = SEC_LEVEL_DELTA
-
- //Will not be announced if you try to set to the same level as it already is
- if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level)
- switch(level)
- if(SEC_LEVEL_GREEN)
- security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
- security_level = SEC_LEVEL_GREEN
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
-
- if(SEC_LEVEL_BLUE)
- if(security_level < SEC_LEVEL_BLUE)
- security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
- else
- security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
- security_level = SEC_LEVEL_BLUE
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
-
- if(SEC_LEVEL_RED)
- if(security_level < SEC_LEVEL_RED)
- security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
- else
- security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
- security_level = SEC_LEVEL_RED
-
- var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
- if(R && (R.z in config.station_levels))
- R.locked = 0
- R.update_icon()
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
-
- if(SEC_LEVEL_GAMMA)
- security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!")
- security_level = SEC_LEVEL_GAMMA
-
- move_gamma_ship()
-
- if(security_level < SEC_LEVEL_RED)
- for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
- if((R.z in config.station_levels))
- R.locked = 0
- R.update_icon()
-
- for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
- if((H.z in config.station_levels))
- H.locked = 0
- H.update_icon()
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
- FA.update_icon()
-
- if(SEC_LEVEL_EPSILON)
- security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!")
- security_level = SEC_LEVEL_EPSILON
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
-
- if(SEC_LEVEL_DELTA)
- security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
- security_level = SEC_LEVEL_DELTA
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
-
- else
- return
-
-/proc/get_security_level()
- switch(security_level)
- if(SEC_LEVEL_GREEN)
- return "green"
- if(SEC_LEVEL_BLUE)
- return "blue"
- if(SEC_LEVEL_RED)
- return "red"
- if(SEC_LEVEL_GAMMA)
- return "gamma"
- if(SEC_LEVEL_EPSILON)
- return "epsilon"
- if(SEC_LEVEL_DELTA)
- return "delta"
-
-/proc/num2seclevel(var/num)
- switch(num)
- if(SEC_LEVEL_GREEN)
- return "green"
- if(SEC_LEVEL_BLUE)
- return "blue"
- if(SEC_LEVEL_RED)
- return "red"
- if(SEC_LEVEL_GAMMA)
- return "gamma"
- if(SEC_LEVEL_EPSILON)
- return "epsilon"
- if(SEC_LEVEL_DELTA)
- return "delta"
-
-/proc/seclevel2num(var/seclevel)
- switch( lowertext(seclevel) )
- if("green")
- return SEC_LEVEL_GREEN
- if("blue")
- return SEC_LEVEL_BLUE
- if("red")
- return SEC_LEVEL_RED
- if("gamma")
- return SEC_LEVEL_GAMMA
- if("epsilon")
- return SEC_LEVEL_EPSILON
- if("delta")
- return SEC_LEVEL_DELTA
-
-
-/*DEBUG
-/mob/verb/set_thing0()
- set_security_level(0)
-/mob/verb/set_thing1()
- set_security_level(1)
-/mob/verb/set_thing2()
- set_security_level(2)
-/mob/verb/set_thing3()
- set_security_level(3)
+/var/security_level = 0
+//0 = code green
+//1 = code blue
+//2 = code red
+//3 = gamma
+//4 = epsilon
+//5 = code delta
+
+//config.alert_desc_blue_downto
+/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg'))
+/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1)
+
+/proc/set_security_level(var/level)
+ switch(level)
+ if("green")
+ level = SEC_LEVEL_GREEN
+ if("blue")
+ level = SEC_LEVEL_BLUE
+ if("red")
+ level = SEC_LEVEL_RED
+ if("gamma")
+ level = SEC_LEVEL_GAMMA
+ if("epsilon")
+ level = SEC_LEVEL_EPSILON
+ if("delta")
+ level = SEC_LEVEL_DELTA
+
+ //Will not be announced if you try to set to the same level as it already is
+ if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level)
+ switch(level)
+ if(SEC_LEVEL_GREEN)
+ security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
+ security_level = SEC_LEVEL_GREEN
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
+
+ if(SEC_LEVEL_BLUE)
+ if(security_level < SEC_LEVEL_BLUE)
+ security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
+ else
+ security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
+ security_level = SEC_LEVEL_BLUE
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
+
+ if(SEC_LEVEL_RED)
+ if(security_level < SEC_LEVEL_RED)
+ security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
+ else
+ security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
+ security_level = SEC_LEVEL_RED
+
+ var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
+ if(R && (R.z in config.station_levels))
+ R.locked = 0
+ R.update_icon()
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
+
+ if(SEC_LEVEL_GAMMA)
+ security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!")
+ security_level = SEC_LEVEL_GAMMA
+
+ move_gamma_ship()
+
+ if(security_level < SEC_LEVEL_RED)
+ for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
+ if((R.z in config.station_levels))
+ R.locked = 0
+ R.update_icon()
+
+ for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
+ if((H.z in config.station_levels))
+ H.locked = 0
+ H.update_icon()
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
+ FA.update_icon()
+
+ if(SEC_LEVEL_EPSILON)
+ security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!")
+ security_level = SEC_LEVEL_EPSILON
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
+
+ if(SEC_LEVEL_DELTA)
+ security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
+ security_level = SEC_LEVEL_DELTA
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
+
+ else
+ return
+
+/proc/get_security_level()
+ switch(security_level)
+ if(SEC_LEVEL_GREEN)
+ return "green"
+ if(SEC_LEVEL_BLUE)
+ return "blue"
+ if(SEC_LEVEL_RED)
+ return "red"
+ if(SEC_LEVEL_GAMMA)
+ return "gamma"
+ if(SEC_LEVEL_EPSILON)
+ return "epsilon"
+ if(SEC_LEVEL_DELTA)
+ return "delta"
+
+/proc/num2seclevel(var/num)
+ switch(num)
+ if(SEC_LEVEL_GREEN)
+ return "green"
+ if(SEC_LEVEL_BLUE)
+ return "blue"
+ if(SEC_LEVEL_RED)
+ return "red"
+ if(SEC_LEVEL_GAMMA)
+ return "gamma"
+ if(SEC_LEVEL_EPSILON)
+ return "epsilon"
+ if(SEC_LEVEL_DELTA)
+ return "delta"
+
+/proc/seclevel2num(var/seclevel)
+ switch( lowertext(seclevel) )
+ if("green")
+ return SEC_LEVEL_GREEN
+ if("blue")
+ return SEC_LEVEL_BLUE
+ if("red")
+ return SEC_LEVEL_RED
+ if("gamma")
+ return SEC_LEVEL_GAMMA
+ if("epsilon")
+ return SEC_LEVEL_EPSILON
+ if("delta")
+ return SEC_LEVEL_DELTA
+
+
+/*DEBUG
+/mob/verb/set_thing0()
+ set_security_level(0)
+/mob/verb/set_thing1()
+ set_security_level(1)
+/mob/verb/set_thing2()
+ set_security_level(2)
+/mob/verb/set_thing3()
+ set_security_level(3)
*/
\ No newline at end of file
diff --git a/code/modules/space_transition/space_transition.dm b/code/modules/space_transition/space_transition.dm
new file mode 100644
index 00000000000..81be4604193
--- /dev/null
+++ b/code/modules/space_transition/space_transition.dm
@@ -0,0 +1,187 @@
+//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube
+
+#define Z_LEVEL_NORTH "1"
+#define Z_LEVEL_SOUTH "2"
+#define Z_LEVEL_EAST "4"
+#define Z_LEVEL_WEST "8"
+
+
+var/list/z_levels_list = list()
+
+/datum/space_level
+ var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
+ var/list/neigbours
+ var/z_value = 1 //actual z placement
+ var/linked = 1
+ var/xi
+ var/yi //imaginary placements on the grid
+
+/datum/space_level/New()
+ neigbours = list()
+ var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST)
+ for(var/A in L)
+ neigbours[A] = src
+
+/datum/space_level/proc/set_neigbours(list/L)
+ for(var/datum/point/P in L)
+ if(P.x == xi)
+ if(P.y == yi+1)
+ neigbours[Z_LEVEL_NORTH] = P.spl
+ P.spl.neigbours[Z_LEVEL_SOUTH] = src
+ else if(P.y == yi-1)
+ neigbours[Z_LEVEL_SOUTH] = P.spl
+ P.spl.neigbours[Z_LEVEL_NORTH] = src
+ else if(P.y == yi)
+ if(P.x == xi+1)
+ neigbours[Z_LEVEL_EAST] = P.spl
+ P.spl.neigbours[Z_LEVEL_WEST] = src
+ else if(P.x == xi-1)
+ neigbours[Z_LEVEL_WEST] = P.spl
+ P.spl.neigbours[Z_LEVEL_EAST] = src
+
+/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else
+ var/list/neigbours = list()
+ var/x
+ var/y
+ var/datum/space_level/spl
+
+/datum/point/New(nx, ny, list/point_grid)
+ if(!point_grid)
+ qdel(src)
+ return
+ var/list/L = point_grid[1]
+ if(nx > point_grid.len || ny > L.len)
+ qdel(src)
+ return
+ x = nx
+ y = ny
+ if(point_grid[x][y])
+ return
+ point_grid[x][y] = src
+
+/datum/point/proc/set_neigbours(list/grid)
+ var/max_X = grid.len
+ var/list/max_Y = grid[1]
+ max_Y = max_Y.len
+ neigbours.Cut()
+ if(x+1 <= max_X)
+ neigbours |= grid[x+1][y]
+ if(x-1 >= 1)
+ neigbours |= grid[x-1][y]
+ if(y+1 <= max_Y)
+ neigbours |= grid[x][y+1]
+ if(y-1 >= 1)
+ neigbours |= grid[x][y-1]
+
+
+//config/space_levels.txt is where you define your zlevel datum names, their connection to actual z levels and if you want them connected to one another or not
+//Grammar: Name;z value;linked/unlinked
+//Name is the name of the datum, just for the sake of it
+//z value is to what actual map z level this datum is pointing
+//linked/unlinked decide if you want the z level in the general map or not, for example centcomm is not reachable
+//Each entry must be separated with a single empty line, no spaces outside the name
+//No comments in the file allowed
+
+/proc/setup_map_transitions() //listamania
+ var/list/SLS = file2list("config/space_levels.txt", "\n\n")
+ var/datum/space_level/D
+ var/list/config_settings[SLS.len][]
+ for(var/A in SLS)
+ config_settings[SLS.Find(A)] = text2list(A, ";")
+ var/conf_set_len = SLS.len
+ SLS.Cut()
+ for(var/A in config_settings)
+ D = new()
+ D.name = A[1]
+ D.z_value = text2num(A[2])
+ if(A[3] != "linked")
+ D.linked = 0
+ z_levels_list["[D.z_value]"] = D
+ else
+ SLS.Add(D)
+ var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1]
+ var/list/grid = list()
+ var/datum/point/P
+ for(var/i = 1, i<=conf_set_len*2+1, i++)
+ for(var/j = 1, j<=conf_set_len*2+1, j++)
+ P = new/datum/point(i,j, point_grid)
+ point_grid[i][j] = P
+ grid.Add(P)
+ for(var/datum/point/pnt in grid)
+ pnt.set_neigbours(point_grid)
+ P = point_grid[conf_set_len][conf_set_len]
+ var/list/possible_points = list()
+ var/list/used_points = list()
+ grid.Cut()
+ while(SLS.len)
+ D = pick(SLS)
+ SLS.Remove(D)
+ D.xi = P.x
+ D.yi = P.y
+ P.spl = D
+ possible_points |= P.neigbours
+ used_points |= P
+ possible_points.Remove(used_points)
+ D.set_neigbours(used_points)
+ P = pick(possible_points)
+ grid["[D.z_value]"] = D
+
+ for(var/A in z_levels_list)
+ grid[A] = z_levels_list[A]
+
+ for(var/turf/space/S in world) //Define the transistions of the z levels
+ if(S.x <= TRANSITIONEDGE)
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_WEST] != D)
+ D = D.neigbours[Z_LEVEL_WEST]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_EAST] != D)
+ D = D.neigbours[Z_LEVEL_EAST]
+ S.destination_z = D.z_value
+ S.destination_x = world.maxx - TRANSITIONEDGE - 2
+ S.destination_y = S.y
+
+ if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_EAST] != D)
+ D = D.neigbours[Z_LEVEL_EAST]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_WEST] != D)
+ D = D.neigbours[Z_LEVEL_WEST]
+ S.destination_z = D.z_value
+ S.destination_x = TRANSITIONEDGE + 2
+ S.destination_y = S.y
+
+ if(S.y <= TRANSITIONEDGE)
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_SOUTH] != D)
+ D = D.neigbours[Z_LEVEL_SOUTH]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_NORTH] != D)
+ D = D.neigbours[Z_LEVEL_NORTH]
+ S.destination_z = D.z_value
+ S.destination_x = S.x
+ S.destination_y = world.maxy - TRANSITIONEDGE - 2
+
+ if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_NORTH] != D)
+ D = D.neigbours[Z_LEVEL_NORTH]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_SOUTH] != D)
+ D = D.neigbours[Z_LEVEL_SOUTH]
+ S.destination_z = D.z_value
+ S.destination_x = S.x
+ S.destination_y = TRANSITIONEDGE + 2
+
+ for(var/A in grid)
+ z_levels_list[A] = grid[A]
+
+#undef Z_LEVEL_NORTH
+#undef Z_LEVEL_SOUTH
+#undef Z_LEVEL_EAST
+#undef Z_LEVEL_WEST
diff --git a/code/modules/vehicle/train/trains/janicart.dm b/code/modules/vehicle/train/trains/janicart.dm
deleted file mode 100644
index a1fae332782..00000000000
--- a/code/modules/vehicle/train/trains/janicart.dm
+++ /dev/null
@@ -1,342 +0,0 @@
-/obj/vehicle/train/janitor/engine
- name = "janitor train tug"
- desc = "A ridable electric car designed for pulling janitor trolleys."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "pussywagon" //mulebot icons until I get some proper icons
- on = 0
- powered = 1
- locked = 0
- layer = MOB_LAYER + 0.1
- load_item_visible = 1
- load_offset_x = 0
- load_offset_y = 7
-
- var/car_limit = 3 //how many cars an engine can pull before performance degrades
- active_engines = 1
- var/obj/item/weapon/key/janitor_train/key
- flags = OPENCONTAINER
- var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
- var/obj/item/weapon/storage/bag/trash/mybag = null
-
-/obj/item/weapon/key/janitor_train
- name = "key"
- desc = "A keyring with a small steel key, and a yellow fob reading \"Choo Choo!\"."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "keys"
- w_class = 1
-
-/obj/vehicle/train/janitor/trolley
- name = "janitor train trolley"
- icon = 'icons/obj/janitor.dmi'
- icon_state = "trashcart"
- anchored = 0
- passenger_allowed = 0
- locked = 0
- load_item_visible = 1
- load_offset_x = 1
- load_offset_y = 7
-
- var/openTop = 0
- var/organs = 0
-//-------------------------------------------
-// Standard procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/New()
- ..()
- cell = new /obj/item/weapon/stock_parts/cell/high
- verbs -= /atom/movable/verb/pull
- key = new()
- var/datum/reagents/R = new/datum/reagents(100)
- reagents = R
- R.my_atom = src
-
-/obj/vehicle/train/janitor/engine/Move()
- . = ..()
- handle_rotation()
- update_mob()
-
-/obj/vehicle/train/janitor/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(openTop)
- W.loc = src
- user.visible_message("[user] puts [W] in [src].","You put [W] in [src].")
- if(istype(W,/obj/item/weapon/organ))
- organs = 1
- update_icon()
- else
- user << "The top is closed!"
-
-/obj/vehicle/train/janitor/trolley/attack_hand(mob/user)
- openTop = !openTop
- user.visible_message("[user] [openTop ? "opens" : "closes"] the top of [src].","You [openTop ? "open" : "close"] the the top of [src].")
- update_icon()
- ..()
-
-/obj/vehicle/train/janitor/trolley/update_icon()
- if(openTop)
- if(organs)
- icon_state = "trashcartopengib"
- else
- icon_state = "trashcartopen"
- else
- if(organs)
- icon_state = "trashcartgib"
- else
- icon_state = "trashcart"
-
-/obj/vehicle/train/janitor/engine/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/weapon/key/janitor_train))
- if(!key)
- user.drop_item()
- key = W
- W.loc = src
- verbs += /obj/vehicle/train/janitor/engine/verb/remove_key
- return
- else if(istype(W, /obj/item/weapon/mop))
- if(reagents.total_volume >= 2)
- reagents.trans_to(W, 2)
- user << "You wet the mop in the pimpin' ride."
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
- if(reagents.total_volume < 1)
- user << "This pimpin' ride is out of water!"
- return
- else if(istype(W, /obj/item/weapon/storage/bag/trash))
- user << "You hook the trashbag onto the pimpin' ride."
- user.drop_item()
- W.loc = src
- mybag = W
- return
- ..()
-
-/obj/vehicle/train/janitor/engine/attack_hand(mob/user)
- if(mybag)
- mybag.loc = get_turf(user)
- user.put_in_hands(mybag)
- mybag = null
- else
- ..()
-
-/obj/vehicle/train/janitor/update_icon()
- if(open)
- //icon_state = "mulebot-hatch"
- icon_state = initial(icon_state)
- else
- icon_state = initial(icon_state)
-
-/obj/vehicle/train/janitor/engine/Emag(mob/user as mob)
- ..()
- flick("mulebot-emagged", src)
-
-/obj/vehicle/train/janitor/trolley/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H)
- return
-
-/obj/vehicle/train/janitor/engine/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H)
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/engine/remove_cell(var/mob/living/carbon/human/H)
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/engine/Bump(atom/Obstacle)
- var/obj/machinery/door/D = Obstacle
- var/mob/living/carbon/human/H = load
- if(istype(D) && istype(H))
- D.Bumped(H) //a little hacky, but hey, it works, and repects access rights
-
- ..()
-
-/obj/vehicle/train/janitor/trolley/Bump(atom/Obstacle)
- if(!lead)
- return //so people can't knock others over by pushing a trolley around
- ..()
-
-/obj/vehicle/train/janitor/engine/handle_rotation()
- if(dir == SOUTH)
- layer = FLY_LAYER
- else
- layer = OBJ_LAYER
-
-/obj/vehicle/train/janitor/engine/proc/update_mob()
- if(load)
- load.dir = dir
- switch(dir)
- if(SOUTH)
- load.pixel_x = 0
- load.pixel_y = 7
- if(WEST)
- load.pixel_x = 13
- load.pixel_y = 7
- if(NORTH)
- load.pixel_x = 0
- load.pixel_y = 4
- if(EAST)
- load.pixel_x = -13
- load.pixel_y = 7
-
-
-//-------------------------------------------
-// Train procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/turn_on()
- if(!key)
- return
- else
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/RunOver(var/mob/living/carbon/human/H)
- var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm")
-
- H.apply_effects(5, 5)
- for(var/i = 0, i < rand(1,3), i++)
- H.apply_damage(rand(1,5), BRUTE, pick(parts))
-
-/obj/vehicle/train/janitor/trolley/RunOver(var/mob/living/carbon/human/H)
- ..()
- attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])")
-
-/obj/vehicle/train/janitor/engine/RunOver(var/mob/living/carbon/human/H)
- ..()
-
- if(is_train_head() && istype(load, /mob/living/carbon/human))
- var/mob/living/carbon/human/D = load
- D << "\red \b You ran over [H]!"
- visible_message("\red \The [src] ran over [H]!")
- attack_log += text("\[[time_stamp()]\] ran over [key_name(H)], driven by [key_name(D)]")
- msg_admin_attack("[key_name_admin(D)] ran over [key_name_admin(H)]")
- else
- attack_log += text("\[[time_stamp()]\] ran over [key_name(H)]")
-
-
-//-------------------------------------------
-// Interaction procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/relaymove(mob/user, direction)
- if(user != load)
- return 0
-
- if(is_train_head())
- if(direction == reverse_direction(dir))
- return 0
- if(Move(get_step(src, direction)))
- return 1
- return 0
- else
- return ..()
-
-
-/obj/vehicle/train/janitor/engine/examine(mob/user)
- if(!..(user, 1))
- return
-
- user << "\icon[src] This [name] contains [reagents.total_volume] unit\s of [reagents]!"
- if(mybag)
- user << "\A [mybag] is hanging on the [name]."
-
- user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition."
-
-/obj/vehicle/train/janitor/engine/verb/check_power()
- set name = "Check power level"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!cell)
- usr << "There is no power cell installed in [src]."
- return
-
- usr << "The power meter reads [round(cell.percent(), 0.01)]%"
-
-/obj/vehicle/train/janitor/engine/verb/start_engine()
- set name = "Start engine"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(on)
- usr << "The engine is already running."
- return
-
- turn_on()
- if (on)
- usr << "You start [src]'s engine."
- else
- if(cell.charge < charge_use)
- usr << "[src] is out of power."
- else
- usr << "[src]'s engine won't start."
-
-/obj/vehicle/train/janitor/engine/verb/stop_engine()
- set name = "Stop engine"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!on)
- usr << "The engine is already stopped."
- return
-
- turn_off()
- if (!on)
- usr << "You stop [src]'s engine."
-
-/obj/vehicle/train/janitor/engine/verb/remove_key()
- set name = "Remove key"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!key || (load && load != usr))
- return
-
- if(on)
- turn_off()
-
- key.loc = usr.loc
- if(!usr.get_active_hand())
- usr.put_in_hands(key)
- key = null
-
- verbs -= /obj/vehicle/train/janitor/engine/verb/remove_key
-
-//-------------------------------------------
-// Loading/unloading procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/trolley/load(var/atom/movable/C)
- return 0
-
-/obj/vehicle/train/janitor/engine/load(var/atom/movable/C)
- if(!ismob(C))
- return 0
-
- return ..()
-
-
-//-------------------------------------------------------
-// Stat update procs
-//
-// Update the trains stats for speed calculations.
-// The longer the train, the slower it will go. car_limit
-// sets the max number of cars one engine can pull at
-// full speed. Adding more cars beyond this will slow the
-// train proportionate to the length of the train. Adding
-// more engines increases this limit by car_limit per
-// engine.
-//-------------------------------------------------------
-
-/obj/vehicle/train/janitor/engine/proc/update_move_delay()
- if(!is_train_head() || !on)
- move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind
- else
- move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains
- move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines)
- move_delay += config.run_speed //base reference speed
- move_delay *= 1.05
diff --git a/code/stylesheet.dm b/code/stylesheet.dm
index ffd829c70b4..c0e951046fa 100644
--- a/code/stylesheet.dm
+++ b/code/stylesheet.dm
@@ -11,6 +11,8 @@ em {font-style: normal; font-weight: bold;}
.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover
{color: #638500;}
+.italics { font-style: italic;}
+
.prefix { font-weight: bold;}
.ooc { font-weight: bold;}
diff --git a/code/world.dm b/code/world.dm
index 9edfb4c38a4..14b23b525b5 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -35,7 +35,6 @@ var/global/datum/global_init/init = new ()
if(config && config.log_runtimes)
log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log")
- load_configuration()
SetupHooks() // /vg/
if(config && config.server_name != null && config.server_suffix && world.port > 0)
@@ -335,32 +334,6 @@ var/world_topic_spam_protect_time = world.timeofday
config.loadoverflowwhitelist("config/ofwhitelist.txt")
// apply some settings from config..
-/hook/startup/proc/loadMods()
- world.load_mods()
- return 1
-
-/world/proc/load_mods()
- if(config.admin_legacy_system)
- var/text = file2text("config/moderators.txt")
- if (!text)
- diary << "Failed to load config/mods.txt\n"
- else
- var/list/lines = text2list(text, "\n")
- for(var/line in lines)
- if (!line)
- continue
-
- if (copytext(line, 1, 2) == ";")
- continue
-
- var/title = "Moderator"
- if(config.mods_are_mentors) title = "Mentor"
- var/rights = admin_ranks[title]
-
- var/ckey = copytext(line, 1, length(line)+1)
- var/datum/admins/D = new /datum/admins(title, rights, ckey)
- D.associate(directory[ckey])
-
/world/proc/update_status()
var/s = ""
diff --git a/config/example/access levels.txt b/config/example/access levels.txt
deleted file mode 100644
index 8068be153fa..00000000000
--- a/config/example/access levels.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-HOW TO CONVERT A MAP TO THE NEW (june 2008) ACCESS LEVEL SYSTEM
-1. Open the .dmp file up in Notepad
-2. Find all the "access = blahblah" attributes of doors.
-3. Delete them.
-4. Open the map up in Dream Maker. If you didn't get them all, it'll tell you so.
-5. Assign the existing doors new access permissions using the method below.
-
-HOW TO MAKE A MAP USING THE NEW (june 2008) ACCESS LEVEL SYSTEM
-1. Make a map as normal
-2. Select a door that you want to not be accessible to everybody
-3. Right click on it and edit its attributes
-4. Make the "req_access_txt" attribute be a semicolon-separated list of the permissions required to open the doors
-5. Repeat for all doors.
-
-For example, a brig door would have it be "2" while a door that requires you have toxins and teleporter access (for whatever reason) would have it be "9;20"
-
-Here is a list of the permissions and their numbers (this may be out of date, see code/game/access.dm for an updated version):
-
-access_security = 1
-access_brig = 2
-access_armory = 3
-access_forensics_lockers= 4
-access_medical = 5
-access_morgue = 6
-access_tox = 7
-access_tox_storage = 8
-access_genetics = 9
-access_engine = 10
-access_engine_equip= 11
-access_maint_tunnels = 12
-access_external_airlocks = 13
-access_emergency_storage = 14
-access_change_ids = 15
-access_ai_upload = 16
-access_teleporter = 17
-access_eva = 18
-access_heads = 19
-access_captain = 20
-access_all_personal_lockers = 21
-access_chapel_office = 22
-access_tech_storage = 23
-access_atmospherics = 24
-access_bar = 25
-access_janitor = 26
-access_crematorium = 27
-access_kitchen = 28
-access_robotics = 29
-access_rd = 30
-access_cargo = 31
-access_construction = 32
-access_chemistry = 33
-access_cargo_bot = 34
-access_hydroponics = 35
-access_manufacturing = 36
-access_library = 37
-access_lawyer = 38
-access_virology = 39
-access_cmo = 40
-access_qm = 41
-access_court = 42
-access_clown = 43
-access_mime = 44
-access_surgery = 45
-access_theatre = 46
-access_research = 47
-access_mining = 48
-access_mining_office = 49 //not in use
-access_mailsorting = 50
-access_mint = 51
-access_mint_vault = 52
-access_heads_vault = 53
-access_mining_station = 54
-access_xenobiology = 55
-access_ce = 56
-access_hop = 57
-access_hos = 58
-access_RC_announce = 59 //Request console announcements
-access_keycard_auth = 60 //Used for events which require at least two people to confirm them
-access_tcomsat = 61 // has access to the entire telecomms satellite / machinery
\ No newline at end of file
diff --git a/config/example/admin_ranks.txt b/config/example/admin_ranks.txt
index e02a56df044..db2118ee8b7 100644
--- a/config/example/admin_ranks.txt
+++ b/config/example/admin_ranks.txt
@@ -5,31 +5,30 @@
# Each rank is then followed by keywords with the prefix "+". #
# These keywords represent groups of verbs and abilities which are given to that rank. #
# +@ (or +prev) is a special shorthand which adds all the rights of the rank above it. #
-# Ranks with no keywords will just be given the most basic verbs and abilities ~Carn #
+# Ranks with no keywords will just be given the most basic verbs and abilities #
########################################################################################
-# PLEASE NOTE: depending on config options, some abilities will be unavailable regardless if you have permission to use them!
-# ALSO NOTE: this is a WorkInProgress at the moment. Most of this is just arbitrarily thrown in whatever group because LoadsaWork2Do+LittleTime.
-# I'll be doing more moving around as feedback comes in. So be sure to check the notes after updates.
-
# KEYWORDS:
-# +ADMIN = general admin tools, verbs etc
-# +FUN = events, other event-orientated actions. Access to the fun secrets in the secrets panel.
-# +BAN = the ability to ban, jobban and fullban
-# +STEALTH = the ability to stealthmin (make yourself appear with a fake name to everyone but other admins
-# +POSSESS = the ability to possess objects
-# +REJUV (or +REJUVINATE) = the ability to heal, respawn, modify damage and use godmode
-# +BUILD (or +BUILDMODE) = the ability to use buildmode
-# +SERVER = higher-risk admin verbs and abilities, such as those which affect the server configuration.
-# +DEBUG = debug tools used for diagnosing and fixing problems. It's useful to give this to coders so they can investigate problems on a live server.
-# +VAREDIT = everyone may view viewvars/debugvars/whatever you call it. This keyword allows you to actually EDIT those variables.
-# +RIGHTS (or +PERMISSIONS) = allows you to promote and/or demote people.
-# +SOUND (or +SOUNDS) = allows you to upload and play sounds
-# +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too)
-# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag
+# +ADMIN = General admin tools and verbs.
+# +FUN = Events and other event-orientated actions.
+# +BAN = The ability to ban and jobban.
+# +STEALTH = The ability to stealthmin (make yourself appear with a fake name to everyone but other admins).
+# +POSSESS = The ability to possess objects.
+# +REJUV (or +REJUVINATE) = The ability to heal, respawn, modify damage and use godmode.
+# +BUILD (or +BUILDMODE) = The ability to use buildmode.
+# +SERVER = Higher-risk admin verbs and abilities, such as those which affect the server configuration.
+# +DEBUG = Debug tools used for diagnosing and fixing problems. It's useful to give this to coders so they can investigate problems on a live server.
+# +VAREDIT = Allows you to actually modify variables in the view variables window.
+# +RIGHTS (or +PERMISSIONS) = Allows you to promote and demote people.
+# +SOUND (or +SOUNDS) = Allows you to upload and play sounds.
+# +SPAWN (or +CREATE) = Mob transformations, spawning of most atoms including mobs (high-risk atoms will require the +FUN flag too).
+# +PROCCALL = The ability to call any proc on any entity.
+# +MOD = Low level admin abilities.
+# +MENTOR = The ability to answer questions.
+# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag.
Admin Observer
+Mentor +MENTOR
Moderator +MOD
-Mentor +MENTOR
Admin Candidate +ADMIN
Trial Admin +@ +SPAWN +REJUV +VAREDIT +BAN
@@ -41,5 +40,4 @@ Retired Admin +ADMIN +STEALTH
Host +EVERYTHING
-Developer +DEBUG +VAREDIT +SERVER +SPAWN +REJUV +POSSESS +BUILDMODE
-Dev Mod +@ +MOD
+Developer +DEBUG +VAREDIT +SERVER +SPAWN +REJUV +POSSESS +BUILDMODE
\ No newline at end of file
diff --git a/config/example/admins.txt b/config/example/admins.txt
index 3b830cd27ff..0e89ae17e23 100644
--- a/config/example/admins.txt
+++ b/config/example/admins.txt
@@ -2,7 +2,7 @@
# Basically, ckey goes first. Rank goes after the "-" #
# Case is not important for ckey. #
# Case IS important for the rank. However punctuation/spaces are not #
-# Ranks can be anything defined in admin_ranks.txt ~Carn #
+# Ranks can be anything defined in admin_ranks.txt #
######################################################################
-# not_a_user - Admin
+# example - Admin
diff --git a/config/example/config.txt b/config/example/config.txt
index e6019f2fec2..076a0e80766 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -1,4 +1,4 @@
-## Server name: This appears at the top of the screen in-game. In this case it will read "tgstation: station_name" where station_name is the randomly generated name of the station for the round. Remove the # infront of SERVERNAME and replace 'tgstation' with the name of your choice
+## Server name: This appears at the top of the screen in-game. In this case it will read "spacestation13: station_name" where station_name is the randomly generated name of the station for the round. Remove the # infront of SERVERNAME and replace 'spacestation13' with the name of your choice
# SERVERNAME spacestation13
## Add a # infront of this if you want to use the SQL based admin system, the legacy system uses admins.txt. You need to set up your database to use the SQL based system.
@@ -165,7 +165,16 @@ GUEST_BAN
## Wiki address
# WIKIURL http://example.org
-## Ban appeals URL - usually for a forum or wherever people should go to contact your admins.
+## Rules address
+# RULESURL http://example.org
+
+## Donations address
+# DONATIONSURL http://example.org
+
+## Repository address
+# REPOSITORYURL http://example.org
+
+## Ban appeals URL - usually for a forum or wherever people should go to contact your admins
# BANAPPEALS http://example.org
## Media base URL - determines where to pull the jukebox playlist from.
@@ -175,10 +184,10 @@ GUEST_BAN
## spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
# FEATURE_OBJECT_SPELL_SYSTEM
-##Toggle for having jobs load up from the .txt
+## Toggle for having jobs load up from the .txt
LOAD_JOBS_FROM_TXT
-##Remove the # mark infront of this to forbid admins from posssessing the singularity.
+## Remove the # mark infront of this to forbid admins from posssessing the singularity.
#FORBID_SINGULO_POSSESSION
## Remove the # to show a popup 'reply to' window to every non-admin that recieves an adminPM.
diff --git a/config/example/custom_items.txt b/config/example/custom_items.txt
deleted file mode 100644
index f4bb1a7028b..00000000000
--- a/config/example/custom_items.txt
+++ /dev/null
@@ -1 +0,0 @@
-ckey: name: /path/to/obj
diff --git a/config/example/moderators.txt b/config/example/moderators.txt
deleted file mode 100644
index b14d8e49f43..00000000000
--- a/config/example/moderators.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-; just add the ckey (lowercase) of every moderator on a separate line
-; lines starting with ; are comments and will be ignored
-
diff --git a/config/example/space_levels.txt b/config/example/space_levels.txt
new file mode 100644
index 00000000000..e724264daac
--- /dev/null
+++ b/config/example/space_levels.txt
@@ -0,0 +1,15 @@
+Main Station;1;linked
+
+Central Command;2;unlinked
+
+Telecommunications Satellite;3;linked
+
+Engineering Outpost;4;linked
+
+Mining Asteroid;5;linked
+
+Derelicted Station;6;linked
+
+Empty Area;7;linked
+
+Syndicate Station;8;unlinked
\ No newline at end of file
diff --git a/config/example/svndir.txt b/config/example/svndir.txt
deleted file mode 100644
index 5c907c92f1f..00000000000
--- a/config/example/svndir.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-#Path to the .svn directory. Used to get server revision info.
-SVNDIR .svn
-
-#Link to revision details.
-REVHREF http://code.google.com/p/tgstation13/source/detail?r=
\ No newline at end of file
diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi
index c32e3c508a4..1c971f8d3f4 100644
Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ
diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi
index 75f2ccef866..24e7f335be8 100644
Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ
diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi
index 79d773f7627..a55b4a75ae2 100644
Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 826c5ea1f4f..dd6cf13fc1e 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 38b93652f0e..119f3df0e37 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/money.dmi b/icons/obj/money.dmi
index c052cb8ea93..7b8a5e09495 100644
Binary files a/icons/obj/money.dmi and b/icons/obj/money.dmi differ
diff --git a/icons/obj/pipe-item.dmi b/icons/obj/pipe-item.dmi
index 1ef48fbad13..34fedaa560f 100644
Binary files a/icons/obj/pipe-item.dmi and b/icons/obj/pipe-item.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 9688bbdccc5..011fb04b816 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/trash.dmi b/icons/obj/trash.dmi
index 1d0d126006b..600ecc9f8a5 100644
Binary files a/icons/obj/trash.dmi and b/icons/obj/trash.dmi differ
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi
index 9d92dd02a81..63515f5b2e5 100644
Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ
diff --git a/interface/interface.dm b/interface/interface.dm
index 0ec03ffc198..bb7b26663ff 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -13,133 +13,196 @@
src << "The wiki URL is not set in the server configuration."
return
-#define CHANGELOG "https://github.com/ParadiseSS13/Paradise/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc"
/client/verb/changes()
set name = "Changelog"
- set desc = "Visit Github to check out the commits."
+ set desc = "Visit our repository to check out the changes."
set hidden = 1
-
- if(alert("This will open the changelog in your browser. Are you sure?",,"Yes","No")=="No")
- return
- src << link(CHANGELOG)
+
+ if(config.repositoryurl)
+ if(alert("This will open the changelog in your browser. Are you sure?",,"Yes","No")=="No")
+ return
+ src << link("[config.repositoryurl]/pulls?q=is%3Apr+is%3Aclosed")
+ else
+ src << "The Repository URL is not set in the server configuration."
return
-#undef CHANGELOG
/client/verb/forum()
set name = "forum"
set desc = "Visit the forum."
set hidden = 1
- if( config.forumurl )
+ if(config.forumurl)
if(alert("This will open the forum in your browser. Are you sure?",,"Yes","No")=="No")
return
src << link(config.forumurl)
else
- src << "\red The forum URL is not set in the server configuration."
+ src << "The forum URL is not set in the server configuration."
return
-#define RULES_FILE "config/rules.html"
/client/verb/rules()
set name = "Rules"
- set desc = "Show Server Rules."
+ set desc = "View the server rules."
set hidden = 1
- src << browse(file(RULES_FILE), "window=rules;size=480x320")
-#undef RULES_FILE
+ if(config.rulesurl)
+ if(alert("This will open the rules in your browser. Are you sure?",,"Yes","No")=="No")
+ return
+ src << link(config.rulesurl)
+ else
+ src << "The rules URL is not set in the server configuration."
+ return
-#define DONATE "http://nanotrasen.se/phpBB3/donate.php"
/client/verb/donate()
set name = "Donate"
- set desc = "Donate to help with development costs."
+ set desc = "Donate to help with hosting costs."
set hidden = 1
-
- if(alert("This will open the donation page in your browser. Are you sure?",,"Yes","No")=="No")
- return
- src << link(DONATE)
+ if(config.donationsurl)
+ if(alert("This will open the donation page in your browser. Are you sure?",,"Yes","No")=="No")
+ return
+ src << link(config.donationsurl)
+ else
+ src << "The rules URL is not set in the server configuration."
return
-#undef DONATE
/client/verb/hotkeys_help()
- set name = "Hotkeys Help"
+ set name = "Hotkey Help"
set category = "OOC"
+ var/adminhotkeys = {"
+Admin:
+\tF5 = Asay
+\tF6 = Admin Ghost
+\tF7 = Player Panel
+\tF8 = Admin PM
+\tF9 = Invisimin
+"}
+
+ mob.hotkey_help()
+
+ if(check_rights(R_MOD|R_ADMIN,0))
+ src << adminhotkeys
+
+/mob/proc/hotkey_help()
var/hotkey_mode = {"
Hotkey-Mode: (hotkey-mode must be on)
-\tTAB = toggle hotkey-mode
-\ta = left
-\ts = down
-\td = right
-\tw = up
-\tq = drop item / deselect cyborg module
-\te = equip
-\tr = toggle throw / unequip cyborg module
-\tt = say
-\tx = swap-hand
-\tz = activate held object (or y)
-\tf = cycle-intents-left
-\tg = cycle-intents-right
-\t1 = help-intent
-\t2 = disarm-intent
-\t3 = grab-intent
-\t4 = harm-intent
+\tTAB = Toggle Hotkey Mode
+\ta = Move Left
+\ts = Move Down
+\td = Move Right
+\tw = Move Up
+\tq = Drop Item
+\te = Equip Item
+\tr = Throw Item
+\tm = Me
+\tt = Say
+\to = OOC
+\tb = Resist
+\tx = Swap Hands
+\tz = Activate Held Object (or y)
+\tf = Cycle Intents Left
+\tg = Cycle Intents Right
+\t1 = Help Intent
+\t2 = Disarm Intent
+\t3 = Grab Intent
+\t4 = Harm Intent
"}
var/other = {"
Any-Mode: (hotkey doesn't need to be on)
-\tCtrl+a = left
-\tCtrl+s = down
-\tCtrl+d = right
-\tCtrl+w = up
-\tCtrl+q = drop item / deselect cyborg module
-\tCtrl+e = equip
-\tCtrl+r = toggle throw / unequip cyborg module
-\tCtrl+x = swap-hand
-\tCtrl+z = activate held object (or Ctrl+y)
-\tCtrl+f = cycle-intents-left
-\tCtrl+g = cycle-intents-right
-\tCtrl+1 = help-intent
-\tCtrl+2 = disarm-intent
-\tCtrl+3 = grab-intent
-\tCtrl+4 = harm-intent
-\tDEL = pull
-\tINS = cycle-intents-right
-\tHOME = drop item / deselect cyborg module
-\tPGUP = swap-hand
-\tPGDN = activate held object
-\tEND = toggle throw / unequip cyborg module
-"}
-
- var/admin = {"
-Admin:
-\tF5 = Aghost (admin-ghost)
-\tF6 = player-panel-new
-\tF7 = admin-pm
-\tF8 = Invisimin
+\tCtrl+a = Move Left
+\tCtrl+s = Move Down
+\tCtrl+d = Move Right
+\tCtrl+w = Move Up
+\tCtrl+q = Drop Item
+\tCtrl+e = Equip Item
+\tCtrl+r = Throw Item
+\tCtrl+b = Resist
+\tCtrl+o = OOC
+\tCtrl+x = Swap Hands
+\tCtrl+z = Activate Held Object (or Ctrl+y)
+\tCtrl+f = Cycle Intents Left
+\tCtrl+g = Cycle Intents Right
+\tCtrl+1 = Help Intent
+\tCtrl+2 = Disarm Intent
+\tCtrl+3 = Grab Intent
+\tCtrl+4 = Harm Intent
+\tDEL = Pull
+\tINS = Cycle Intents Right
+\tHOME = Drop Item
+\tPGUP = Swap Hands
+\tPGDN = Activate Held Object
+\tEND = Throw Item
+\tF2 = OOC
+\tF3 = Say
+\tF4 = Me
"}
src << hotkey_mode
src << other
- if(holder)
- src << admin
+/mob/living/silicon/robot/hotkey_help()
+ var/hotkey_mode = {"
+Hotkey-Mode: (hotkey-mode must be on)
+\tTAB = Toggle Hotkey Mode
+\ta = Move Left
+\ts = Move Down
+\td = Move Right
+\tw = Move Up
+\tq = Unequip Active Module
+\tm = Me
+\tt = Say
+\to = OOC
+\tx = Cycle Active Modules
+\tb = Resist
+\tz = Activate Held Object (or y)
+\tf = Cycle Intents Left
+\tg = Cycle Intents Right
+\t1 = Activate Module 1
+\t2 = Activate Module 2
+\t3 = Activate Module 3
+\t4 = Toggle Intents
+"}
+
+ var/other = {"
+Any-Mode: (hotkey doesn't need to be on)
+\tCtrl+a = Move Left
+\tCtrl+s = Move Down
+\tCtrl+d = Move Right
+\tCtrl+w = Move Up
+\tCtrl+q = Unequip Active Module
+\tCtrl+x = Cycle Active Modules
+\tCtrl+b = Resist
+\tCtrl+o = OOC
+\tCtrl+z = Activate Held Object (or Ctrl+y)
+\tCtrl+f = Cycle Intents Left
+\tCtrl+g = Cycle Intents Right
+\tCtrl+1 = Activate Module 1
+\tCtrl+2 = Activate Module 2
+\tCtrl+3 = Activate Module 3
+\tCtrl+4 = Toggle Intents
+\tDEL = Pull
+\tINS = Toggle Intents
+\tPGUP = Cycle Active Modules
+\tPGDN = Activate Held Object
+\tF2 = OOC
+\tF3 = Say
+\tF4 = Me
+"}
+
+ src << hotkey_mode
+ src << other
//adv. hotkey mode verbs, vars located in /code/modules/client/client defines.dm
-
/client/verb/hotkey_toggle()//toggles hotkey mode between on and off, respects selected type
set name = ".Toggle Hotkey Mode"
hotkeyon = !hotkeyon//toggle the var
-
- var/hotkeys = hotkeylist[hotkeytype]//get the list containing the hotkey names
- var/hotkeyname = hotkeys[hotkeyon ? "on" : "off"]//get the name of the hotkey, to not clutter winset() to much
-
- winset(usr, "mainwindow", "macro=[hotkeyname]")//change the hotkey
usr << (hotkeyon ? "Hotkey mode enabled." : "Hotkey mode disabled.")//feedback to the user
if(hotkeyon)//using an if statement because I don't want to clutter winset() with ? operators
winset(usr, "mainwindow.hotkey_toggle", "is-checked=true")//checks the button
- winset(usr, "mapwindow.map", "focus=true")//sets mapwindow focus
else
winset(usr, "mainwindow.hotkey_toggle", "is-checked=false")//unchecks the button
- winset(usr, "mainwindow.input", "focus=true")//sets focus
+ if(mob)
+ mob.update_interface()
/client/verb/hotkey_mode()//asks user for the hotkey type and changes the macro accordingly
set name = "Set Hotkey Mode"
diff --git a/interface/skin.dmf b/interface/skin.dmf
index e23a7b994ea..c66843ff071 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -87,6 +87,10 @@ macro "AZERTYoff"
name = "CTRL+D+REP"
command = ".east"
is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
elem
name = "CTRL+E"
command = "quick-equip"
@@ -161,14 +165,18 @@ macro "AZERTYoff"
is-disabled = false
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Aghost"
is-disabled = false
elem
name = "F7"
- command = "Admin-PM"
+ command = "player-panel-new"
is-disabled = false
elem
name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
command = "Invisimin"
is-disabled = false
elem
@@ -289,6 +297,10 @@ macro "AZERTYon"
name = "CTRL+D+REP"
command = ".east"
is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
elem
name = "E"
command = "quick-equip"
@@ -349,6 +361,14 @@ macro "AZERTYon"
name = "T"
command = ".say"
is-disabled = false
+ elem
+ name = "O"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "M"
+ command = ".me"
+ is-disabled = false
elem
name = "W"
command = "Activate-Held-Object"
@@ -415,14 +435,18 @@ macro "AZERTYon"
is-disabled = false
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Aghost"
is-disabled = false
elem
name = "F7"
- command = "Admin-PM"
+ command = "player-panel-new"
is-disabled = false
elem
name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
command = "Invisimin"
is-disabled = false
elem
@@ -430,6 +454,256 @@ macro "AZERTYon"
command = "F12"
is-disabled = false
+macro "borghotkeymode"
+ elem
+ name = "TAB"
+ command = ".winset \"mainwindow.macro=borgmacro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5\""
+ is-disabled = false
+ elem
+ name = "CENTER+REP"
+ command = ".center"
+ is-disabled = false
+ elem
+ name = "NORTHEAST"
+ command = ".northeast"
+ is-disabled = false
+ elem
+ name = "SOUTHEAST"
+ command = ".southeast"
+ is-disabled = false
+ elem
+ name = "NORTHWEST"
+ command = "unequip-module"
+ is-disabled = false
+ elem
+ name = "CTRL+WEST"
+ command = "westface"
+ is-disabled = false
+ elem
+ name = "WEST+REP"
+ command = ".west"
+ is-disabled = false
+ elem
+ name = "CTRL+NORTH"
+ command = "northface"
+ is-disabled = false
+ elem
+ name = "NORTH+REP"
+ command = ".north"
+ is-disabled = false
+ elem
+ name = "CTRL+EAST"
+ command = "eastface"
+ is-disabled = false
+ elem
+ name = "EAST+REP"
+ command = ".east"
+ is-disabled = false
+ elem
+ name = "CTRL+SOUTH"
+ command = "southface"
+ is-disabled = false
+ elem
+ name = "SOUTH+REP"
+ command = ".south"
+ is-disabled = false
+ elem
+ name = "INSERT"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "DELETE"
+ command = "delete-key-pressed"
+ is-disabled = false
+ elem
+ name = "1"
+ command = "toggle-module 1"
+ is-disabled = false
+ elem
+ name = "CTRL+1"
+ command = "toggle-module 1"
+ is-disabled = false
+ elem
+ name = "2"
+ command = "toggle-module 2"
+ is-disabled = false
+ elem
+ name = "CTRL+2"
+ command = "toggle-module 2"
+ is-disabled = false
+ elem
+ name = "3"
+ command = "toggle-module 3"
+ is-disabled = false
+ elem
+ name = "CTRL+3"
+ command = "toggle-module 3"
+ is-disabled = false
+ elem
+ name = "4"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "CTRL+4"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "A+REP"
+ command = ".west"
+ is-disabled = false
+ elem
+ name = "CTRL+A+REP"
+ command = ".west"
+ is-disabled = false
+ elem
+ name = "B"
+ command = "resist"
+ is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
+ elem
+ name = "T"
+ command = ".say"
+ is-disabled = false
+ elem
+ name = "O"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "M"
+ command = ".me"
+ is-disabled = false
+ elem
+ name = "CTRL+O"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "D+REP"
+ command = ".east"
+ is-disabled = false
+ elem
+ name = "CTRL+D+REP"
+ command = ".east"
+ is-disabled = false
+ elem
+ name = "F"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "CTRL+F"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "G"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "CTRL+G"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "Q"
+ command = "unequip-module"
+ is-disabled = false
+ elem
+ name = "CTRL+Q"
+ command = "unequip-module"
+ is-disabled = false
+ elem "s_key"
+ name = "S+REP"
+ command = ".south"
+ is-disabled = false
+ elem
+ name = "CTRL+S+REP"
+ command = ".south"
+ is-disabled = false
+ elem "w_key"
+ name = "W+REP"
+ command = ".north"
+ is-disabled = false
+ elem
+ name = "CTRL+W+REP"
+ command = ".north"
+ is-disabled = false
+ elem
+ name = "X"
+ command = ".northeast"
+ is-disabled = false
+ elem
+ name = "CTRL+X"
+ command = ".northeast"
+ is-disabled = false
+ elem
+ name = "Y"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "CTRL+Y"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "Z"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "CTRL+Z"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "F1"
+ command = "adminhelp"
+ is-disabled = false
+ elem
+ name = "CTRL+SHIFT+F1+REP"
+ command = ".options"
+ is-disabled = false
+ elem
+ name = "F2"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "F2+REP"
+ command = ".screenshot auto"
+ is-disabled = false
+ elem
+ name = "SHIFT+F2+REP"
+ command = ".screenshot"
+ is-disabled = false
+ elem
+ name = "F3"
+ command = ".say"
+ is-disabled = false
+ elem
+ name = "F4"
+ command = ".me"
+ is-disabled = false
+ elem
+ name = "F5"
+ command = "asay"
+ is-disabled = false
+ elem
+ name = "F6"
+ command = "Aghost"
+ is-disabled = false
+ elem
+ name = "F7"
+ command = "player-panel-new"
+ is-disabled = false
+ elem
+ name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
+ command = "Invisimin"
+ is-disabled = false
+ elem
+ name = "F12"
+ command = "F12"
+ is-disabled = false
+
macro "macro"
elem
name = "TAB"
@@ -519,6 +793,10 @@ macro "macro"
name = "CTRL+D+REP"
command = ".east"
is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
elem
name = "CTRL+E"
command = "quick-equip"
@@ -593,14 +871,18 @@ macro "macro"
is-disabled = false
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Aghost"
is-disabled = false
elem
name = "F7"
- command = "Admin-PM"
+ command = "player-panel-new"
is-disabled = false
elem
name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
command = "Invisimin"
is-disabled = false
elem
@@ -706,7 +988,15 @@ macro "hotkeymode"
command = "a-intent harm"
is-disabled = false
elem
- name = "5"
+ name = "T"
+ command = ".say"
+ is-disabled = false
+ elem
+ name = "O"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "M"
command = ".me"
is-disabled = false
elem
@@ -725,6 +1015,14 @@ macro "hotkeymode"
name = "CTRL+D+REP"
command = ".east"
is-disabled = false
+ elem
+ name = "B"
+ command = "resist"
+ is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
elem
name = "E"
command = "quick-equip"
@@ -851,14 +1149,18 @@ macro "hotkeymode"
is-disabled = false
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Aghost"
is-disabled = false
elem
name = "F7"
- command = "Admin-PM"
+ command = "player-panel-new"
is-disabled = false
elem
name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
command = "Invisimin"
is-disabled = false
elem
@@ -866,6 +1168,183 @@ macro "hotkeymode"
command = "F12"
is-disabled = false
+macro "borgmacro"
+ elem
+ name = "TAB"
+ command = ".winset \"mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0\""
+ is-disabled = false
+ elem
+ name = "CENTER+REP"
+ command = ".center"
+ is-disabled = false
+ elem
+ name = "NORTHEAST"
+ command = ".northeast"
+ is-disabled = false
+ elem
+ name = "SOUTHEAST"
+ command = ".southeast"
+ is-disabled = false
+ elem
+ name = "NORTHWEST"
+ command = "unequip-module"
+ is-disabled = false
+ elem
+ name = "CTRL+WEST"
+ command = "westface"
+ is-disabled = false
+ elem
+ name = "WEST+REP"
+ command = ".west"
+ is-disabled = false
+ elem
+ name = "CTRL+NORTH"
+ command = "northface"
+ is-disabled = false
+ elem
+ name = "NORTH+REP"
+ command = ".north"
+ is-disabled = false
+ elem
+ name = "CTRL+EAST"
+ command = "eastface"
+ is-disabled = false
+ elem
+ name = "EAST+REP"
+ command = ".east"
+ is-disabled = false
+ elem
+ name = "CTRL+SOUTH"
+ command = "southface"
+ is-disabled = false
+ elem
+ name = "SOUTH+REP"
+ command = ".south"
+ is-disabled = false
+ elem
+ name = "INSERT"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "DELETE"
+ command = "delete-key-pressed"
+ is-disabled = false
+ elem
+ name = "CTRL+1"
+ command = "toggle-module 1"
+ is-disabled = false
+ elem
+ name = "CTRL+2"
+ command = "toggle-module 2"
+ is-disabled = false
+ elem
+ name = "CTRL+3"
+ command = "toggle-module 3"
+ is-disabled = false
+ elem
+ name = "CTRL+4"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "CTRL+A+REP"
+ command = ".west"
+ is-disabled = false
+ elem
+ name = "CTRL+B"
+ command = "resist"
+ is-disabled = false
+ elem
+ name = "CTRL+O"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "CTRL+D+REP"
+ command = ".east"
+ is-disabled = false
+ elem
+ name = "CTRL+F"
+ command = "a-intent left"
+ is-disabled = false
+ elem
+ name = "CTRL+G"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "CTRL+Q"
+ command = "unequip-module"
+ is-disabled = false
+ elem
+ name = "CTRL+S+REP"
+ command = ".south"
+ is-disabled = false
+ elem
+ name = "CTRL+W+REP"
+ command = ".north"
+ is-disabled = false
+ elem
+ name = "CTRL+X"
+ command = ".northeast"
+ is-disabled = false
+ elem
+ name = "CTRL+Y"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "CTRL+Z"
+ command = "Activate-Held-Object"
+ is-disabled = false
+ elem
+ name = "F1"
+ command = "adminhelp"
+ is-disabled = false
+ elem
+ name = "CTRL+SHIFT+F1+REP"
+ command = ".options"
+ is-disabled = false
+ elem
+ name = "F2"
+ command = "ooc"
+ is-disabled = false
+ elem
+ name = "F2+REP"
+ command = ".screenshot auto"
+ is-disabled = false
+ elem
+ name = "SHIFT+F2+REP"
+ command = ".screenshot"
+ is-disabled = false
+ elem
+ name = "F3"
+ command = ".say"
+ is-disabled = false
+ elem
+ name = "F4"
+ command = ".me"
+ is-disabled = false
+ elem
+ name = "F5"
+ command = "asay"
+ is-disabled = false
+ elem
+ name = "F6"
+ command = "Aghost"
+ is-disabled = false
+ elem
+ name = "F7"
+ command = "player-panel-new"
+ is-disabled = false
+ elem
+ name = "F8"
+ command = "admin-pm-key"
+ is-disabled = false
+ elem
+ name = "F9"
+ command = "Invisimin"
+ is-disabled = false
+ elem
+ name = "F12"
+ command = "F12"
+ is-disabled = false
menu "menu"
elem
diff --git a/paradise.dme b/paradise.dme
index 5fcbab6ee36..510d4864fbe 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -121,6 +121,7 @@
#include "code\ATMOSPHERICS\components\unary_devices\heat_source.dm"
#include "code\ATMOSPHERICS\components\unary_devices\outlet_injector.dm"
#include "code\ATMOSPHERICS\components\unary_devices\oxygen_generator.dm"
+#include "code\ATMOSPHERICS\components\unary_devices\passive_vent.dm"
#include "code\ATMOSPHERICS\components\unary_devices\portables_connector.dm"
#include "code\ATMOSPHERICS\components\unary_devices\tank.dm"
#include "code\ATMOSPHERICS\components\unary_devices\thermal_plate.dm"
@@ -186,6 +187,7 @@
#include "code\datums\spell.dm"
#include "code\datums\supplypacks.dm"
#include "code\datums\uplink_item.dm"
+#include "code\datums\vision_override.dm"
#include "code\datums\cache\air_alarm.dm"
#include "code\datums\cache\apc.dm"
#include "code\datums\cache\cache.dm"
@@ -813,7 +815,6 @@
#include "code\game\objects\structures\musician.dm"
#include "code\game\objects\structures\noticeboard.dm"
#include "code\game\objects\structures\safe.dm"
-#include "code\game\objects\structures\segway.dm"
#include "code\game\objects\structures\signs.dm"
#include "code\game\objects\structures\spirit_board.dm"
#include "code\game\objects\structures\tables_racks.dm"
@@ -907,6 +908,7 @@
#include "code\modules\admin\player_panel.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\sql_notes.dm"
+#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\topic.dm"
#include "code\modules\admin\ToRban.dm"
#include "code\modules\admin\watchlist.dm"
@@ -944,6 +946,8 @@
#include "code\modules\admin\verbs\ticklag.dm"
#include "code\modules\admin\verbs\tripAI.dm"
#include "code\modules\admin\verbs\vox_raiders.dm"
+#include "code\modules\admin\verbs\SDQL2\SDQL_2.dm"
+#include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm"
#include "code\modules\alarm\alarm.dm"
#include "code\modules\alarm\alarm_handler.dm"
#include "code\modules\alarm\atmosphere_alarm.dm"
@@ -996,6 +1000,7 @@
#include "code\modules\client\client defines.dm"
#include "code\modules\client\client procs.dm"
#include "code\modules\client\global_cache.dm"
+#include "code\modules\client\message.dm"
#include "code\modules\client\preferences.dm"
#include "code\modules\client\preferences_mysql.dm"
#include "code\modules\client\preferences_spawnpoints.dm"
@@ -1089,10 +1094,10 @@
#include "code\modules\crafting\table.dm"
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\customitems\item_spawning.dm"
-#include "code\modules\DetectiveWork\detective_work.dm"
-#include "code\modules\DetectiveWork\evidence.dm"
-#include "code\modules\DetectiveWork\footprints_and_rag.dm"
-#include "code\modules\DetectiveWork\scanner.dm"
+#include "code\modules\detective_work\detective_work.dm"
+#include "code\modules\detective_work\evidence.dm"
+#include "code\modules\detective_work\footprints_and_rag.dm"
+#include "code\modules\detective_work\scanner.dm"
#include "code\modules\economy\Accounts.dm"
#include "code\modules\economy\Accounts_DB.dm"
#include "code\modules\economy\ATM.dm"
@@ -1178,8 +1183,8 @@
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\food\recipes_oven.dm"
#include "code\modules\food\recipes_table.dm"
-#include "code\modules\garbage collection\garbage_collector.dm"
-#include "code\modules\garbage collection\gc_testing.dm"
+#include "code\modules\garbage_collection\garbage_collector.dm"
+#include "code\modules\garbage_collection\gc_testing.dm"
#include "code\modules\holiday\christmas.dm"
#include "code\modules\holiday\holiday.dm"
#include "code\modules\hydroponics\grown.dm"
@@ -1495,6 +1500,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\interaction\admin.dm"
#include "code\modules\nano\interaction\base.dm"
+#include "code\modules\nano\interaction\conscious.dm"
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
@@ -1583,14 +1589,14 @@
#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\power\supermatter\supermatter.dm"
-#include "code\modules\procedural mapping\mapGenerator.dm"
-#include "code\modules\procedural mapping\mapGeneratorModule.dm"
-#include "code\modules\procedural mapping\mapGeneratorReadme.dm"
-#include "code\modules\procedural mapping\mapGeneratorModules\helpers.dm"
-#include "code\modules\procedural mapping\mapGeneratorModules\nature.dm"
-#include "code\modules\procedural mapping\mapGenerators\asteroid.dm"
-#include "code\modules\procedural mapping\mapGenerators\nature.dm"
-#include "code\modules\procedural mapping\mapGenerators\syndicate.dm"
+#include "code\modules\procedural_mapping\mapGenerator.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModule.dm"
+#include "code\modules\procedural_mapping\mapGeneratorReadme.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModules\helpers.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModules\nature.dm"
+#include "code\modules\procedural_mapping\mapGenerators\asteroid.dm"
+#include "code\modules\procedural_mapping\mapGenerators\nature.dm"
+#include "code\modules\procedural_mapping\mapGenerators\syndicate.dm"
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\gun.dm"
#include "code\modules\projectiles\projectile.dm"
@@ -1802,8 +1808,8 @@
#include "code\modules\scripting\Parser\Parser.dm"
#include "code\modules\scripting\Scanner\Scanner.dm"
#include "code\modules\scripting\Scanner\Tokens.dm"
-#include "code\modules\security levels\keycard authentication.dm"
-#include "code\modules\security levels\security levels.dm"
+#include "code\modules\security_levels\keycard authentication.dm"
+#include "code\modules\security_levels\security levels.dm"
#include "code\modules\shieldgen\circuits_and_designs.dm"
#include "code\modules\shieldgen\energy_field.dm"
#include "code\modules\shieldgen\shield_capacitor.dm"
@@ -1820,6 +1826,7 @@
#include "code\modules\shuttles\shuttle_supply.dm"
#include "code\modules\shuttles\shuttles_multi.dm"
#include "code\modules\shuttles\whiteship.dm"
+#include "code\modules\space_transition\space_transition.dm"
#include "code\modules\store\items.dm"
#include "code\modules\store\store.dm"
#include "code\modules\surgery\bones.dm"
@@ -1846,7 +1853,6 @@
#include "code\modules\vehicle\vehicle.dm"
#include "code\modules\vehicle\train\train.dm"
#include "code\modules\vehicle\train\trains\ambulance.dm"
-#include "code\modules\vehicle\train\trains\janicart.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_train.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\fourwheeler.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\motorcycle.dm"