diff --git a/.travis.yml b/.travis.yml index e25b3495f45..464e01c8f53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,11 +63,10 @@ jobs: env: addons: before_install: - - npm install -g bower gulp + - npm install -g gulp-cli - cd ./nano/ install: - npm install --loglevel=error - - bower install --silent before_script: script: - - gulp --min + - gulp diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm index c5b876c8c3e..67aa6f37c3a 100644 --- a/_maps/map_files/Delta/delta.dmm +++ b/_maps/map_files/Delta/delta.dmm @@ -10705,7 +10705,7 @@ "dXS" = (/obj/structure/cable,/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/obj/structure/closet/secure_closet/medical2,/turf/simulated/floor/plating,/area/medical/surgery1) "dXT" = (/obj/effect/decal/cleanable/dirt,/obj/machinery/light/small,/obj/structure/closet/crate/freezer,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/turf/simulated/floor/plating,/area/medical/surgery1) "dXU" = (/obj/structure/table/reinforced,/obj/item/storage/firstaid/regular,/obj/item/clothing/gloves/color/latex,/obj/item/clothing/mask/surgical,/obj/machinery/status_display{pixel_y = -32},/turf/simulated/floor/plasteel,/area/medical/surgery1) -"dXV" = (/obj/structure/table/wood,/obj/item/soulstone/anybody/chaplain,/obj/item/nullrod,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) +"dXV" = (/obj/structure/table/wood,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) "dXW" = (/obj/machinery/light/small{dir = 4; pixel_y = 8},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; master_tag = "arrival_south_airlock"; name = "interior access button"; pixel_x = -24; pixel_y = -24; req_access_txt = "10;13"},/obj/structure/sign/vacuum{pixel_x = -32},/turf/simulated/floor/plasteel,/area/hallway/secondary/exit) "dXX" = (/turf/space,/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1379; master_tag = "sw_maint2_airlock"; name = "exterior access button"; pixel_x = 24; pixel_y = 24; req_access_txt = "0"},/turf/simulated/floor/plating/airless/catwalk,/area/space) "dXY" = (/obj/structure/table/reinforced,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/blood/random,/obj/item/reagent_containers/syringe/epinephrine,/obj/item/reagent_containers/syringe,/obj/item/clothing/accessory/stethoscope,/obj/effect/decal/cleanable/dirt,/obj/machinery/status_display{pixel_y = -32},/turf/simulated/floor/plasteel,/area/medical/surgery1) diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm index b00fa636018..bf42c36de77 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm @@ -43,7 +43,7 @@ "aQ" = (/obj/structure/window/reinforced{dir = 8},/turf/space,/area/space) "aR" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) "aS" = (/obj/machinery/power/apc/worn_out{dir = 8; pixel_x = -24; pixel_y = 0},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/rack,/obj/item/melee/baton/cattleprod,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) -"aT" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/structure/rack,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/tank/emergency_oxygen/double,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) +"aT" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/structure/rack,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/tank/emergency_oxygen/double,/obj/item/clothing/head/helmet/space/hardsuit/medical,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) "aU" = (/obj/structure/rack,/obj/item/crowbar,/obj/item/shield/riot,/obj/machinery/light{dir = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) "aV" = (/obj/machinery/smartfridge/chemistry,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) "aW" = (/obj/structure/table/reinforced,/obj/item/gun/syringe,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/unpowered) diff --git a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm index 21cc056bbb4..f3f89b30c13 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm @@ -37,7 +37,7 @@ "aK" = (/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/ruin/unpowered) "aL" = (/obj/machinery/light/small{dir = 4; pixel_y = -8},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/ruin/unpowered) "aM" = (/obj/structure/table,/obj/item/clothing/gloves/combat,/obj/item/clothing/gloves/combat,/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas,/turf/simulated/floor/plasteel,/area/ruin/unpowered) -"aN" = (/obj/structure/table,/obj/item/mass_spectrometer/adv,/obj/item/mass_spectrometer/adv,/obj/item/healthanalyzer,/obj/item/healthanalyzer,/obj/item/stack/medical/bruise_pack,/obj/item/stack/medical/bruise_pack,/turf/simulated/floor/plasteel,/area/ruin/unpowered) +"aN" = (/obj/structure/table,/obj/item/reagent_scanner/adv,/obj/item/healthanalyzer,/obj/item/healthanalyzer,/obj/item/stack/medical/bruise_pack,/obj/item/stack/medical/bruise_pack,/turf/simulated/floor/plasteel,/area/ruin/unpowered) "aO" = (/obj/structure/closet/radiation,/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel,/area/ruin/unpowered) "aP" = (/obj/structure/closet/cardboard,/obj/item/reagent_containers/food/drinks/cans/cola,/obj/item/reagent_containers/food/drinks/cans/cola,/obj/item/reagent_containers/food/drinks/cans/cola,/obj/item/reagent_containers/food/drinks/cans/cola,/obj/item/reagent_containers/food/drinks/cans/cola,/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor/plasteel,/area/ruin/unpowered) "aQ" = (/obj/structure/closet/wardrobe/pink,/turf/simulated/floor/wood{tag = "icon-wood-broken2"; icon_state = "wood-broken2"},/area/ruin/unpowered) @@ -177,4 +177,3 @@ aaaaaaaaaaaaaaaaaaaaaaabababababababababababababcececececeababababababababababab aaaaaaaaaaaaaaaaaaaaaaaaabababababababababababababcececececeababababababababaaaaaaababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababcececececeababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "} - diff --git a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm index a6890bdd61d..e0ecd3bd02a 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm @@ -1,5 +1,5 @@ "aa" = (/turf/template_noop,/area/template_noop) -"ab" = (/turf/simulated/mineral,/area/ruin/unpowered) +"ab" = (/turf/simulated/mineral/random,/area/ruin/unpowered) "ac" = (/turf/simulated/wall/r_wall,/area/ruin/space/ancientstation/hivebot) "ad" = (/obj/structure/closet/crate,/obj/item/stack/sheet/glass/fifty,/obj/item/stack/sheet/plasteel{amount = 30},/obj/item/stack/sheet/mineral/titanium{amount = 30},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/ruin/space/ancientstation/hivebot) "ae" = (/turf/simulated/floor/plating/airless,/area/template_noop) @@ -551,7 +551,7 @@ "kE" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/ruin/space/ancientstation/proto) "kF" = (/obj/structure/transit_tube_pod{dir = 4},/obj/structure/transit_tube/station/reverse{dir = 1},/obj/effect/decal/cleanable/dirt,/obj/effect/decal/warning_stripes/arrow{icon_state = "4"; dir = 1},/turf/simulated/floor/plasteel,/area/ruin/space/ancientstation) "kG" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/ruin/space/ancientstation) -"kH" = (/turf/simulated/mineral/uranium,/area/ruin/unpowered) +"kH" = (/turf/simulated/mineral/random/high_chance,/area/ruin/unpowered) "kI" = (/obj/effect/decal/warning_stripes/southeast,/obj/effect/decal/warning_stripes/northwest,/obj/effect/decal/cleanable/dirt,/obj/effect/mob_spawn/human/oldsec,/turf/simulated/floor/plasteel,/area/ruin/space/ancientstation) "kJ" = (/obj/effect/decal/warning_stripes/southeast,/obj/effect/decal/warning_stripes/northwest,/obj/effect/decal/cleanable/dirt,/obj/effect/mob_spawn/human/oldsci,/turf/simulated/floor/plasteel,/area/ruin/space/ancientstation) "kK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/decal/warning_stripes/southeast,/obj/effect/decal/warning_stripes/northwest,/obj/effect/decal/cleanable/dirt,/obj/effect/mob_spawn/human/oldeng,/turf/simulated/floor/plasteel,/area/ruin/space/ancientstation) @@ -619,11 +619,11 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabacadapacapapacaiahajahahaiacakacababaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalamanananananamalaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababacapcoaccvapacapapapaiaqaoacaraiaiasaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalaMaOauavawaYbhalalaaaaaaaaaaaaaaaaabababaaaaaaaaaaagababacapapacapcKacapapahapahcLaccPcLayasaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazazalaMaOataAaBaCataYbhalazazazaaaaagaaababababaaagaaaaaaagababacaiahaDaoahaDapdsaiapcLahaDcLcLaiasaa -aaaaaaaaaaaaaaaaaaagaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaEalbiaFaGaGaGatataFbjalaIaJazagagaaaaababababaaaaaaaaagaaababacaxahaDahajaDapapapapcLahaDcLcLayasaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazazalaMaOataAaBaCataYbhalazazazaaaaagaaabkHkHabaaagaaaaaaagababacaiahaDaoahaDapdsaiapcLahaDcLcLaiasaa +aaaaaaaaaaaaaaaaaaagaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaEalbiaFaGaGaGatataFbjalaIaJazagagaaaaabkHkHabaaaaaaaaagaaababacaxahaDahajaDapapapapcLahaDcLcLayasaa aaaaaaaaaaaaabaaaaaaaaagagagagagagagagagagagagagagagagagazaKaLalbkatataGaNaGatatcWalaPaQazaaaaaaagaaababaaaaaaagaaaaaaababaccoapacaiahacapaiahapahcLaccLcLaiasaa -aaaaaaagaaabababagaaagaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaRaLalbiaSataGaTaGataFbjalaUazazaaaaaaaaaaaacXaaaaaaaaaaaaaaababacapapaccoapacapapapaiajaoacahaoayasaa -aaaVaWaVagababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaXaLaldcdtataGaZaGatdudvalbabbazaaaaaaaaaaaaaaaaaaaaaaaaaaaaababacbcapacdsapacahahaoahahahacbdacababaa +aaaaaaagaaabkHabagaaagaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaRaLalbiaSataGaTaGataFbjalaUazazaaaaaaaaaaaacXaaaaaaaaaaaaaaababacapapaccoapacapapapaiajaoacahaoayasaa +aaaVaWaVagabkHababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazaXaLaldcdtataGaZaGatdudvalbabbazaaaaaaaaaaaaaaaaaaaaaaaaaaaaababacbcapacdsapacahahaoahahahacbdacababaa aVbebfaVaVabababaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazbgaLalaldLdMdtaZdudPdxalalblbmazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababacacacbnbnacacacacacacacacacababaaaa aVbfbfbfbobfbfbfbfbfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazazazazazbpazalambqbqbrbqbqamalazaUbsazazazazaaaaaaaaaaaaaabubububuaaaaababbvbwbxbxbwbvababababababbubububuaa agbybebebebebfbebebzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAbBbCbDbEbFbGbHbIbGbGbJbGbGbIbHbGbGbKbLbCbCbAaacXaaaaaaaaaabMbNbObPbubububububQbRbRbQbubububububububudHbTbuaa @@ -652,10 +652,10 @@ jZlrkajLaaagaaaaaaaaagaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaazkbkcazkdbCbCbCdVkebCbC kkinlEjLagaaagagagagaaaaaaaaagdlagaaaaagagagagagagagagagazazkmazknbCkJbCkKbCjPbCkoazkpazazagagagagagagagagagagagagagagagagjtkqjTjUjVkrksjVjWjXktjtaaaaaaaaaaaaaa kulJkwjLaaaaaaaaaaaaaaaaaaagaaababaaaaaaaaaaaaaaaaaaaaaaaaazkxazkdbCbCbCdVbCbCbCkfazbgazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajtkyjCjUkzkAkAkzjWjCkBjtaaaaaaaaaaaaaa kClrkDjLaaagaaaaaaaaaaaaagaaaHabababaaagaaaaaaaaaaaaaaaaaaazazazbCbCjPbCjQbCjPbCbCazazazaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajtjtjtjtjtkEkEjtjtjtjtjtaaaaaaaaaaaaaa -aalNipipaaaaaaaaaaaaaaaaaaaaababababaaaaaaaaaaaaaaaaaaaaaaaaaaazazjfbCbCkGbCbCjfazazaaaaaaaaaaaaaaaaaaaaababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -agipipaaaaaaaaaaaaaaaaaaaaaaabkHababaaaaaaaaaaaaaaaaaaaaaaaaaaaaazazbAazbAazbAazazaaaaaaaaaaaaaaaaaaaaabababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagcaaaaaa -aaaaaaaaaaaaaaaaaaaagcaaaaaaaaaaaaaaaaaagcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aalNipipaaaaaaaaaaaaaaaaaaaaabkHkHabaaaaaaaaaaaaaaaaaaaaaaaaaaazazjfbCbCkGbCbCjfazazaaaaaaaaaaaaaaaaaaaaababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +agipipaaaaaaaaaaaaaaaaaaaaaaabkHkHabaaaaaaaaaaaaaaaaaaaaaaaaaaaaazazbAazbAazbAazazaaaaaaaaaaaaaaaaaaaaabababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababkHkHabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagcaaaaaa +aaaaaaaaaaaaaaaaaaaagcaaaaaaaaaaaaaaaaaagcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababkHkHabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagcaaaaaaababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm index 982be66cace..1c5708849bd 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm @@ -140,7 +140,7 @@ "cJ" = (/obj/machinery/light/small,/turf/simulated/floor/plasteel,/area/ruin/onehalf/bridge) "cK" = (/obj/machinery/door/poddoor/preopen{id_tag = "onehalf bridge"; name = "bridge blast door"},/obj/machinery/door/airlock/command/glass{name = "Bridge"},/turf/simulated/floor/plasteel,/area/ruin/onehalf/bridge) "cL" = (/obj/item/crowbar,/obj/item/multitool,/turf/simulated/floor/plating,/area/ruin/onehalf/bridge) -"cM" = (/obj/structure/safe/floor,/obj/item/tank/oxygen/red,/obj/item/clothing/mask/gas/syndicate,/obj/item/clothing/suit/space/hardsuit/syndi,/obj/item/reagent_containers/food/drinks/bottle/rum,/obj/item/reagent_containers/food/drinks/bottle/rum,/obj/item/folder/syndicate/blue,/turf/simulated/floor/plating,/area/ruin/onehalf/bridge) +"cM" = (/obj/structure/safe/floor,/obj/item/tank/oxygen/red,/obj/item/clothing/mask/gas/syndicate,/obj/item/clothing/suit/space/hardsuit/syndi,/obj/item/reagent_containers/food/drinks/bottle/rum,/obj/item/reagent_containers/food/drinks/bottle/rum,/obj/item/folder/syndicate/blue,/obj/item/clothing/head/helmet/space/hardsuit/syndi,/turf/simulated/floor/plating,/area/ruin/onehalf/bridge) "cN" = (/obj/structure/chair/comfy/black{tag = "icon-comfychair (EAST)"; icon_state = "comfychair"; dir = 4},/turf/simulated/floor/plasteel,/area/ruin/onehalf/bridge) "cO" = (/obj/structure/lattice,/obj/item/stack/cable_coil/cut{amount = 2; dir = 2; icon_state = "coil_red2"},/turf/space,/area/ruin/onehalf/hallway) "cQ" = (/obj/machinery/light{dir = 8},/obj/machinery/vending/sovietsoda,/turf/simulated/floor/plasteel,/area/ruin/onehalf/bridge) @@ -189,3 +189,4 @@ aaaaaaaaaaaaaaaaaadgawclbPczdjbTbTbTbTdkdldmdldnbTbTaiaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaacxdodpacacacacacdqacacacdqacacafaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "} + diff --git a/_maps/map_files/RandomZLevels/academy.dmm b/_maps/map_files/RandomZLevels/academy.dmm index 4830397aea6..6ada07bc1cb 100644 --- a/_maps/map_files/RandomZLevels/academy.dmm +++ b/_maps/map_files/RandomZLevels/academy.dmm @@ -35,7 +35,7 @@ "aI" = (/obj/structure/table/reinforced,/obj/item/laser_pointer/upgraded,/turf/simulated/floor/carpet,/area/awaymission/academy/headmaster) "aJ" = (/obj/structure/cult/tome,/obj/item/twohanded/staff,/obj/item/spellbook/oneuse/charge,/turf/simulated/floor/wood,/area/awaymission/academy/headmaster) "aK" = (/obj/structure/chair/wood/wings{dir = 8},/turf/simulated/floor/wood,/area/awaymission/academy/headmaster) -"aL" = (/obj/item/clothing/suit/space/hardsuit/wizard,/obj/structure/table/wood,/obj/item/stack/sheet/mineral/silver{amount = 20},/turf/simulated/floor/wood,/area/awaymission/academy/headmaster) +"aL" = (/obj/item/clothing/suit/space/hardsuit/wizard,/obj/structure/table/wood,/obj/item/stack/sheet/mineral/silver{amount = 20},/obj/item/clothing/head/helmet/space/hardsuit/wizard,/turf/simulated/floor/wood,/area/awaymission/academy/headmaster) "aM" = (/obj/structure/table/reinforced,/obj/item/storage/briefcase,/turf/simulated/floor/carpet,/area/awaymission/academy/headmaster) "aN" = (/obj/structure/table/reinforced,/obj/item/coin/plasma,/turf/simulated/floor/carpet,/area/awaymission/academy/headmaster) "aO" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/unary/vent_pump,/turf/simulated/floor/carpet,/area/awaymission/academy/headmaster) @@ -420,17 +420,17 @@ "id" = (/obj/item/stack/cable_coil/random,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "ie" = (/obj/structure/rack,/obj/item/stack/sheet/mineral/plasma{amount = 50},/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "if" = (/turf/simulated/floor/grass,/area/awaymission/academy/academyaft) -"ig" = (/obj/structure/rack,/obj/item/circuitboard/telecomms/broadcaster,/obj/item/circuitboard/telecomms/receiver,/obj/item/circuitboard/telecomms/relay,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) +"ig" = (/obj/structure/rack,/obj/item/circuitboard/telecomms/broadcaster,/obj/item/circuitboard/telecomms/receiver,/obj/item/circuitboard/telecomms/processor,/obj/item/circuitboard/telecomms/bus,/obj/item/circuitboard/telecomms/relay,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "ih" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/unary/vent_pump{dir = 4; layer = 2.4; on = 1},/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "ii" = (/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "ij" = (/obj/structure/mirror{pixel_y = 28},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "ik" = (/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) -"il" = (/obj/structure/rack,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/crystal,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/micro_laser/high,/obj/item/stock_parts/micro_laser/high,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) +"il" = (/obj/structure/rack,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/crystal,/obj/item/stock_parts/micro_laser/high,/obj/item/stock_parts/micro_laser/high,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/analyzer,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) "im" = (/obj/machinery/power/smes/magical,/obj/structure/cable,/turf/simulated/floor/plating,/area/awaymission/academy/academyaft) "in" = (/obj/structure/rack,/obj/item/clothing/glasses/welding,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) "io" = (/obj/structure/mineral_door/iron,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) -"ip" = (/obj/structure/rack,/obj/item/stock_parts/scanning_module,/obj/item/stock_parts/micro_laser,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/subspace/ansible,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) -"iq" = (/obj/item/stock_parts/manipulator,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) +"ip" = (/obj/structure/rack,/obj/item/stock_parts/subspace/ansible,/obj/item/stock_parts/micro_laser/high,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/subspace/amplifier,/obj/item/stock_parts/subspace/filter,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) +"iq" = (/obj/structure/rack,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/filter,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/filter,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "ir" = (/obj/structure/rack,/obj/item/storage/toolbox/mechanical,/turf/simulated/floor/plasteel,/area/awaymission/academy/academyaft) "is" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "it" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) @@ -438,7 +438,7 @@ "iv" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/wood,/area/awaymission/academy/academyaft) "iw" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "ix" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) -"iy" = (/obj/structure/rack,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/subspace/filter,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) +"iy" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/structure/rack,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stock_parts/subspace/treatment,/obj/item/stock_parts/subspace/treatment,/obj/item/stock_parts/manipulator,/obj/item/stock_parts/manipulator,/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "iz" = (/obj/structure/toilet{dir = 8},/obj/machinery/light/small{dir = 1},/obj/effect/landmark{name = "awaystart"},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "iA" = (/obj/structure/toilet{dir = 4},/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/awaymission/academy/academyaft) "iB" = (/mob/living/simple_animal/hostile/statue,/turf/simulated/floor/plasteel,/area/awaymission/academy/headmaster) @@ -546,7 +546,6 @@ "kz" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel/airless{tag = "icon-whitered (EAST)"; icon_state = "whitered"; dir = 4},/area/awaymission/academy/academyaft) "kA" = (/obj/structure/bookcase,/obj/item/spellbook/oneuse/summonitem,/turf/simulated/floor/wood,/area/awaymission/academy/classrooms) "kB" = (/mob/living/simple_animal/hostile/carp/megacarp{name = "Elmo"},/turf/simulated/mineral/random/high_chance,/area/awaymission/academy) -"kC" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/structure/rack,/obj/item/stack/sheet/metal{amount = 50},/turf/simulated/floor/plasteel{icon_state = "hydrofloor"},/area/awaymission/academy/academyaft) "kD" = (/obj/effect/landmark{name = "awaystart"},/turf/simulated/floor/engine,/area/awaymission/academy/academyaft) "kE" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel,/area/awaymission/academy/classrooms) "kF" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/awaymission/academy/classrooms) @@ -678,13 +677,13 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabsbBbBgIgVhqgXgYgXgYdmbEdcdcdcdcdcdcbEfLfDfHfLkUfDfDfLbEgggggLgLgLcAbsbsaPaaaaaaaaaaaaaPaaaPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZgZgZgZgZgZgZgZgZgZgZfBfBfBfBfBfBfBfBfBhrfBkThbfBfBfBfBfBfBfBfBfBgZgZgZgZgZgZgZgZgZgZgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchdhehehfhshthigZhDgZhkhlhlhmhlhlhnfDfDfHfDkWfDfDfDhkhlhlhmhlhlhogZhDgZhphFhMhJichuhchcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchvhwheihkXiLixiQiPiQiRiSiSiSiSiSiTiZiZjbjajciZiZiZiRiSiSiSiSiSjdiQjgiQjkjhlplohchchKhcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchvhwheihkXiLixiQiPiQiRiSiSiSiSiSiTiZiZjbjajciZiZiZiRiSiSiSiSiSjdiQjgiQjkjhlplohKhchKhcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchLhchcjmhphphNgZhOgZhkhPhQhRhShTfBhUhUhUfHkWhUhUhUfBhVhWhXhYhZhngZhOgZiaibhplqhchchchcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaSaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchvhwhejpidhliegZgZgZfBfBfBfBfBfBfBhUifhUfHkWhUifhUfBfBfBfBfBfBfBgZgZgZighphplrlshchKhcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaSaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchLhchcjChphpiegZaagZiiiiiiijiiikfBhUifhUfHkWhUifhUfBiiiiijiiiiiigZaagZilhplulthchchchcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhcimhwhejFhphpingZaagZiiiiiiiiiiiiiohUifhUfHkWhUifhUioiiiiiiiiiiiigZaagZipiqlulvlshchKhcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchchchchphlhpirgZaagZisiiiiitfBfBfBiuifhUfHkWhUifivfBfBfBiwiiiijGgZaagZiyhpluluhchchchcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZhphlidhphphlhNgZaagZiiiiiiiiioizfBhUifhUfHkWhUifhUfBiAioiiiiiiiigZaagZkChlluluhphlhpgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaSaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhcimhwhejFhphpingZaagZiiiiiiiiiiiiiohUifhUfHkWhUifhUioiiiiiiiiiiiigZaagZiphplulvlshchKhcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZhchchchchphlhpirgZaagZisiiiiitfBfBfBiuifhUfHkWhUifivfBfBfBiwiiiijGgZaagZiqhpluluhchchchcgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZhphlidhphphlhNgZaagZiiiiiiiiioizfBhUifhUfHkWhUifhUfBiAioiiiiiiiigZaagZiyhlluluhphlhpgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZhphphlhlhpiCgZaagZisiiiiiifBfBfBhUifhUfHkWhUifhUfBfBfBiiiiiijGgZaagZhlhlhphphlhpgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZhphlhphphlgZaPgZiiiiiiiiioiDfBiEifhUfHkWhUifhUfBiAioiiiiiiiigZaPgZhlhphphpiFgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagZgZgZgZiGgZgZaagZisiiiiitfBfBfBhUifhUfHkWhUifhUfBfBfBiwiiiijGgZaagZgZiGgZgZgZgZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -733,3 +732,4 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "} + diff --git a/_maps/map_files/RandomZLevels/example.dmm b/_maps/map_files/RandomZLevels/example.dmm index 9c72113a674..768d213c25e 100644 --- a/_maps/map_files/RandomZLevels/example.dmm +++ b/_maps/map_files/RandomZLevels/example.dmm @@ -54,7 +54,7 @@ "bb" = (/obj/structure/table,/obj/item/healthanalyzer,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) "bc" = (/obj/structure/bed,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) "bd" = (/obj/structure/chair/stool,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) -"be" = (/obj/structure/table,/obj/item/mass_spectrometer/adv,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) +"be" = (/obj/structure/table,/obj/item/reagent_scanner/adv,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) "bf" = (/obj/structure/table,/obj/item/reagent_containers/glass/beaker,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) "bg" = (/obj/structure/table,/obj/item/folder/white,/obj/item/pen/red,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) "bh" = (/obj/machinery/light,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/example) diff --git a/_maps/map_files/RandomZLevels/stationCollision.dmm b/_maps/map_files/RandomZLevels/stationCollision.dmm index 72a1a9ac6af..51d3038c5aa 100644 --- a/_maps/map_files/RandomZLevels/stationCollision.dmm +++ b/_maps/map_files/RandomZLevels/stationCollision.dmm @@ -283,7 +283,7 @@ "fw" = (/obj/machinery/r_n_d/circuit_imprinter,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) "fx" = (/obj/machinery/r_n_d/protolathe,/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) "fy" = (/obj/machinery/r_n_d/destructive_analyzer,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) -"fz" = (/obj/structure/table,/obj/item/analyzer,/obj/item/mass_spectrometer{pixel_x = 5; pixel_y = 5},/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) +"fz" = (/obj/structure/table,/obj/item/analyzer,/obj/item/reagent_scanner{pixel_x = 5; pixel_y = 5},/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) "fA" = (/obj/effect/decal/remains/human{desc = "This guy seemed to have died in terrible way! Half his remains are dust."; icon_state = "remains"; name = "Syndicate agent remains"},/obj/item/ammo_casing/c10mm,/obj/item/paper/sc_safehint_paper_caf,/obj/item/clothing/under/syndicate,/obj/effect/decal/cleanable/blood/splatter,/turf/simulated/floor/plasteel,/area/awaymission/midblock) "fB" = (/obj/structure/target_stake,/obj/item/grown/sunflower,/turf/simulated/floor/plasteel{icon_state = "showroomfloor"},/area/awaymission/research) "fC" = (/obj/effect/decal/remains/human{desc = "This guy seemed to have died in terrible way! Half his remains are dust."; icon_state = "remains"; name = "Syndicate agent remains"},/obj/item/ammo_casing/c10mm,/obj/item/clothing/under/syndicate,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/item/gun/projectile/shotgun/toy/tommygun,/turf/simulated/floor/plasteel,/area/awaymission/midblock) diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 0cf3cd72a23..ca13cad8b02 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -2534,7 +2534,7 @@ "aWL" = (/obj/machinery/door/airlock{name = "Unisex Showers"; req_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/crew_quarters/toilet) "aWM" = (/obj/structure/window/reinforced{dir = 4},/obj/structure/table/reinforced,/obj/item/clothing/head/that{pixel_x = 4; pixel_y = 6},/obj/item/lighter/zippo,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/crew_quarters/bar) "aWN" = (/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/plasteel,/area/hallway/primary/central/ne) -"aWO" = (/obj/structure/table/glass,/obj/item/stack/packageWrap,/obj/item/mass_spectrometer/adv,/obj/machinery/light{dir = 1; in_use = 1},/obj/machinery/camera{c_tag = "Medbay Chemistry North"; network = list("SS13")},/obj/structure/extinguisher_cabinet{pixel_x = -5; pixel_y = 30},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whiteyellow"},/area/medical/chemistry) +"aWO" = (/obj/structure/table/glass,/obj/item/stack/packageWrap,/obj/item/reagent_scanner/adv,/obj/machinery/light{dir = 1; in_use = 1},/obj/machinery/camera{c_tag = "Medbay Chemistry North"; network = list("SS13")},/obj/structure/extinguisher_cabinet{pixel_x = -5; pixel_y = 30},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whiteyellow"},/area/medical/chemistry) "aWP" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor/wood,/area/crew_quarters/bar) "aWQ" = (/obj/machinery/light/small{dir = 8},/obj/item/storage/secure/safe{pixel_x = -22; pixel_y = 0},/turf/simulated/floor/wood,/area/crew_quarters/bar) "aWR" = (/obj/effect/decal/warning_stripes/north,/obj/machinery/chem_master,/obj/machinery/status_display{layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel,/area/medical/chemistry) @@ -2685,7 +2685,7 @@ "aZG" = (/obj/machinery/door/airlock/public/glass{name = "Central Access"},/turf/simulated/floor/plasteel{icon_state = "bluecorner"},/area/hallway/primary/fore) "aZH" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/visible/universal{dir = 4},/obj/machinery/requests_console{department = "Atmospherics"; departmentType = 3; name = "Atmospherics Requests Console"; pixel_y = -30},/obj/item/stack/sheet/glass{amount = 50},/obj/item/clothing/head/welding,/obj/item/clothing/head/welding,/obj/item/clothing/glasses/welding,/obj/item/clothing/glasses/welding,/turf/simulated/floor/plasteel,/area/atmos) "aZI" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/maintenance/fsmaint) -"aZJ" = (/obj/effect/decal/cleanable/cobweb,/obj/item/clothing/mask/muzzle/gag,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) +"aZJ" = (/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) "aZK" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) "aZL" = (/obj/item/restraints/handcuffs/pinkcuffs,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) "aZM" = (/obj/structure/chair,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) @@ -2828,7 +2828,7 @@ "bct" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel,/area/hallway/secondary/entry) "bcu" = (/obj/structure/table/wood,/obj/item/pen,/obj/item/reagent_containers/food/drinks/bottle/holywater,/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor/carpet/black,/area/chapel/office) "bcv" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plasteel,/area/hallway/secondary/entry) -"bcw" = (/obj/machinery/alarm{pixel_y = 25},/obj/machinery/camera{c_tag = "Chapel Chaplain's Office"; dir = 2; network = list("SS13")},/obj/structure/table/wood,/obj/item/soulstone/anybody/chaplain,/turf/simulated/floor/carpet/black,/area/chapel/office) +"bcw" = (/obj/machinery/alarm{pixel_y = 25},/obj/machinery/camera{c_tag = "Chapel Chaplain's Office"; dir = 2; network = list("SS13")},/obj/structure/table/wood,/turf/simulated/floor/carpet/black,/area/chapel/office) "bcx" = (/turf/simulated/floor/carpet/black,/area/chapel/office) "bcy" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/grass,/area/hydroponics) "bcz" = (/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) @@ -2927,7 +2927,7 @@ "beo" = (/obj/structure/chair/office/dark{dir = 8},/turf/simulated/floor/wood,/area/library) "bep" = (/obj/machinery/newscaster{pixel_x = 30},/turf/simulated/floor/wood,/area/library) "beq" = (/obj/machinery/ai_status_display{pixel_x = -32; pixel_y = 0; step_size = 0},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) -"ber" = (/obj/structure/table/wood,/obj/item/stack/tile/carpet/black{amount = 10},/obj/item/nullrod,/turf/simulated/floor/carpet/black,/area/chapel/office) +"ber" = (/obj/structure/table/wood,/obj/item/stack/tile/carpet/black{amount = 10},/turf/simulated/floor/carpet/black,/area/chapel/office) "bes" = (/obj/item/radio/intercom{name = "station intercom (General)"; pixel_y = -28},/turf/simulated/shuttle/floor,/area/shuttle/arrival/station) "bet" = (/obj/structure/chair{dir = 4},/obj/effect/landmark/start{name = "Chaplain"},/turf/simulated/floor/carpet/black,/area/chapel/office) "beu" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/carpet/black,/area/chapel/office) @@ -4009,7 +4009,7 @@ "bze" = (/obj/structure/sign/barsign,/turf/simulated/wall,/area/crew_quarters/bar) "bzf" = (/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard/west) "bzg" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard/west) -"bzh" = (/obj/machinery/camera{c_tag = "Starboard Primary Hallway 2"; dir = 2; network = list("SS13")},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard/west) +"bzh" = (/obj/machinery/camera{c_tag = "Starboard Primary Hallway 2"; dir = 2; network = list("SS13")},/obj/structure/closet/crate/can,/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard/west) "bzi" = (/obj/item/radio/intercom{pixel_y = 25},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) "bzj" = (/obj/structure/table/reinforced,/obj/machinery/door/firedoor,/obj/machinery/door/window/westright{dir = 1; name = "Hydroponics Desk"; req_access_txt = "35"},/turf/simulated/floor/plasteel,/area/hydroponics) "bzk" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/public/glass{name = "Hydroponics"; req_access_txt = "35"},/turf/simulated/floor/plasteel,/area/hydroponics) @@ -4270,7 +4270,7 @@ "bEf" = (/obj/item/paper_bin{pixel_x = -3; pixel_y = 7},/obj/structure/table/reinforced,/turf/simulated/floor/plasteel{icon_state = "arrival"; dir = 4},/area/quartermaster/office) "bEg" = (/obj/structure/table/wood,/obj/item/folder/blue,/obj/item/stamp/captain,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bEh" = (/obj/structure/table/wood,/obj/item/hand_tele,/turf/simulated/floor/wood,/area/crew_quarters/captain) -"bEi" = (/obj/structure/table/wood,/obj/item/flashlight/lamp/green,/obj/item/paper/safe_code{owner = "captain"},/turf/simulated/floor/wood,/area/crew_quarters/captain) +"bEi" = (/obj/structure/closet/crate/medical,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/cleanable/dirt,/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/quartermaster/storage) "bEj" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/hallway/primary/central/west) "bEk" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bEl" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/radio/intercom{pixel_y = 25},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/hallway/primary/starboard/east) @@ -4308,7 +4308,7 @@ "bER" = (/turf/space,/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/shuttle/specops) "bES" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/port) "bET" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/port) -"bEU" = (/obj/structure/closet/crate/medical,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/cleanable/dirt,/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/quartermaster/storage) +"bEU" = (/obj/structure/table/wood,/obj/item/flashlight/lamp/green,/obj/item/paper/safe_code{owner = "captain"},/turf/simulated/floor/wood,/area/crew_quarters/captain) "bEV" = (/obj/machinery/light{dir = 4},/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/hallway/secondary/entry) "bEW" = (/obj/machinery/door/airlock{name = "Unit 4"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/crew_quarters/locker/locker_toilet) "bEX" = (/obj/machinery/conveyor/west{id = "garbage"},/turf/simulated/floor/plating,/area/maintenance/disposal) @@ -4439,7 +4439,7 @@ "bHs" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall/r_wall,/area/engine/gravitygenerator) "bHt" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/space,/area/space) "bHu" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/gravitygenerator) -"bHv" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/rack,/obj/item/tank/emergency_oxygen/double,/obj/item/tank/jetpack/oxygen/captain,/obj/item/clothing/suit/space/captain,/obj/item/clothing/mask/gas,/obj/item/radio/intercom/private{pixel_x = -28},/obj/item/crowbar/red,/obj/item/clothing/head/helmet/space/capspace,/turf/simulated/floor/wood,/area/crew_quarters/captain) +"bHv" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/maintenance/port) "bHw" = (/obj/machinery/computer/card,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bHx" = (/obj/structure/table/wood,/obj/machinery/recharger{pixel_y = 4},/obj/item/melee/chainofcommand,/obj/item/card/id/captains_spare,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bHy" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/wood,/area/crew_quarters/captain) @@ -4492,7 +4492,7 @@ "bIt" = (/obj/structure/table,/obj/item/stack/sheet/glass{amount = 50; pixel_x = 3; pixel_y = 3},/obj/item/stack/sheet/metal{amount = 50},/obj/item/clothing/glasses/welding,/obj/machinery/door_control{id = "rdlab"; name = "Research and Development Lab Shutters Control"; pixel_x = -24; pixel_y = 0; req_access_txt = "47"},/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTH)"; icon_state = "whitepurple"; dir = 1},/area/toxins/lab) "bIu" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/shuttle/engine/heater,/turf/simulated/floor/plating/airless,/area/shuttle/escape) "bIv" = (/obj/structure/table,/obj/item/folder/white,/obj/item/disk/tech_disk,/obj/item/disk/tech_disk,/obj/item/disk/design_disk,/obj/item/disk/design_disk,/obj/item/reagent_containers/dropper,/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTH)"; icon_state = "whitepurple"; dir = 1},/area/toxins/lab) -"bIw" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/maintenance/port) +"bIw" = (/obj/machinery/door/poddoor/shutters{dir = 2; id_tag = "qm_warehouse"; name = "Warehouse Shutters"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/warning_stripes/yellow,/obj/effect/decal/cleanable/dirt,/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/quartermaster/storage) "bIx" = (/obj/structure/shuttle/engine/heater,/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/shuttle/escape) "bIy" = (/obj/item/radio/intercom{frequency = 1459; name = "station intercom (General)"; pixel_x = 28},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab) "bIz" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel,/area/hallway/primary/starboard/east) @@ -4641,7 +4641,7 @@ "bLm" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel,/area/assembly/chargebay) "bLn" = (/obj/machinery/door/airlock/command{name = "Captain's Quarters"; req_access = null; req_access_txt = "20"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) "bLo" = (/obj/effect/decal/warning_stripes/north,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/assembly/robotics) -"bLp" = (/obj/machinery/door/airlock/maintenance{name = "Captain's Office Maintenance"; req_access_txt = "20"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/crew_quarters/captain) +"bLp" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/command{id_tag = null; name = "Captain's Office"; req_access = null; req_access_txt = "20"},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/crew_quarters/captain) "bLq" = (/obj/structure/disposalpipe/segment,/obj/structure/extinguisher_cabinet{pixel_x = -27; pixel_y = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) "bLr" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) "bLs" = (/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) @@ -4689,7 +4689,7 @@ "bMi" = (/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/obj/machinery/atmospherics/unary/vent_pump{on = 1},/obj/effect/decal/warning_stripes/southeast,/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) "bMj" = (/obj/machinery/light{dir = 8},/obj/machinery/computer/rdconsole/core,/obj/effect/decal/warning_stripes/southwest,/turf/simulated/floor/plasteel,/area/toxins/lab) "bMk" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor/plating,/area/maintenance/disposal) -"bMl" = (/obj/machinery/door/poddoor/shutters{dir = 2; id_tag = "qm_warehouse"; name = "Warehouse Shutters"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/warning_stripes/yellow,/obj/effect/decal/cleanable/dirt,/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/quartermaster/storage) +"bMl" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/wall,/area/quartermaster/storage) "bMm" = (/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable,/obj/machinery/alarm{dir = 1; pixel_y = -25},/obj/structure/closet,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plating,/area/maintenance/disposal) "bMn" = (/obj/machinery/light/small,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/maintenance/disposal) "bMo" = (/turf/simulated/shuttle/wall{tag = "icon-swall12"; icon_state = "swall12"; dir = 2},/area/shuttle/supply) @@ -4731,7 +4731,7 @@ "bMY" = (/obj/structure/table,/obj/item/storage/firstaid/regular{pixel_x = 5; pixel_y = 5},/obj/item/storage/firstaid/regular,/obj/machinery/alarm{pixel_y = 25},/obj/machinery/camera{c_tag = "Medbay Medicine Storage"; dir = 2; network = list("SS13")},/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/biostorage) "bMZ" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) "bNa" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) -"bNb" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/crew_quarters/captain) +"bNb" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/crew_quarters/captain) "bNc" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) "bNd" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) "bNe" = (/obj/structure/sign/redcross{desc = "The Star of Life, a symbol of Medical Aid."; icon_state = "lifestar"; name = "Medbay"},/turf/simulated/wall/r_wall,/area/medical/chemistry) @@ -4816,7 +4816,7 @@ "bOF" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engineering"; req_access_txt = "10"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/gravitygenerator) "bOG" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/space,/area/space) "bOH" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating,/area/engine/gravitygenerator) -"bOI" = (/obj/structure/safe/floor{knownby = list("captain")},/obj/item/gun/projectile/revolver/russian,/obj/item/reagent_containers/food/drinks/bottle/absinthe/premium,/obj/item/lighter/zippo/nt_rep,/obj/item/storage/fancy/cigarettes/cigpack_robustgold,/obj/item/toy/figure/captain,/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) +"bOI" = (/obj/structure/disposalpipe/segment,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/wall,/area/quartermaster/storage) "bOJ" = (/obj/structure/table/wood,/obj/item/flashlight/lamp/green,/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) "bOK" = (/turf/simulated/wall,/area/crew_quarters/captain/bedroom) "bOL" = (/obj/structure/toilet{dir = 4},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/crew_quarters/captain/bedroom) @@ -4826,7 +4826,7 @@ "bOP" = (/obj/structure/bed,/obj/item/bedsheet/captain,/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) "bOQ" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/medical/chemistry) "bOR" = (/obj/structure/table,/obj/item/clothing/glasses/hud/health{pixel_x = -2; pixel_y = 2},/obj/item/clothing/glasses/hud/health,/obj/item/clothing/glasses/hud/health{pixel_x = 2; pixel_y = -2},/obj/item/clothing/glasses/hud/health{pixel_x = 4; pixel_y = -4},/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/biostorage) -"bOS" = (/obj/machinery/light/small{dir = 8},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/crew_quarters/captain) +"bOS" = (/obj/machinery/light/small{dir = 8},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/crew_quarters/captain) "bOT" = (/obj/item/storage/firstaid/toxin{pixel_x = 5; pixel_y = 5},/obj/item/storage/firstaid/toxin,/obj/structure/table,/obj/structure/extinguisher_cabinet{pixel_x = 25; pixel_y = 0},/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/biostorage) "bOU" = (/turf/simulated/wall,/area/medical/chemistry) "bOV" = (/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/biostorage) @@ -4834,7 +4834,7 @@ "bOX" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) "bOY" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/medical/morgue) "bOZ" = (/obj/machinery/mech_bay_recharge_port,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/item/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/obj/machinery/camera{c_tag = "Research Mech Bay"; dir = 4; network = list("Research","SS13")},/turf/simulated/floor/plating,/area/assembly/chargebay) -"bPa" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/wall,/area/quartermaster/storage) +"bPa" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/rack,/obj/item/tank/emergency_oxygen/double,/obj/item/tank/jetpack/oxygen/captain,/obj/item/clothing/suit/space/captain,/obj/item/clothing/mask/gas,/obj/item/radio/intercom/private{pixel_x = -28},/obj/item/crowbar/red,/obj/item/clothing/head/helmet/space/capspace,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bPb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/assembly/robotics) "bPc" = (/obj/machinery/door/firedoor,/obj/machinery/door/poddoor/shutters{dir = 8; id_tag = "paramedic"; name = "Paramedic Garage"},/turf/simulated/floor/plasteel,/area/medical/paramedic) "bPd" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera{c_tag = "Research Hallway Entrance"; dir = 2; network = list("Research","SS13")},/obj/effect/decal/warning_stripes/yellow/hollow,/turf/simulated/floor/plasteel,/area/medical/research{name = "Research Division"}) @@ -4863,7 +4863,7 @@ "bPA" = (/obj/machinery/space_heater,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "bPB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab) "bPC" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 5; icon_state = "whitehall"},/area/medical/research{name = "Research Division"}) -"bPD" = (/obj/structure/disposalpipe/segment,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/wall,/area/quartermaster/storage) +"bPD" = (/obj/structure/chair/stool,/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTH)"; icon_state = "whitepurple"; dir = 1},/area/toxins/lab) "bPE" = (/obj/item/paper_bin{pixel_x = 1; pixel_y = 9},/obj/structure/table/glass,/obj/item/pen/multi,/obj/item/book/manual/sop_science{pixel_y = -14},/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bPF" = (/obj/structure/chair/stool,/obj/effect/decal/warning_stripes/east,/obj/effect/landmark/start{name = "Chemist"},/turf/simulated/floor/plasteel,/area/medical/chemistry) "bPG" = (/obj/machinery/light{dir = 8},/obj/structure/reagent_dispensers/fueltank/chem{pixel_x = -32},/obj/machinery/chem_dispenser,/turf/simulated/floor/plasteel,/area/medical/chemistry) @@ -4910,7 +4910,7 @@ "bQv" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/obj/structure/closet/secure_closet/captains,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) "bQw" = (/obj/structure/table/wood,/obj/item/radio/intercom{name = "station intercom (General)"; pixel_y = -28},/obj/item/storage/box/matches,/obj/item/reagent_containers/food/drinks/flask/gold,/obj/item/clothing/mask/cigarette/cigar,/obj/item/razor{pixel_x = -4; pixel_y = 2},/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) "bQx" = (/obj/machinery/door/window/eastright{base_state = "left"; dir = 1; icon_state = "left"; name = "Shower"; req_access_txt = "0"},/obj/machinery/shower{tag = "icon-shower (EAST)"; icon_state = "shower"; dir = 4},/obj/item/soap/deluxe,/obj/item/bikehorn/rubberducky,/obj/effect/landmark{name = "revenantspawn"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/crew_quarters/captain/bedroom) -"bQy" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/crew_quarters/captain) +"bQy" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/crew_quarters/captain) "bQz" = (/obj/structure/disposalpipe/segment,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) "bQA" = (/obj/structure/disposalpipe/trunk{dir = 8},/obj/machinery/disposal,/turf/simulated/floor/plasteel{dir = 4; icon_state = "whiteyellow"},/area/medical/chemistry) "bQB" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/biostorage) @@ -5002,7 +5002,7 @@ "bSj" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall/r_wall,/area/teleporter) "bSk" = (/obj/machinery/power/smes{charge = 5e+006},/obj/structure/cable,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/item/radio/intercom{dir = 4; name = "station intercom (General)"; pixel_x = 28},/turf/simulated/floor/plasteel,/area/engine/gravitygenerator) "bSl" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plasteel,/area/engine/gravitygenerator) -"bSm" = (/obj/machinery/door/airlock/maintenance{name = "Teleporter Maintenance"; req_access_txt = "17"},/obj/structure/sign/securearea{pixel_x = -32; pixel_y = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/teleporter) +"bSm" = (/obj/structure/sign/securearea{pixel_x = -32; pixel_y = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/command{name = "Teleport Access"; req_access_txt = "17"},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/teleporter) "bSn" = (/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/chemistry) "bSo" = (/obj/machinery/vending/medical,/obj/machinery/camera{c_tag = "Medbay Corridor West"; dir = 4; network = list("SS13")},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitebluecorner"; tag = "icon-whitebluecorner"},/area/medical/medbay2) "bSp" = (/obj/structure/disposalpipe/segment,/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) @@ -5124,7 +5124,7 @@ "bUB" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 5; icon_state = "intact"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/medical/genetics_cloning) "bUC" = (/obj/machinery/light,/obj/effect/decal/warning_stripes/arrow{icon_state = "4"; dir = 8},/obj/effect/decal/warning_stripes/yellow/partial{icon_state = "3"; dir = 8},/turf/simulated/floor/plasteel,/area/quartermaster/storage) "bUD" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; initialize_directions = 10},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/medical/genetics_cloning) -"bUE" = (/obj/machinery/optable{name = "Robotics Operating Table"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics) +"bUE" = (/obj/structure/disposalpipe/junction{tag = "icon-pipe-j2 (EAST)"; icon_state = "pipe-j2"; dir = 4},/turf/simulated/wall,/area/quartermaster/office) "bUF" = (/obj/machinery/computer/operating{name = "Robotics Operating Computer"},/obj/machinery/light,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics) "bUG" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/disposalpipe/sortjunction{dir = 8; icon_state = "pipe-j2s"; name = "Med. CMO"; sortType = 10},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/medbay2) "bUH" = (/obj/structure/closet/wardrobe/robotics_black,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics) @@ -6318,12 +6318,12 @@ "crz" = (/obj/structure/sign/poster/contraband/smoke{pixel_x = -32},/obj/effect/spawner/random_spawners/blood_maybe,/turf/simulated/floor/plating,/area/maintenance/asmaint) "crA" = (/turf/simulated/floor/plasteel{dir = 4; icon_state = "whitebluecorner"; tag = "icon-whitebluecorner"},/area/medical/medbay2) "crB" = (/obj/effect/decal/warning_stripes/west,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/medbay2) -"crC" = (/obj/structure/rack,/obj/item/clothing/suit/radiation,/obj/item/clothing/head/radiation,/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) +"crC" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/quartermaster/office) "crD" = (/turf/simulated/wall,/area/medical/psych) "crE" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/medical/cmostore) "crF" = (/obj/structure/closet/l3closet,/obj/item/clothing/mask/gas,/obj/machinery/light{dir = 1; in_use = 1},/obj/item/radio/intercom{pixel_y = 25},/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) -"crG" = (/obj/structure/rack,/obj/item/clothing/suit/radiation,/obj/item/clothing/head/radiation,/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) -"crH" = (/obj/structure/closet/l3closet,/obj/item/clothing/mask/gas,/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) +"crG" = (/obj/structure/safe/floor{knownby = list("captain")},/obj/item/gun/projectile/revolver/russian,/obj/item/reagent_containers/food/drinks/bottle/absinthe/premium,/obj/item/lighter/zippo/nt_rep,/obj/item/storage/fancy/cigarettes/cigpack_robustgold,/obj/item/toy/figure/captain,/turf/simulated/floor/carpet,/area/crew_quarters/captain/bedroom) +"crH" = (/obj/machinery/optable{name = "Robotics Operating Table"},/obj/item/storage/firstaid/machine,/obj/item/storage/firstaid/machine,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics) "crI" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/effect/spawner/random_spawners/blood_maybe,/turf/simulated/floor/plating,/area/maintenance/genetics) "crJ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plating,/area/maintenance/genetics) "crK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/maintenance/genetics) @@ -6405,10 +6405,10 @@ "cti" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitebluecorner"; tag = "icon-whitebluecorner"},/area/medical/medbay2) "ctj" = (/obj/effect/decal/warning_stripes/northwestcorner,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{tag = "icon-whitebluecorner (WEST)"; icon_state = "whitebluecorner"; dir = 8},/area/medical/medbay2) "ctk" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/medical/cmostore) -"ctl" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical/glass{id_tag = null; name = "Secondary Storage"; req_access_txt = "39"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/medical/cmostore) +"ctl" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) "ctm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) "ctn" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10; initialize_directions = 10; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plasteel{dir = 6; icon_state = "blue"},/area/medical/cmostore) -"cto" = (/obj/structure/table,/obj/item/storage/firstaid/brute{pixel_x = 2; pixel_y = 2},/obj/item/storage/firstaid/fire,/obj/machinery/status_display{layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) +"cto" = (/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/mixing) "ctp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 10},/area/medical/cmostore) "ctq" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/maintenance/genetics) "ctr" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/genetics) @@ -6468,11 +6468,11 @@ "cut" = (/obj/effect/spawner/window/reinforced,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "open"; id_tag = "psychoffice"; name = "Privacy Shutters"; opacity = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/medical/psych) "cuu" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical{name = "Psych Office"; req_access_txt = "64"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/turf/simulated/floor/wood,/area/medical/psych) "cuv" = (/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitebluecorner"; tag = "icon-whitebluecorner"},/area/medical/medbay2) -"cuw" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/hardsuit/medical,/obj/machinery/light_switch{pixel_x = -23; pixel_y = 0},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 8},/area/medical/cmostore) +"cuw" = (/obj/structure/closet/radiation,/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) "cux" = (/turf/simulated/wall/r_wall,/area/medical/psych) "cuy" = (/turf/simulated/floor/plasteel{dir = 4; icon_state = "bluefull"},/area/medical/cmostore) "cuz" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 8},/area/medical/cmostore) -"cuA" = (/obj/structure/table,/obj/item/storage/firstaid/adv{pixel_x = 2; pixel_y = 2},/obj/item/storage/firstaid/regular,/obj/machinery/camera{c_tag = "Medbay Secure Storage"; dir = 8; network = list("SS13")},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) +"cuA" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/closet/radiation,/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) "cuB" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) "cuC" = (/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24; shock_proof = 0},/obj/structure/cable{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/maintenance/genetics) "cuD" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/genetics) @@ -6544,10 +6544,10 @@ "cvR" = (/obj/structure/closet/secure_closet/psychiatrist,/obj/item/clipboard{pixel_x = -5},/obj/machinery/door_control{id = "psychoffice"; name = "Privacy Shutters Control"; pixel_x = -25; pixel_y = 0},/turf/simulated/floor/wood,/area/medical/psych) "cvS" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/wood,/area/medical/psych) "cvT" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/turf/simulated/floor/wood,/area/medical/psych) -"cvU" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/hardsuit/medical,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 10},/area/medical/cmostore) +"cvU" = (/obj/structure/closet/l3closet,/obj/item/clothing/mask/gas,/obj/machinery/status_display{layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/medical/cmostore) "cvV" = (/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/medical/cmostore) "cvW" = (/turf/simulated/floor/plasteel{dir = 5; icon_state = "blue"},/area/medical/cmostore) -"cvX" = (/obj/structure/table,/obj/item/storage/firstaid/o2{pixel_x = 2; pixel_y = 2},/obj/item/storage/firstaid/toxin,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) +"cvX" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical/glass{id_tag = null; name = "Secondary Storage"; req_access_txt = "5"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/medical/cmostore) "cvY" = (/turf/simulated/floor/plasteel{dir = 9; icon_state = "blue"},/area/medical/cmostore) "cvZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/wall/r_wall,/area/maintenance/asmaint) "cwa" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/ai_status_display{pixel_x = -32; pixel_y = 0; step_size = 0},/turf/simulated/floor/plasteel{tag = "icon-whitegreen (NORTHWEST)"; icon_state = "whitegreen"; dir = 9},/area/medical/virology) @@ -6563,12 +6563,12 @@ "cwk" = (/obj/machinery/disposal,/obj/structure/sign/poster/random{pixel_x = -32; pixel_y = 0},/obj/structure/disposalpipe/trunk{dir = 4},/turf/simulated/floor/wood,/area/medical/psych) "cwl" = (/obj/structure/cable,/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/wood,/area/medical/psych) "cwm" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor/wood,/area/medical/psych) -"cwn" = (/obj/structure/table,/obj/item/assembly/timer,/obj/item/assembly/timer,/obj/item/assembly/timer,/obj/machinery/light,/obj/item/grenade/chem_grenade,/obj/item/grenade/chem_grenade,/obj/item/grenade/chem_grenade,/obj/item/grenade/chem_grenade,/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/medical/cmostore) +"cwn" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/hardsuit/medical,/obj/machinery/door/window/westright{name = "Emergency Hardsuits"; req_access_txt = "40"},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) "cwo" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/engine/break_room) "cwp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/medical/research{name = "Research Division"}) "cwq" = (/obj/machinery/camera{c_tag = "Research E.X.P.E.R.I-MENTOR Lab"; dir = 1; network = list("Research","SS13")},/obj/structure/disposalpipe/trunk{dir = 4},/obj/machinery/disposal,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/explab) -"cwr" = (/obj/structure/table,/obj/machinery/cell_charger,/turf/simulated/floor/plasteel{dir = 5; icon_state = "blue"},/area/medical/cmostore) -"cws" = (/obj/structure/table,/obj/item/assembly/igniter,/obj/item/assembly/igniter,/obj/machinery/alarm{dir = 1; pixel_y = -22},/turf/simulated/floor/plasteel{dir = 6; icon_state = "blue"},/area/medical/cmostore) +"cwr" = (/obj/machinery/light_switch{pixel_x = -23; pixel_y = 0},/obj/structure/table,/obj/item/storage/box/pillbottles{layer = 4},/obj/item/storage/box/bodybags{layer = 3; pixel_x = 5; pixel_y = 5},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 8},/area/medical/cmostore) +"cws" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/hardsuit/medical,/obj/item/clothing/mask/gas,/obj/item/clothing/head/helmet/space/hardsuit/medical,/obj/machinery/door/window/westleft{name = "Emergency Hardsuits"; req_access_txt = "40"},/obj/structure/window/reinforced,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) "cwt" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/wall/r_wall,/area/atmos/control) "cwu" = (/obj/machinery/atmospherics/unary/tank/air{dir = 8},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cwv" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/turf/simulated/floor/plasteel{dir = 8; icon_state = "whitegreencorner"},/area/medical/research{name = "Research Division"}) @@ -6943,7 +6943,7 @@ "cDA" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) "cDB" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "whitepurplecorner"},/area/toxins/misc_lab) "cDC" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/misc_lab) -"cDD" = (/obj/structure/chair/stool,/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTH)"; icon_state = "whitepurple"; dir = 1},/area/toxins/lab) +"cDD" = (/obj/structure/chair/office/light{dir = 1},/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{tag = "icon-vault (NORTHEAST)"; icon_state = "vault"; dir = 5},/area/toxins/misc_lab) "cDE" = (/obj/effect/decal/warning_stripes/west,/turf/simulated/floor/plasteel{tag = "icon-vault (NORTHEAST)"; icon_state = "vault"; dir = 5},/area/toxins/misc_lab) "cDF" = (/obj/structure/chair/office/light{dir = 4},/turf/simulated/floor/plasteel{tag = "icon-vault (NORTHEAST)"; icon_state = "vault"; dir = 5},/area/toxins/misc_lab) "cDG" = (/turf/simulated/floor/plasteel{tag = "icon-vault (NORTHEAST)"; icon_state = "vault"; dir = 5},/area/toxins/misc_lab) @@ -7633,7 +7633,7 @@ "cQO" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/maintenance/genetics) "cQP" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/atmos) "cQQ" = (/obj/machinery/pipedispenser/disposal,/turf/simulated/floor/plasteel,/area/atmos) -"cQR" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{aiControlDisabled = 0; frequency = 1379; hackProof = 0; icon_state = "door_locked"; id_tag = "atmospherics_south_inner"; locked = 1; name = "Atmospherics External Access"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/engine/engineering) +"cQR" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/structure/table,/obj/item/storage/box/syringes{pixel_x = 5; pixel_y = 5},/obj/item/storage/box/autoinjectors,/obj/item/reagent_containers/syringe/antiviral{pixel_y = 19},/obj/item/reagent_containers/syringe/antiviral{pixel_x = 0; pixel_y = 13},/obj/item/reagent_containers/syringe/antiviral{pixel_y = 16},/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 10},/area/medical/cmostore) "cQS" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/turf/simulated/floor/plating,/area/engine/equipmentstorage) "cQT" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel,/area/atmos/distribution) "cQU" = (/obj/machinery/light_switch{pixel_x = 27},/obj/structure/reagent_dispensers/watertank,/obj/machinery/atmospherics/unary/vent_pump{dir = 1; external_pressure_bound = 101; on = 1; pressure_checks = 1},/obj/effect/decal/warning_stripes/northwest,/turf/simulated/floor/plating,/area/storage/secure) @@ -7662,7 +7662,7 @@ "cRr" = (/obj/machinery/light,/obj/effect/decal/warning_stripes/south,/turf/simulated/floor/plasteel,/area/engine/engineering) "cRs" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = -32},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engineering) "cRt" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/reagentgrinder,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) -"cRu" = (/obj/structure/disposalpipe/junction{tag = "icon-pipe-j2 (EAST)"; icon_state = "pipe-j2"; dir = 4},/turf/simulated/wall,/area/quartermaster/office) +"cRu" = (/obj/structure/table,/obj/item/storage/firstaid/brute{pixel_x = 5; pixel_y = 5},/obj/item/storage/firstaid/toxin,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/medical/cmostore) "cRv" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) "cRw" = (/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; master_tag = "engineering_west_airlock"; name = "interior access button"; pixel_x = -20; pixel_y = -20; req_access_txt = "10;13"},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/warning_stripes/south,/turf/simulated/floor/plasteel,/area/engine/engineering) "cRx" = (/obj/machinery/processor{name = "Slime Processor"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) @@ -7736,7 +7736,7 @@ "cSN" = (/obj/structure/chair/stool,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/decal/warning_stripes/south,/turf/simulated/floor/plasteel,/area/engine/engineering) "cSO" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/item/stack/sheet/mineral/plasma{pixel_x = -2; pixel_y = -2},/obj/item/stack/sheet/mineral/plasma,/obj/item/stack/sheet/mineral/plasma{pixel_x = 2; pixel_y = 2},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) "cSP" = (/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/obj/structure/extinguisher_cabinet{pixel_x = 27; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) -"cSQ" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/transit_tube/station,/obj/structure/transit_tube_pod{dir = 8},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/engineering) +"cSQ" = (/obj/structure/table,/obj/machinery/light,/obj/item/storage/firstaid/adv{pixel_x = 5; pixel_y = 5},/obj/item/storage/firstaid/fire,/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/medical/cmostore) "cSR" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = -32; pixel_y = 0},/obj/machinery/atmospherics/unary/portables_connector,/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating,/area/maintenance/portsolar) "cSS" = (/obj/machinery/optable{name = "Robotics Operating Table"},/obj/machinery/light,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/assembly_line) "cST" = (/obj/structure/cable{d2 = 2; icon_state = "0-2"},/obj/machinery/power/smes{charge = 0},/turf/simulated/floor/plating,/area/maintenance/portsolar) @@ -8143,8 +8143,8 @@ "daE" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 2; icon_state = "ramptop"; tag = "icon-stage_stairs"},/area/escapepodbay) "daF" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engine Room"; req_access_txt = "10"; req_one_access_txt = null},/turf/simulated/floor/plasteel,/area/engine/engineering) "daG" = (/turf/simulated/floor/plating,/area/engine/engineering) -"daH" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/turf/simulated/floor/plating,/area/engine/engineering) -"daI" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/atmos) +"daH" = (/obj/structure/table,/obj/machinery/cell_charger,/obj/item/stock_parts/cell/high,/turf/simulated/floor/plasteel{dir = 5; icon_state = "blue"},/area/medical/cmostore) +"daI" = (/obj/structure/table,/obj/machinery/alarm{dir = 1; pixel_y = -22},/obj/item/storage/firstaid/o2{layer = 2.8; pixel_x = 5; pixel_y = 5},/obj/item/storage/firstaid,/turf/simulated/floor/plasteel{dir = 6; icon_state = "blue"},/area/medical/cmostore) "daJ" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/obj/effect/decal/warning_stripes/southeastcorner,/turf/simulated/floor/plasteel,/area/engine/engineering) "daK" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{level = 1},/obj/machinery/vending/wallmed1{name = "Emergency NanoMed"; pixel_x = 0; pixel_y = -32; req_access_txt = "0"},/turf/simulated/floor/plasteel,/area/engine/engineering) "daL" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plasteel,/area/atmos) @@ -8191,7 +8191,7 @@ "dbA" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/wall/r_wall,/area/engine/engineering) "dbB" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'RADIOACTIVE AREA'"; icon_state = "radiation"; name = "RADIOACTIVE AREA"; pixel_x = 32; pixel_y = 0},/turf/simulated/wall/r_wall,/area/engine/engineering) "dbC" = (/obj/machinery/door/firedoor,/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Singularity"; name = "Singularity Blast Doors"; opacity = 0},/obj/machinery/door/airlock/engineering/glass{name = "Engine Room"; req_access_txt = "10"; req_one_access_txt = null},/turf/simulated/floor/plating,/area/engine/engineering) -"dbD" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/engine/engineering) +"dbD" = (/obj/structure/chair{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) "dbE" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Singularity"; name = "Singularity Shutters"; opacity = 0},/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/engine/engineering) "dbF" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Singularity"; name = "Singularity Shutters"; opacity = 0},/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/engine/engineering) "dbG" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Singularity"; name = "Singularity Shutters"; opacity = 0},/obj/effect/spawner/window/reinforced,/obj/structure/sign/securearea{desc = "A warning sign which reads 'RADIOACTIVE AREA'"; icon_state = "radiation"; name = "RADIOACTIVE AREA"; pixel_x = 32; pixel_y = 0},/turf/simulated/floor/plating,/area/engine/engineering) @@ -8230,9 +8230,9 @@ "dcn" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{level = 1},/turf/simulated/wall/r_wall,/area/engine/engineering) "dco" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/hallway/primary/central/ne) "dcp" = (/obj/machinery/porta_turret{dir = 1},/obj/structure/sign/securearea{pixel_x = 32; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{icon_state = "darkbluecorners"},/area/turret_protected/aisat_interior) -"dcq" = (/obj/machinery/door/airlock/external{aiControlDisabled = 0; frequency = 1379; hackProof = 0; icon_state = "door_locked"; id_tag = "atmospherics_south_outer"; locked = 1; name = "Atmospherics External Access"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/engine/engineering) +"dcq" = (/turf/simulated/wall/r_wall,/area/maintenance/storage) "dcr" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 10},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/maintenance/turbine) -"dcs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/effect/decal/cleanable/fungus,/turf/simulated/wall/r_wall,/area/engine/engineering) +"dcs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/turf/simulated/floor/plating,/area/maintenance/storage) "dct" = (/obj/machinery/portable_atmospherics/scrubber,/turf/simulated/floor/plasteel,/area/atmos) "dcu" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/maintenance/turbine) "dcv" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/manifold/visible{dir = 8},/turf/simulated/floor/plasteel,/area/atmos) @@ -8283,7 +8283,7 @@ "ddo" = (/obj/structure/reagent_dispensers/watertank,/obj/item/extinguisher,/obj/structure/extinguisher_cabinet{pixel_y = -30},/obj/machinery/light/small,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/maintenance/turbine) "ddp" = (/obj/machinery/atmospherics/pipe/simple/visible/purple,/obj/machinery/computer/turbine_computer{id = "incineratorturbine"},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/maintenance/turbine) "ddq" = (/obj/machinery/hologram/holopad,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/maintenance/turbine) -"ddr" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = -32},/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/machinery/door/airlock/external{name = "Engineering Escape Pod"; req_access = null; req_access_txt = "10"},/turf/simulated/floor/plating,/area/engine/engineering) +"ddr" = (/turf/simulated/floor/plating,/area/maintenance/storage) "dds" = (/obj/machinery/portable_atmospherics/pump,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/atmos) "ddt" = (/obj/machinery/atmospherics/binary/pump{dir = 0; name = "Port to Filter"; on = 0},/turf/simulated/floor/plasteel,/area/atmos) "ddu" = (/obj/structure/chair/stool,/obj/machinery/atmospherics/pipe/simple/visible{dir = 5},/obj/item/wrench,/obj/machinery/light/small{dir = 8},/obj/effect/decal/warning_stripes/southwest,/turf/simulated/floor/plating,/area/maintenance/asmaint) @@ -8317,7 +8317,7 @@ "ddW" = (/turf/space,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating/airless/catwalk,/area/solar/starboard) "ddX" = (/turf/space,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/plating/airless/catwalk,/area/solar/starboard) "ddY" = (/turf/simulated/floor/plating,/obj/structure/shuttle/engine/propulsion/burst{dir = 8},/turf/simulated/shuttle/wall{tag = "icon-swall_f6"; icon_state = "swall_f6"; dir = 2},/area/shuttle/pod_4) -"ddZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/engine/engineering) +"ddZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/maintenance/storage) "dea" = (/obj/machinery/space_heater,/turf/simulated/floor/plasteel,/area/atmos) "deb" = (/turf/space,/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1450; master_tag = "sci_maint"; name = "exterior access button"; pixel_x = 8; pixel_y = 25; req_access_txt = "13"},/turf/simulated/floor/plating/airless/catwalk{tag = "icon-catwalk0"; icon_state = "catwalk0"},/area/space) "dec" = (/obj/machinery/atmospherics/pipe/manifold/visible,/turf/simulated/floor/plasteel,/area/atmos) @@ -8337,32 +8337,41 @@ "deq" = (/obj/machinery/computer/guestpass,/turf/simulated/wall,/area/medical/reception) "der" = (/obj/structure/table,/turf/simulated/floor/plating,/area/maintenance/asmaint) "des" = (/obj/machinery/light/small{dir = 8},/obj/machinery/field/generator,/turf/simulated/floor/plating,/area/storage/secure) -"det" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/quartermaster/office) +"det" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/storage) "deu" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/wall,/area/engine/engineering) -"dev" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) -"dew" = (/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/mixing) -"dex" = (/obj/structure/chair/office/light{dir = 1},/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{tag = "icon-vault (NORTHEAST)"; icon_state = "vault"; dir = 5},/area/toxins/misc_lab) -"dey" = (/obj/structure/chair{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) +"dev" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/effect/decal/cleanable/fungus,/turf/simulated/wall/r_wall,/area/maintenance/storage) +"dew" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/power/apc{dir = 4; pixel_x = 24},/turf/simulated/floor/plating,/area/maintenance/storage) +"dex" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = -32},/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/machinery/door/airlock/maintenance{name = "Atmospherics Maintenance"; req_access_txt = "10"; req_one_access_txt = null},/turf/simulated/floor/plating,/area/maintenance/storage) +"dey" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/small{dir = 8},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/storage) +"dez" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/storage) "deA" = (/obj/structure/chair/stool,/turf/simulated/floor/plasteel,/area/engine/engineering) "deB" = (/obj/structure/particle_accelerator/power_box,/turf/simulated/floor/plating,/area/engine/engineering) "deC" = (/obj/item/screwdriver,/turf/simulated/floor/plasteel,/area/engine/engineering) +"deD" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plasteel,/area/atmos) +"deE" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/storage) "deF" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Singularity"; name = "Singularity Blast Doors"; opacity = 0},/turf/simulated/floor/plating,/area/engine/engineering) +"deG" = (/obj/machinery/atmospherics/pipe/simple/visible/purple,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/atmos) "deH" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/floor/plasteel,/area/atmos) "deI" = (/obj/machinery/atmospherics/pipe/manifold/visible/purple,/turf/simulated/floor/plasteel,/area/atmos) "deJ" = (/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/floor/plasteel,/area/atmos) "deK" = (/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 9},/turf/simulated/floor/plasteel,/area/atmos) +"deL" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "atmos"; name = "Atmos Blast Door"; opacity = 0},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = -32},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/maintenance{name = "Atmospherics Maintenance"; req_access_txt = "24"},/turf/simulated/floor/plating,/area/maintenance/storage) +"deM" = (/obj/structure/table,/obj/item/wrench,/obj/item/t_scanner,/obj/item/storage/belt/utility,/obj/item/storage/belt/utility,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plasteel,/area/atmos) +"deN" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/maintenance/storage) "deO" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 6},/obj/machinery/power/apc{dir = 8; name = "west bump Engineering"; pixel_x = -24; shock_proof = 1},/turf/simulated/floor/plasteel,/area/atmos) -"deP" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/floor/plasteel,/area/atmos) +"deP" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/maintenance/storage) "deQ" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 6; initialize_directions = 6; level = 2},/turf/simulated/floor/plasteel,/area/atmos) "deR" = (/obj/machinery/atmospherics/binary/pump{dir = 4; name = "N2 to Pure"; on = 0},/turf/simulated/floor/plasteel,/area/atmos) "deS" = (/obj/structure/sign/nosmoking_2{pixel_y = 32},/turf/simulated/floor/plating,/area/maintenance/asmaint) "deT" = (/obj/structure/chair/stool,/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor/plating,/area/maintenance/asmaint) "deU" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 9; tag = "icon-intact-y (NORTHWEST)"},/turf/simulated/floor/plasteel,/area/atmos) "deV" = (/obj/machinery/computer/general_air_control/large_tank_control{frequency = 1441; input_tag = "co2_in"; name = "Carbon Dioxide Supply Control"; output_tag = "co2_out"; sensors = list("co2_sensor" = "Tank")},/turf/simulated/floor/plasteel{icon_state = "caution"; dir = 4},/area/atmos) +"deW" = (/obj/machinery/light/small{dir = 8},/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 32},/turf/simulated/floor/plating,/area/maintenance/storage) "deX" = (/obj/machinery/air_sensor{frequency = 1441; id_tag = "co2_sensor"},/turf/simulated/floor/engine{carbon_dioxide = 50000; name = "co2 floor"; nitrogen = 0; oxygen = 0},/area/atmos) "deY" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor/engine{carbon_dioxide = 50000; name = "co2 floor"; nitrogen = 0; oxygen = 0},/area/atmos) "deZ" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plating,/area/maintenance/asmaint) "dfa" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5; level = 1},/turf/simulated/floor/plating,/area/maintenance/asmaint) +"dfb" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/floor/plating,/area/maintenance/storage) "dfc" = (/obj/structure/table,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "dfd" = (/turf/simulated/wall/r_wall,/area/maintenance/engi_shuttle) "dfe" = (/obj/machinery/pipedispenser/disposal,/turf/simulated/floor/plating,/area/storage/secure) @@ -8370,19 +8379,28 @@ "dfg" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/asmaint) "dfh" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/wall/r_wall,/area/maintenance/asmaint2) "dfi" = (/obj/structure/table,/obj/effect/spawner/lootdrop/maintenance,/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plating,/area/maintenance/asmaint2) +"dfj" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1379; id_tag = "atmospherics_south_pump"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "atmospherics_south_sensor"; pixel_x = -8; pixel_y = -30},/obj/machinery/embedded_controller/radio/airlock/airlock_controller{frequency = 1379; id_tag = "atmospherics_south"; pixel_x = 0; pixel_y = -25; req_access_txt = null; tag_airpump = "atmospherics_south_pump"; tag_chamber_sensor = "atmospherics_south_sensor"; tag_exterior_door = "atmospherics_south_outer"; tag_interior_door = "atmospherics_south_inner"},/turf/simulated/floor/plating,/area/maintenance/storage) "dfk" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/engine/engineering) +"dfl" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/machinery/door/airlock/external{aiControlDisabled = 0; frequency = 1379; hackProof = 0; icon_state = "door_locked"; id_tag = "atmospherics_south_inner"; locked = 1; name = "Atmospherics External Access"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/maintenance/storage) +"dfm" = (/obj/machinery/door/airlock/external{aiControlDisabled = 0; frequency = 1379; hackProof = 0; icon_state = "door_locked"; id_tag = "atmospherics_south_outer"; locked = 1; name = "Atmospherics External Access"; req_access_txt = "13"},/turf/simulated/floor/plating,/area/maintenance/storage) +"dfn" = (/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/access_button/airlock_interior{master_tag = "atmospherics_south"; pixel_x = 22; pixel_y = 10},/turf/simulated/floor/plating,/area/maintenance/storage) "dfo" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/engine/engineering) +"dfp" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/storage) "dfq" = (/obj/structure/particle_accelerator/particle_emitter/left,/turf/simulated/floor/plating,/area/engine/engineering) "dfr" = (/obj/structure/particle_accelerator/particle_emitter/center,/turf/simulated/floor/plating,/area/engine/engineering) "dfs" = (/obj/structure/particle_accelerator/particle_emitter/right,/turf/simulated/floor/plating,/area/engine/engineering) "dft" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/engine/engineering) +"dfu" = (/obj/machinery/camera{c_tag = "Mini Satellite Access"; dir = 4; network = list("SS13","MiniSat")},/obj/structure/closet/emcloset,/turf/simulated/floor/plasteel{dir = 9; icon_state = "blue"},/area/maintenance/storage) "dfv" = (/obj/machinery/light/small{dir = 4},/obj/structure/closet/walllocker/emerglocker/north,/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/engine/engineering) "dfw" = (/obj/machinery/light/small{dir = 8},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1379; id_tag = "engineering_west_pump"},/obj/structure/closet/walllocker/emerglocker/north,/turf/simulated/floor/plating,/area/engine/engineering) -"dfx" = (/obj/structure/table,/obj/item/wrench,/obj/item/t_scanner,/obj/item/storage/belt/utility,/obj/item/storage/belt/utility,/turf/simulated/floor/plasteel,/area/atmos) +"dfx" = (/obj/structure/sign/securearea,/turf/simulated/wall/r_wall,/area/maintenance/storage) "dfy" = (/obj/structure/chair/stool,/turf/simulated/floor/plasteel,/area/atmos) "dfz" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 32},/turf/simulated/wall/r_wall,/area/engine/engineering) +"dfA" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/transit_tube{dir = 4; icon_state = "Block"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/maintenance/storage) "dfB" = (/obj/machinery/atmospherics/pipe/manifold/visible/cyan{level = 2},/turf/simulated/floor/plasteel,/area/atmos) -"dfE" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "atmos"; name = "Atmos Blast Door"; opacity = 0},/obj/machinery/door/airlock/external{name = "Engineering Escape Pod"; req_access = null; req_access_txt = "24"},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = -32},/turf/simulated/floor/plating,/area/atmos) +"dfC" = (/obj/item/radio/intercom{dir = 1; name = "station intercom (General)"; pixel_y = 25},/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/maintenance/storage) +"dfD" = (/obj/effect/spawner/window/reinforced,/obj/structure/transit_tube,/turf/simulated/floor/plating,/area/maintenance/storage) +"dfE" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/transit_tube/station,/obj/structure/transit_tube_pod{dir = 8},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/maintenance/storage) "dfF" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 4; level = 2},/turf/simulated/floor/plasteel,/area/atmos) "dfG" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 4; level = 2},/obj/machinery/meter,/turf/simulated/floor/plasteel,/area/atmos) "dfH" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 4; level = 2},/obj/machinery/atmospherics/binary/pump{dir = 1; name = "O2 to Pure"; on = 0},/turf/simulated/floor/plasteel,/area/atmos) @@ -8394,7 +8412,10 @@ "dfN" = (/obj/machinery/atmospherics/pipe/simple/visible/green{dir = 4; level = 2},/turf/simulated/floor/plasteel{dir = 6; icon_state = "caution"},/area/atmos) "dfO" = (/obj/machinery/atmospherics/unary/outlet_injector{dir = 8; frequency = 1441; icon_state = "on"; id = "co2_in"; on = 1; pixel_y = 1},/turf/simulated/floor/engine{carbon_dioxide = 50000; name = "co2 floor"; nitrogen = 0; oxygen = 0},/area/atmos) "dfP" = (/obj/structure/table,/turf/simulated/floor/plating,/area/maintenance/asmaint2) +"dfQ" = (/obj/machinery/light_switch{name = "light switch "; dir = 2; pixel_x = 0; pixel_y = -22},/turf/simulated/floor/plasteel{dir = 10; icon_state = "blue"},/area/maintenance/storage) +"dfR" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/command{name = "MiniSat Access"; req_access_txt = "75"},/turf/simulated/floor/plasteel,/area/maintenance/storage) "dfS" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/wall,/area/maintenance/asmaint2) +"dfT" = (/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/maintenance/storage) "dfU" = (/obj/structure/grille,/obj/structure/window/reinforced/tinted{dir = 8; icon_state = "twindow"; tag = ""},/obj/structure/window/reinforced/tinted{dir = 1},/obj/structure/window/reinforced/tinted{dir = 4; icon_state = "twindow"; tag = ""},/obj/structure/window/reinforced/tinted,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "dfV" = (/turf/simulated/floor/plating,/area/storage/secure) "dfW" = (/obj/docking_port/stationary{dir = 2; dwidth = 2; height = 18; id = "skipjack_sw"; name = "southwest of SS13"; width = 19},/turf/space,/area/space) @@ -8402,14 +8423,22 @@ "dfY" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/constructionsite) "dfZ" = (/obj/machinery/door/airlock/external{id_tag = "s_docking_airlock"; name = "Shuttle Hatch"; req_access_txt = "0"; req_one_access_txt = "10;24"},/obj/docking_port/mobile{dir = 2; dwidth = 3; height = 5; id = "engineering"; name = "engineering shuttle"; rebuildable = 1; roundstart_move = "engineering_away"; width = 7},/obj/docking_port/stationary{dir = 2; dwidth = 3; height = 5; id = "engineering_home"; name = "engineering dock"; width = 7},/turf/simulated/floor/plating,/area/shuttle/constructionsite) "dga" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f10"; dir = 2},/area/shuttle/constructionsite) +"dgb" = (/obj/machinery/light,/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/maintenance/storage) +"dgc" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/maintenance/storage) +"dgd" = (/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 6},/area/maintenance/storage) +"dge" = (/obj/machinery/light/small{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/storage) +"dgf" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/turf/simulated/floor/plating,/area/maintenance/storage) "dgg" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{level = 2},/turf/simulated/floor/plasteel,/area/atmos) "dgh" = (/obj/machinery/atmospherics/unary/portables_connector,/turf/simulated/floor/plasteel,/area/atmos) +"dgi" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating,/area/maintenance/storage) "dgj" = (/obj/machinery/light{dir = 4},/turf/simulated/floor/plasteel,/area/atmos) "dgk" = (/obj/structure/sign/fire{pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dgl" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1379; id_tag = "engineering_east_pump"},/turf/simulated/floor/plating,/area/engine/engineering) "dgm" = (/obj/structure/closet/emcloset,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dgn" = (/obj/structure/sign/biohazard,/turf/simulated/wall,/area/maintenance/asmaint) "dgo" = (/obj/structure/disposalpipe/segment,/turf/simulated/wall,/area/maintenance/asmaint) +"dgp" = (/obj/machinery/door/airlock/external{name = "Escape Pod"},/turf/simulated/floor/plating,/area/maintenance/storage) +"dgq" = (/obj/structure/closet/emcloset,/turf/simulated/floor/plating,/area/maintenance/storage) "dgr" = (/obj/machinery/camera{c_tag = "Atmospherics South-West"; dir = 4; network = list("SS13")},/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/visible/purple,/turf/simulated/floor/plasteel,/area/atmos) "dgs" = (/obj/structure/table,/obj/item/radio{pixel_x = -6; pixel_y = 4},/obj/item/radio{pixel_x = 6; pixel_y = 4},/obj/item/radio,/turf/simulated/floor/plasteel,/area/atmos) "dgt" = (/obj/machinery/atmospherics/pipe/manifold/visible/cyan{dir = 8; initialize_directions = 11; level = 2},/obj/machinery/meter,/turf/simulated/floor/plasteel,/area/atmos) @@ -8425,6 +8454,8 @@ "dgD" = (/turf/space,/turf/simulated/shuttle/wall{tag = "icon-propulsion (EAST)"; icon_state = "propulsion"; dir = 4},/area/shuttle/constructionsite) "dgE" = (/obj/machinery/power/grounding_rod{anchored = 1},/turf/simulated/floor/plating/airless,/area/space) "dgF" = (/turf/simulated/shuttle/wall{icon_state = "swall1"; dir = 2},/area/shuttle/constructionsite) +"dgG" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'RADIOACTIVE AREA'"; icon_state = "radiation"; name = "RADIOACTIVE AREA"; pixel_x = 0; pixel_y = 0},/turf/simulated/wall/r_wall,/area/maintenance/storage) +"dgH" = (/obj/machinery/hydroponics/soil,/obj/item/seeds/carrot,/obj/item/seeds/carrot,/obj/item/seeds/carrot,/turf/simulated/floor/grass,/area/security/permabrig) "dgJ" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plating/airless,/area/space) "dgM" = (/obj/item/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 5},/turf/simulated/floor/plasteel,/area/atmos) "dgN" = (/obj/machinery/atmospherics/trinary/filter{density = 0; dir = 4; filter_type = 2; name = "Gas filter (N2 tank)"; on = 1},/turf/simulated/floor/plasteel,/area/atmos) @@ -8447,7 +8478,6 @@ "dhj" = (/obj/machinery/door/airlock/atmos{name = "Turbine Access"; req_access_txt = "12;24"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/turbine) "dhk" = (/obj/structure/rack,/obj/effect/spawner/lootdrop/maintenance{lootcount = 2; name = "2maintenance loot spawner"},/obj/item/toy/minimeteor,/obj/item/poster/random_contraband,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dho" = (/obj/machinery/camera/emp_proof{c_tag = "Engineering Singularity North-West"; dir = 2; network = list("Singularity","SS13"); pixel_x = 20; pixel_y = 0},/obj/machinery/power/grounding_rod{anchored = 1},/turf/simulated/floor/plating/airless,/area/engine/engineering) -"dhs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/engine/engineering) "dhv" = (/obj/machinery/camera/emp_proof{c_tag = "Engineering Singularity North-East"; dir = 2; network = list("Singularity","SS13")},/obj/machinery/power/grounding_rod{anchored = 1},/turf/simulated/floor/plating/airless,/area/engine/engineering) "dhx" = (/obj/machinery/light,/obj/machinery/atmospherics/binary/volume_pump/on{name = "Space Loop In"},/turf/simulated/floor/plasteel,/area/atmos) "dhz" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/structure/closet/firecloset,/obj/machinery/requests_console{department = "Atmospherics"; departmentType = 3; name = "Atmospherics Requests Console"; pixel_x = -30},/turf/simulated/floor/plasteel,/area/atmos) @@ -8538,7 +8568,6 @@ "djU" = (/obj/machinery/atmospherics/pipe/simple/visible,/obj/structure/grille,/obj/machinery/meter{frequency = 1443; id = "mair_out_meter"; name = "Mixed Air Tank Out"},/turf/simulated/wall/r_wall,/area/atmos) "djX" = (/obj/structure/disposalpipe/segment,/obj/structure/closet,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "djY" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/wall,/area/maintenance/asmaint) -"djZ" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/engine/engineering) "dka" = (/obj/machinery/door/airlock/engineering{name = "Aft Starboard Solar Access"; req_access_txt = "10"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/starboardsolar) "dkb" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 0},/turf/simulated/wall/r_wall,/area/maintenance/starboardsolar) "dkc" = (/obj/machinery/power/emitter,/obj/machinery/camera{c_tag = "Engineering Secure Storage South"; dir = 4; network = list("SS13")},/turf/simulated/floor/plating,/area/storage/secure) @@ -8624,11 +8653,9 @@ "dmb" = (/obj/effect/decal/warning_stripes/west,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "dmc" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/table,/obj/effect/spawner/lootdrop/maintenance,/obj/item/clipboard,/obj/machinery/light/small,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dmd" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "solar_xeno_inner"; locked = 1; name = "Engineering External Access"; req_access = null; req_access_txt = "13"},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/starboardsolar) -"dme" = (/obj/machinery/light/small{dir = 8},/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 32},/turf/simulated/floor/plating,/area/engine/engineering) "dmh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/public/glass{autoclose = 0; frequency = 1449; heat_proof = 1; icon_state = "door_locked"; id_tag = "gas_turbine_exterior"; locked = 1; name = "Turbine Exterior Airlock"; req_access_txt = "32"},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dmi" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/wall/r_wall/coated,/area/maintenance/asmaint) "dmj" = (/obj/item/radio,/turf/simulated/floor/plating/airless,/area/engine/engineering) -"dmk" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/floor/plating,/area/engine/engineering) "dml" = (/obj/structure/disposalpipe/junction{tag = "icon-pipe-j2 (EAST)"; icon_state = "pipe-j2"; dir = 4},/obj/machinery/atmospherics/binary/pump{name = "Waste Out"; on = 1},/turf/simulated/floor/plating,/area/maintenance/asmaint) "dmm" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/closet/emcloset,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dmn" = (/obj/effect/decal/warning_stripes/west,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint2) @@ -8639,7 +8666,6 @@ "dms" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/embedded_controller/radio/airlock/airlock_controller{tag_airpump = "solar_xeno_pump"; tag_exterior_door = "solar_xeno_outer"; frequency = 1379; id_tag = "solar_xeno_airlock"; tag_interior_door = "solar_xeno_inner"; pixel_x = 25; req_access_txt = "13"; tag_chamber_sensor = "solar_xeno_sensor"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "solar_xeno_sensor"; pixel_x = 25; pixel_y = 12},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1379; id_tag = "solar_xeno_pump"},/turf/simulated/floor/plating,/area/maintenance/starboardsolar) "dmt" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/visible/purple,/turf/simulated/floor/plating,/area/maintenance/asmaint) "dmu" = (/obj/structure/disposalpipe/segment,/turf/simulated/wall/r_wall,/area/maintenance/asmaint2) -"dmv" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1379; id_tag = "atmospherics_south_pump"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "atmospherics_south_sensor"; pixel_x = -8; pixel_y = -30},/obj/machinery/embedded_controller/radio/airlock/airlock_controller{frequency = 1379; id_tag = "atmospherics_south"; pixel_x = 0; pixel_y = -25; req_access_txt = null; tag_airpump = "atmospherics_south_pump"; tag_chamber_sensor = "atmospherics_south_sensor"; tag_exterior_door = "atmospherics_south_outer"; tag_interior_door = "atmospherics_south_inner"},/turf/simulated/floor/plating,/area/engine/engineering) "dmy" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1; frequency = 1443; id = "air_in"},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dmz" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; external_pressure_bound = 0; initialize_directions = 1; internal_pressure_bound = 4000; on = 0; pressure_checks = 2; pump_direction = 0},/obj/structure/sign/vacuum{pixel_y = -30},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dmA" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/igniter{icon_state = "igniter0"; id = "gasturbine"; on = 0},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) @@ -8649,13 +8675,9 @@ "dmE" = (/obj/machinery/door/poddoor{id_tag = "auxiliaryturbinevent"; name = "Auxiliary Turbine Vent"},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dmF" = (/obj/structure/lattice,/obj/machinery/atmospherics/pipe/simple/visible/purple,/turf/space,/area/space) "dmG" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "solar_xeno_outer"; locked = 1; name = "Engineering External Access"; req_access = null; req_access_txt = "10;13"},/turf/simulated/floor/plating,/area/maintenance/starboardsolar) -"dmL" = (/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/access_button/airlock_interior{master_tag = "atmospherics_south"; pixel_x = 22; pixel_y = 10},/turf/simulated/floor/plating,/area/engine/engineering) "dmM" = (/obj/effect/decal/warning_stripes/northeast,/obj/structure/table/glass,/obj/item/wirerod,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "dmN" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating/airless,/area/space) "dmO" = (/obj/structure/cable{d2 = 2; icon_state = "0-2"},/obj/structure/cable,/obj/machinery/power/compressor{comp_id = "incineratorturbine"; dir = 1},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) -"dmP" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/engine/engineering) -"dmQ" = (/obj/structure/sign/securearea,/turf/simulated/wall/r_wall,/area/engine/engineering) -"dmV" = (/obj/effect/spawner/window/reinforced,/obj/structure/transit_tube,/turf/simulated/floor/plating,/area/engine/engineering) "dmW" = (/obj/structure/transit_tube,/turf/space,/area/space) "dmX" = (/obj/structure/transit_tube{icon_state = "E-W-Pass"},/obj/structure/lattice,/turf/space,/area/space) "dmZ" = (/obj/structure/transit_tube,/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) @@ -8664,9 +8686,6 @@ "dnd" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/space) "dne" = (/obj/structure/cable,/obj/machinery/power/turbine,/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dng" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/maintenance/asmaint) -"dnj" = (/obj/machinery/camera{c_tag = "Mini Satellite Access"; dir = 4; network = list("SS13","MiniSat")},/obj/structure/closet/emcloset,/turf/simulated/floor/plasteel{dir = 9; icon_state = "blue"},/area/engine/engineering) -"dnk" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/transit_tube{dir = 4; icon_state = "Block"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/engineering) -"dnl" = (/obj/item/radio/intercom{dir = 1; name = "station intercom (General)"; pixel_y = 25},/turf/simulated/floor/plasteel{dir = 1; icon_state = "blue"},/area/engine/engineering) "dnn" = (/obj/machinery/portable_atmospherics/canister/air,/obj/machinery/atmospherics/unary/portables_connector{dir = 8},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "dno" = (/obj/structure/transit_tube{dir = 8; icon_state = "Block"},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dnp" = (/obj/structure/disposalpipe/trunk{dir = 1},/obj/structure/disposaloutlet,/turf/simulated/floor/plating/airless,/area/space) @@ -8674,23 +8693,14 @@ "dns" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'RADIOACTIVE AREA'"; icon_state = "radiation"; name = "RADIOACTIVE AREA"; pixel_x = 0; pixel_y = 0},/turf/simulated/wall/r_wall,/area/engine/engineering) "dnv" = (/obj/effect/decal/warning_stripes/north,/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dnx" = (/obj/structure/sign/fire,/turf/simulated/wall/r_wall/coated,/area/maintenance/turbine) -"dnA" = (/obj/machinery/light_switch{name = "light switch "; dir = 2; pixel_x = 0; pixel_y = -22},/turf/simulated/floor/plasteel{dir = 10; icon_state = "blue"},/area/engine/engineering) -"dnB" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/command{name = "MiniSat Access"; req_access_txt = "75"},/turf/simulated/floor/plasteel,/area/engine/engineering) -"dnC" = (/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/engine/engineering) -"dnD" = (/obj/machinery/light/small{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/engine/engineering) -"dnE" = (/obj/machinery/light,/turf/simulated/floor/plasteel{dir = 0; icon_state = "blue"},/area/engine/engineering) "dnF" = (/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dnG" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) -"dnH" = (/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 6},/area/engine/engineering) "dnI" = (/obj/machinery/door/poddoor{id_tag = "turbinevent"; name = "Turbine Vent"},/turf/simulated/floor/engine/insulated,/area/maintenance/turbine) "dnJ" = (/obj/machinery/door/airlock/external{frequency = 1450; icon_state = "door_locked"; id_tag = "sci_inner"; locked = 1; name = "External Access"; req_access = null; req_access_txt = "13"},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/asmaint2) -"dnK" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating,/area/engine/engineering) "dnP" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = -32},/obj/machinery/light/small{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/asmaint2) -"dnS" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/turf/simulated/floor/plating,/area/engine/engineering) "dnT" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4; level = 2},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dnV" = (/obj/effect/spawner/window/reinforced,/obj/structure/sign/securearea{pixel_x = 0; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4; level = 2},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dnW" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4; level = 2},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) -"dnX" = (/obj/machinery/door/airlock/external{name = "Escape Pod"},/turf/simulated/floor/plating,/area/engine/engineering) "dnZ" = (/turf/simulated/wall,/area/turret_protected/aisat_interior) "doa" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4; level = 2},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "dob" = (/obj/machinery/light/small,/obj/item/radio/intercom{dir = 1; name = "station intercom (General)"; pixel_y = -28},/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4; level = 2},/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) @@ -8717,7 +8727,6 @@ "doG" = (/obj/structure/cable,/obj/machinery/power/solar{id = "starboardsolar"; name = "Starboard Solar Array"},/turf/simulated/floor/plasteel/airless{icon_state = "solarpanel"},/area/solar/starboard) "doH" = (/obj/machinery/teleport/hub,/turf/simulated/floor/plating,/area/turret_protected/aisat_interior) "doI" = (/obj/structure/chair{dir = 4},/obj/item/radio/intercom{broadcasting = 0; listening = 1; name = "station intercom (General)"; pixel_y = 25},/turf/simulated/shuttle/floor,/area/shuttle/pod_4) -"doJ" = (/obj/structure/closet/emcloset,/turf/simulated/floor/plating,/area/engine/engineering) "doK" = (/obj/machinery/light,/turf/simulated/floor/plating,/area/toxins/launch{name = "Toxins Launch Room"}) "doL" = (/obj/docking_port/mobile/pod{dir = 4; id = "pod4"; name = "escape pod 4"},/obj/machinery/door/airlock/shuttle{id_tag = "s_docking_airlock"; name = "Escape Pod Hatch"},/turf/simulated/shuttle/floor,/area/shuttle/pod_4) "doM" = (/obj/structure/chair{dir = 4},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/light,/turf/simulated/shuttle/floor,/area/shuttle/pod_4) @@ -8947,7 +8956,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQacIabVacJabQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabNabOabMabPabNaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTabIabIabIabIabQacIabVacJacUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabNabNacaabYaccabNabNaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadeabVabVadfabQacIabVacJabQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabNacgachaciachacjabNaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadeabVadyadzabQacIabVacJabQabIadBadAadCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacoacpachaciachacpacoaaaaaaaaaaabaabaabaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadeabVadyadzabQacIabVacJabQabIadBadAadCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacoacpachaciachdgHacoaaaaaaaaaaabaabaabaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadSabVabVadTabQadUabVacfadWadVadVadVabQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacuactacvacwacvacxacyaaaaaaaaaabNabNabNabNabNaabaabaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadeabVabVabVaesabVabVaetaeuaevaevaewabQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaexaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaababNacBacCacDachacEabNaaaaaaaababNacFacHacGabNabNabNaaaaaaaabaabaabafOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQadeabVabVabVaePabVabVabVaeQaeRaeRaeSabQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaabNacKacLacDacMacNabNaaaaabaababNacbacPacOacRacSabNaaaaabaabafOaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9028,19 +9037,19 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaMsaMsaMsaMsaMsaMsbzrbzsbqrbqrbqrbqrbqrbqrbztbqrbqrbqrbnKbnKbzwbvsbzubzvbynbzxbvsbzzbzybzAblMbrNbstbwNbnDblMbnKbxabxbbzCbzDbBjbywbBjbxbbyybyzbzEbzFbzIbzHbzKbzJbzMbzLbyFbzRbzNbBsbzPbzQbzQbzPbzUbzSbvXbzTbxqbxqbyPbzWbyPbxqbxqbzVbwbbzXbAbbzYbzZbAabAdbzYbAcbxvbAlbAebAfbAgbAhbAicMKbAkbAkbAkbAkbAkbAkbAmbAobAnbAkbAkbAqbAkbAkbAkbAkbAkbAkbAkbAkbApbAsbArbArbArbArbArbArbAtbAicVsbvhbvhbBtbBrbBNbBrbBPbBrbBUbBQbDkbBrbDubDtbElbDxcVUcVUbEmcVUbEBcVUbENbEHbFzbFwbGjbGhbjRbwDbwCbxzbjRbGobmmbmmbGIbGsbjRbGMbGNbjRblDblAbeCblCbnbblAbeCblCbnbblAbeCblCblDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAQbARbARbARbARbASbASbARbARbATaaaaabaSdaUlaMEbAVbAUbAXbAWbAWbAWbAWbAYbAZbBablQbnwbBbbzwbvsbvsbvsbBdbyobvsblMblMblMblMbrNbuabyAbBfblMbBhbBibxbbBkbBlbywbBjbCubxbbyybzGbzEbzFbBnbBobBpbzJbBqbzLbyFbzRbDobCAbDsbBubBvbBwbzUbBxbvXbBybyPbxqbBAbBzbBAbxqbyPbBBbxubBCbzYbzYbzZbBDbAdbzYbBEbxvbBFbAfbAfbAgbAhbAibAkbAkbAkbAkbAkbAkbAkbBGbAkbAkbAkbAkbAkbAkbBHbBIbBIbBIbBIaQwbBIbBIbBIbBIbBIbBIaQwbBIbBIbBIaQybDVdcebIsbIzbwtbwtbwtbwtbwtbwubwtbwtbwtbwtbwtbwtbwtbwtbwtbwtbwtbMhbKubRFbNWbomcbudckcVtbjRcVVbzdbzmbjRcWhbmmbmmcWAcWvbjRcWEcWQbjRbnbblAbeCblCbnbblAbeCblCbnbblAbeCblCbnbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbCcbBZbCebCbbCbbClbCibARbATaSdaSdaSdaTobCnbCfbCgbCfbCfbCfbCfbChbCtbCjblQblQblQbCwbvsbwPbCmbCxbzxbvsbCobCpbCoblMblMblMblMbCqblMbCrbCsbxbbCvbCybBjbCzbDRbxbbyybzJbCBbzFbBnbBnbCEbzJbCFbzLbyFbzRbDybCAbDsbCGbCCbBwbzUbCDbvXbCHbCIbxqbCKbCJbCLbxqbCRbCNbCSbCMbCTbCObCPbCQbCUbzYbCVbxvbCYbCXbAfbAgbAhbAibAkbCZbAkbDAbDbbDbbDbbDbbDbbDbbDbaRybAkbAkbAkbAkbAkbDabAkaRAaRCaRBaRCaRCaRCaREaRHaRFaSFaROaSHbFsaSKaSIaTHaSVbwvbwvbwvcXfbDpbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbDrbDqcXhcXgcXjcXibmmbGhbjRbwDbwCbxzbjRbGobmmbmmcXlcXkbjRbGNbGMbjRbqoblAbeCblCbqoblAbeCblCbqoblAbeCblCbqoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbDGbCbbCbbCbbCbbCbbCbbCbbDHbDCaOQbDCaSfbDIbCfbDEbDJbDLbDKbDMbChbDObDNbDQbDQbBcbKHbvsbvsbvsbynbDYbymblQblQblQblQbDPbCkbCkbDSbCkbDWbDSbFmbEUbDTbDZbFjbywbxbbDUbzJbEbbzFbBnbBnbEfbDXbEjbzLcXqbxlbHpbHobzPbzPbzPbzPbzUbEcbvXbEdbEebvXbvXbvXbvXbvXbvXbvXbxubxvbErbEgbEhbEibEsbEkbEvbxvbEwbEnbEnbEpbEpbEpbEpbEpbEpbEqbEybEpaTLaTKaTMbEpbNebEobEobEobEobEobEubEubEuaTNbEubEubEubEubEubEuaTObEubEubEubteaTPaTQbwvbuxbuxbEAbEAbEAbEAbEAbEJbDqbDqbDrbDqbwvbDqbDqbDqbDqbEMbEDbEDbEDbEDcXncXibmmbAJbEFbjRbjRbjRbAKbALbmmbmmbAMbjRbjRbjRbqnbjRbicbzqbeCbeCbeCbeCbeCbeCbeCbeCbeCbeCbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbDGbCbbCbbCbbCbbCbbCbbCbbDHbDCaOQbDCaSfbDIbCfbDEbDJbDLbDKbDMbChbDObDNbDQbDQbBcbKHbvsbvsbvsbynbDYbymblQblQblQblQbDPbCkbCkbDSbCkbDWbDSbFmbEibDTbDZbFjbywbxbbDUbzJbEbbzFbBnbBnbEfbDXbEjbzLcXqbxlbHpbHobzPbzPbzPbzPbzUbEcbvXbEdbEebvXbvXbvXbvXbvXbvXbvXbxubxvbErbEgbEhbEUbEsbEkbEvbxvbEwbEnbEnbEpbEpbEpbEpbEpbEpbEqbEybEpaTLaTKaTMbEpbNebEobEobEobEobEobEubEubEuaTNbEubEubEubEubEubEuaTObEubEubEubteaTPaTQbwvbuxbuxbEAbEAbEAbEAbEAbEJbDqbDqbDrbDqbwvbDqbDqbDqbDqbEMbEDbEDbEDbEDcXncXibmmbAJbEFbjRbjRbjRbAKbALbmmbmmbAMbjRbjRbjRbqnbjRbicbzqbeCbeCbeCbeCbeCbeCbeCbeCbeCbeCbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbEKbELbELbCbbELbELbELbARbERaSdaSdaSdaTobEVbCfbEYbEXbEXbEXbFcbChbnKbFfbESbETbETbFgbvsbwPbEWbynbFhbymbFibEZbFabFbbFkbFdbFdbFebFdbFnbFobxbbFlbFpbFqbFrbKQbFmbNsbyBbFubFtbBnboxbFybvQbEjbzLcYPbxlbwebFvbJabFFbFIbFGbFMbxmbxmbFBbFCbFDbFEbFNbFEbFPbFCaaabFHbxvbFRbFJbFKbFLbEsbzYbFSbxvbFUbFObFWbEpaTTaTSaTVaTUaTYaTWaUPaUObLzbGabBLaVxaVIaVyaWOaWIaWSaWRbEuaYkaYoaYlaYraYqaZUaZTbobbbybuOaZTaZTbzibGrbGrbBJbGrbwLbwLbEAbGubGAbGwbEAbGBbGEbGBbEAbGFbDqbEMbEDbGKbGLbGKbEDbGCbGDbEDcXocXibmmbmmcXscXpcYdcXpcYebmmbmmbmmbwWbAEboIbANbrMboIbAObeCbeCbeCbeCbAPbeCbAPbeCbeCbeCbeCaYUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGPbARbARbARbARbARbARbARbARbERaaaaaaaSdbBgbmSbHabCfbHdbCfbHebIHbHfbGQbChbHgbGSbGTbGVbGUbGWbGWbGWbGWbGWbGWbGYbGXbIwbHbbGZbxbbxbbxbbxbbxbbxbbxbbMlbFmbFmbFmbPDbPabHcbAFbHjbBnbBnbBnbHnbDXcZfbzLcZjbxlbBebFvbxlbxlbxlbxmbHrbxmbHkbHlbHmbHubHBbHzbHDbHCbHsbHtbHFbxvbHvbzYbHwbHxbEsbHybzYbxvbHHbHAbHIbEpbCWbBMbDfbDfbDfbDfbDfbDfbDfbDebDhbDgbDjbDibSnbDlbDnbDmbEubEtbEzbExbECaZTbEEaZTbFQbEIbuObFTbFXbFVbGrbIfbFYbIgbFZbBmbIabGcbIdbIdbImbIcbIlbInbEAbIibIrbIkbEDbItcDDbIvbIobIpbIybEDcYhcXibmmbmmbmmbmmcYmcYkcYkcYkcYkcYkcYnbqnbjRbjRbjRbjRbqpbjCbBWbBVbjCbBXaYUbBXaYUbBYbBRbBSbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaSdaSdaSdaSdaSdaSdaToaSfbIGbCfbJjbIBbIIbIDbIDbIJbILbIKbIMbIMbIObINbDQbDQbDQbDQbDQbDQbIQbIPbIPbIRbITbxbbIVbIUbIYbIXbISbIZbJfbJbbxbbIWbJicRubyCbDXbHjbBnbBnbKCbzJbzJbJmdaQdbnbJcbJdbJebJpbJgbJhbJsbJtbJkbJlbJubHsbJnbJvbJnbJvbJwbHsbHtbJqbJrbJybJxbJDbJzbJGbJEbJHbJrbJIbFObFObEpbDcbBMbGdbDdbGfbGebGebLybDebDebDebGtbGxbGvbSnbDlbGzbGybEubHEbHJbHGbHLbHKbHMaZTbFQbEIbuObFTbFXaZTbGrbHNbHQbHPbHSbHRbHUbHTbHVbJYbJYbKhbJYbIbbKbbGbbKdbGkbKfbKqbKrbKibKibKibKjbEDcYpcYocYqcYqcYqcYrcYvcYscYwcYwcYwcYxbBKbAEboIbrMbrMboIbDBdsldsldsldsnbicaaabicbDDbDwbDwbDFbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbGmbGlbKpaMdaMdaMdbmSaSfaSfbCfbKPbCfbKDbKsbKtbKEbCfblQbKvbKvbKwbKFbKwbKwbKwbKFbKwblQblQbxbbxbbxbbKGbxbbKzbKzbKzbKzbKzbKzbJfbKAbKBdetbzFbKIbKKbKJbKMbKLbKObFxccYccZbKSbKRdbYbKUbKXbKXbLabKZbKTbLbbLfbKWbLgbKYbFCbLhbHDbLibHBbLkbFCaaabLcbLdbLebLnbLdbLdbLdbLdbLpbxvbLqbLrbIechhbGibGgbGibEpbIhbGqbJAbIjbJBbJKbJTbJPbJXbJWbKabJZbKcbOUbEubEubEubEubEubKebKgaZTbFQbEIbLjbFTbFXaZTbGrbLNbLEbLPbLmbLlbLIbLTbLobLLbLMbLUbLObKkbEAbGRbLRbKnbEDbKobKybKxbIpbLWbNCbEDcYhbmmcYObjRcZkcYYcZlboDcZmbjRcZnbuHcZobqnbjRbjRbjRbjRaYUdsqdsldslbEObicaaabicbEPbDwbDwbEQbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGPbARbARbARbARbARbARbARbARbERaaaaaaaSdbBgbmSbHabCfbHdbCfbHebIHbHfbGQbChbHgbGSbGTbGVbGUbGWbGWbGWbGWbGWbGWbGYbGXbHvbHbbGZbxbbxbbxbbxbbxbbxbbxbbIwbFmbFmbFmbOIbMlbHcbAFbHjbBnbBnbBnbHnbDXcZfbzLcZjbxlbBebFvbxlbxlbxlbxmbHrbxmbHkbHlbHmbHubHBbHzbHDbHCbHsbHtbHFbxvbPabzYbHwbHxbEsbHybzYbxvbHHbHAbHIbEpbCWbBMbDfbDfbDfbDfbDfbDfbDfbDebDhbDgbDjbDibSnbDlbDnbDmbEubEtbEzbExbECaZTbEEaZTbFQbEIbuObFTbFXbFVbGrbIfbFYbIgbFZbBmbIabGcbIdbIdbImbIcbIlbInbEAbIibIrbIkbEDbItbPDbIvbIobIpbIybEDcYhcXibmmbmmbmmbmmcYmcYkcYkcYkcYkcYkcYnbqnbjRbjRbjRbjRbqpbjCbBWbBVbjCbBXaYUbBXaYUbBYbBRbBSbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaSdaSdaSdaSdaSdaSdaToaSfbIGbCfbJjbIBbIIbIDbIDbIJbILbIKbIMbIMbIObINbDQbDQbDQbDQbDQbDQbIQbIPbIPbIRbITbxbbIVbIUbIYbIXbISbIZbJfbJbbxbbIWbJibUEbyCbDXbHjbBnbBnbKCbzJbzJbJmdaQdbnbJcbJdbJebJpbJgbJhbJsbJtbJkbJlbJubHsbJnbJvbJnbJvbJwbHsbHtbJqbJrbJybJxbJDbJzbJGbJEbJHbJrbJIbFObFObEpbDcbBMbGdbDdbGfbGebGebLybDebDebDebGtbGxbGvbSnbDlbGzbGybEubHEbHJbHGbHLbHKbHMaZTbFQbEIbuObFTbFXaZTbGrbHNbHQbHPbHSbHRbHUbHTbHVbJYbJYbKhbJYbIbbKbbGbbKdbGkbKfbKqbKrbKibKibKibKjbEDcYpcYocYqcYqcYqcYrcYvcYscYwcYwcYwcYxbBKbAEboIbrMbrMboIbDBdsldsldsldsnbicaaabicbDDbDwbDwbDFbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbGmbGlbKpaMdaMdaMdbmSaSfaSfbCfbKPbCfbKDbKsbKtbKEbCfblQbKvbKvbKwbKFbKwbKwbKwbKFbKwblQblQbxbbxbbxbbKGbxbbKzbKzbKzbKzbKzbKzbJfbKAbKBcrCbzFbKIbKKbKJbKMbKLbKObFxccYccZbKSbKRdbYbKUbKXbKXbLabKZbKTbLbbLfbKWbLgbKYbFCbLhbHDbLibHBbLkbFCaaabLcbLdbLebLnbLdbLdbLdbLdbLpbxvbLqbLrbIechhbGibGgbGibEpbIhbGqbJAbIjbJBbJKbJTbJPbJXbJWbKabJZbKcbOUbEubEubEubEubEubKebKgaZTbFQbEIbLjbFTbFXaZTbGrbLNbLEbLPbLmbLlbLIbLTbLobLLbLMbLUbLObKkbEAbGRbLRbKnbEDbKobKybKxbIpbLWbNCbEDcYhbmmcYObjRcZkcYYcZlboDcZmbjRcZnbuHcZobqnbjRbjRbjRbjRaYUdsqdsldslbEObicaaabicbEPbDwbDwbEQbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbLYbLXbKpbLZbLZbMabMbbLZbMcbCfbMebIBbNSbMkbMnbMmbCfaaaaabaabbMpbMobMobMobMobMobMraaaaaabKBbMdbMsbMubMqbKzbKzbKzbKzbKzbKzbMwbMvbMzbMybMDbMBbMxbDXbzJbzJbMFbMAbzJbzJbMJbMCbMLbMEbMMbMGbMGbMHbMGbMIbMNbMGbMKbKYbFCbMObFEbFEbFEbMPbFCaaabLcbLdbMRbMQbMVbMTbMWbMSbNbbMUbNcbFObLschhbJFbJCbJJbIqbJLbDebLvbLubHObLAbLBbEobEobLDbLFbDlbLQbLKbLVbLSbMYbMXbLKbMZbNdbNabFTbEIbNfbFTbEIaZTbGrbNgbHXbHXbLmbNhbNEbNibNjbNHbNIbNJbNObNNbEAbMfbLRbMibEDbMjbNPbMtbIpbIpbNUbEDcZpbmmcZDbAKcZkbDvcZGcZEcZmbAKcZIcZHcZJbEGaaaaaaaaaaaabicdsudswdsvdsvbicaaabicbGObDwbGObDwbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKpbKpbObaSdaSdbjQaLdaSdaSdbCfbOdbIBbIBbIBbCfbCfbCfaaaaaaaaabOebOcbOcbOfbOcbOcbOeaaaaaabKBbNQbKzbOibOhbOhcdabOhbOhbOkbOjbOhbOlbOnbOmbOpbOobOrbOqbzJbOtbBnbFAbOsbDXbOwbOubOxbMEbMEbMGbOAbOybOCbOBbODbMGbFBbKYbFCbOEbOHbOFbOObOMbFCaaabOGbLdbOPbOIbOJbOKbOLbOKbOSbONbNkbFObNlchhbNnbLwbNpdeqbNmbLxbNqbNobHObLAbNrbEobNDbNAbNGbNFbNLbNKbORbNMbOVbOTbLKbOWaZTbOXbFQbEIbOYbFTbFXbFVbGrbOZbLEbLPbUlbNBbNEbPnbPbbPobPpbIdbPqbPybPsbPtbIrbPubEDbPzbPwbIpbPHbPBbPJbEDcZpbmmcYObjRcZkbmmcZGbmmcZmbjRcZnbmmcZKbEGaaaaaaaaaaaabIAbjJbIubIubIubICaaabIEbIxbIxbIxbjJbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKpbKpbObaSdaSdbjQaLdaSdaSdbCfbOdbIBbIBbIBbCfbCfbCfaaaaaaaaabOebOcbOcbOfbOcbOcbOeaaaaaabKBbNQbKzbOibOhbOhcdabOhbOhbOkbOjbOhbOlbOnbOmbOpbOobOrbOqbzJbOtbBnbFAbOsbDXbOwbOubOxbMEbMEbMGbOAbOybOCbOBbODbMGbFBbKYbFCbOEbOHbOFbOObOMbFCaaabOGbLdbOPcrGbOJbOKbOLbOKbOSbONbNkbFObNlchhbNnbLwbNpdeqbNmbLxbNqbNobHObLAbNrbEobNDbNAbNGbNFbNLbNKbORbNMbOVbOTbLKbOWaZTbOXbFQbEIbOYbFTbFXbFVbGrbOZbLEbLPbUlbNBbNEbPnbPbbPobPpbIdbPqbPybPsbPtbIrbPubEDbPzbPwbIpbPHbPBbPJbEDcZpbmmcYObjRcZkbmmcZGbmmcZmbjRcZnbmmcZKbEGaaaaaaaaaaaabIAbjJbIubIubIubICaaabIEbIxbIxbIxbjJbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbPIbPIbPIbPNbPMbPIbPIbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbOebPTbKBbKBbNRbPObPPbHhbHhbHhbPObKzceEbKAbKzbKzbKBbPZbPSbQcbQdbPVbQebHibBnbBnbPYbDXbOwbOubQhbHqbJObQibQkbOzbQlbQgbQnbMGbQobQjbHmbQpbQqbQmbQsbQrbHsbHtbQtbLdbQvbQubQwbOKbQxbOKbQybONbQzbFObKNbPcbPebLtbPfbEpbPgbNybDebPhbHObLAbPmbEobPGbPFbQabPKbQAbNKbQCbQBbQEbQDbLKbFXaZTbQFbQHbQGbQIbNdbQJbNdbQLbQKbQKbQKbQNbQMbIabRkbPbbPobRlbRhbPqbRmbEAbOvbOvbPdbEDbRpbRybRqbRzbIpbREbEDcZTcYmcYkcZVdaacYkdaldakbmmdambmmdandaqbEGaaaaaaaaaaaaaaabIAbKmbKmbKmbIFaaabIAbKmbKmbKmbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbRubRvbRwbRxbRGbRHbRAbRGbRBbRCbRDbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbRJbRIbRKbRIbRSbRRbRTbRRbRRbRRbRRbPQbJfbKAbRLbxbbxbbRMbBnbzFbQdbRNbDXbPXbRPbRPbRQbNYbRYbRXbRZbRVbQbbSbbSdbScbSabQgbSebMGbMKbKYbFCbSfbShbSgbSlbSkbFCaaabOGbSibSjbSibSibSibSibSibSmbSibSpbFObQOchhbQQbQPbQQbEpbQSbQRbSsbSqbHObLAbNzbQTbQWbQUbQZbQYbRabLKbQCbRbbOVbRcbLKbWdbWdbWdbRebRdbEubEubEubEubGrbJobHXbHXbRfbSTbIabSWbRibRgbRrbRjbPqbSYbTabSZbTfbTcbTbbTgbTdbTebTjbTebEDbEDbEGdasbEFbEFbigdatdazdatbigaYSaYSaYSaYSaYSaYSdaCdaDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbRAbRAbRAbTlbRGbTnbTnbRGbTobRAbRAbTpbWLbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbTtbTrbTqbTrbNTbKzbPPbHhbHhbHhbKzbKzbJfbKAbQfbRobxbbTAbBnbTBbQdbTvbDXbRObBnbBobBnbPWbOwbTybTzbRVbQbbTCbTEbTDbTKbTFbTLbTGbTHbTIbTJbTJbTNbTMbTPbFCbFCaaabOGbSibTQbTObTSbTRbTVbTTbTWbTUbTXbFObRsbQVbSobRtbSrbEpbIqbStbIqbEpbPvbPrbPxbOUbOUbSwbSybSxbOQbLKbNKbSzbSAbLKbLKbWdbSCbSBbSEbSDbWgbSFbSHbSGbGraZSbpDbSIbRUbRUbIabSJbUEbUFbIabSKbPqbUHbIabUKbUMbULbUObUNbZNbpvbsBbqbbRnbtscjTcjYcOCbKlbigbaNdaEbaObaGbaTbaQbaRbaHbaTbaUbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbRAbRAbRAbTlbRGbTnbTnbRGbTobRAbRAbTpbWLbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbTtbTrbTqbTrbNTbKzbPPbHhbHhbHhbKzbKzbJfbKAbQfbRobxbbTAbBnbTBbQdbTvbDXbRObBnbBobBnbPWbOwbTybTzbRVbQbbTCbTEbTDbTKbTFbTLbTGbTHbTIbTJbTJbTNbTMbTPbFCbFCaaabOGbSibTQbTObTSbTRbTVbTTbTWbTUbTXbFObRsbQVbSobRtbSrbEpbIqbStbIqbEpbPvbPrbPxbOUbOUbSwbSybSxbOQbLKbNKbSzbSAbLKbLKbWdbSCbSBbSEbSDbWgbSFbSHbSGbGraZSbpDbSIbRUbRUbIabSJcrHbUFbIabSKbPqbUHbIabUKbUMbULbUObUNbZNbpvbsBbqbbRnbtscjTcjYcOCbKlbigbaNdaEbaObaGbaTbaQbaRbaHbaTbaUbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbVebVfbVgbVhbVibRGbVkbRAbVlbRAbRAbRAbRAbRAbTlbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebVmbOcbOcbOcbVnbOebPTbKBbKBbOgbKzbPPbKzbKzbywbKzbKzbJfbCybQfbRWbxbbVrbBnbVqbVsbBnbVwbzEbBnbBnbVtbDXbOwbTybTzbRVbQbbMGbVubVvbVybVxbVzbMHbVBbVAbVDbVCbHsbVEbVFbHsbHtbHtbVGbSibVIbVHbVKbVJbVLbVLbVNbVMbVObFObSMbSubSObSNbSPbSvcrAbSLcrAcrAbSRbSQbSUbSSbwFbXAbSXbRtbXAbThbXAbJRcuobJSbTZbTYbUabUabUcbUbbWgbUdbUfbUdbWibWibWjbWjbWjbWjbIabIabIabIabIabWlbWnbLIbIabNVbNZbNXbWqbWqbPibOabLRctvbPkbPjcacdlDbGGdaSbigdaZdbedbddbkbaTbaTbaTbaTbaTbaUbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWObWGbRAbRAcuHcuHcuHbRGbRAbRAbRGbWIbWJbWKbRAbWMbWNbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbWPbTrbTqbTrbNRbTubWRbKzbKzbKzbTubKzbJfbKAbQfbTsbxbbWWbBnbzFbQdbBnbzJbLJbBnbBnbWUbDXbOwbTybWVbRVbTxbMGbXbbWYbWZbXabXdbMHbXcbXebXgbXfbXibXhbXjbFCaaaaaaaaabSibXpbXkbXlbXlbXmbXnbXobSibXrbXqbUhbPUbUjbUibUrbUkbUnbUebUmbUmbUpbUobUmbUmbUqbUmbUmbUsbUnbUmbUmbUGbNubNtbUwbUvbUBbUybZfbUDbXNbUIbUIbUIbUJbWgbLRbUPbWqbWqbXYbXXbWqbXZbYbbYabYdbYcbWqbPlbYgbYfbYibYhbYlbYjbYjbYjbYjbYjcacdlDdbmcAUbigdbodbpbclbcIbaTbaTbaTbaTbaTbaUbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYubWGbRAbRAbRAbRAbRAbYtbRAbRAbRGbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbWQbUgbYwbUgbYybYxdcYdcYdcYdcYdcYbUCbYEbYDbQfbVpbxbbYGbYIbYHbYNbYJbYKbYLbYLbYLbYMbYMbYObTybYRbWSbQbbMGbYTbYSbYVbVvbYWbMHbYUbYXbZdbTJbZebQmbYYbFCaaaaaaaaabSibYZbZabZbbZcbXmbXnbXobSibZgbZJbURbUQbUTbUScyTcyTbUVbUUbUXbUWbUWbUYbUZbUZbVabUZbUZbUSbUVbUZbVcbVbbVdcyTbVPbVjbVRbVQbVTbVSbVVbVUbVXbVWbVZbVYbWcbWbbWcbWcbWebUNbZMbUNbZNbUNbZPbZObZObPCdevbZRbZUbZTbZXbZVbVobZWbYzbYjdbwdbvdbxbGGdbhbcHdbHbgbbgkbaTbgcbgmbaTbaTbgdbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYubWGbRAbRAbRAbRAbRAbYtbRAbRAbRGbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbWQbUgbYwbUgbYybYxdcYdcYdcYdcYdcYbUCbYEbYDbQfbVpbxbbYGbYIbYHbYNbYJbYKbYLbYLbYLbYMbYMbYObTybYRbWSbQbbMGbYTbYSbYVbVvbYWbMHbYUbYXbZdbTJbZebQmbYYbFCaaaaaaaaabSibYZbZabZbbZcbXmbXnbXobSibZgbZJbURbUQbUTbUScyTcyTbUVbUUbUXbUWbUWbUYbUZbUZbVabUZbUZbUSbUVbUZbVcbVbbVdcyTbVPbVjbVRbVQbVTbVSbVVbVUbVXbVWbVZbVYbWcbWbbWcbWcbWebUNbZMbUNbZNbUNbZPbZObZObPCctlbZRbZUbZTbZXbZVbVobZWbYzbYjdbwdbvdbxbGGdbhbcHdbHbgbbgkbaTbgcbgmbaTbaTbgdbaVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIcafcagcahcaibRAbRGbRAbRAbRGbRAcancakcaraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbOebPTbKBbKBbxbbxbbKBbKBbKBbKBbKBbxbbxbbKBbKBbKBbxbcamcamcamcascambYMcaocapcaqcatbYMbOwbTycawbMEbMEbMGbMGbMGbMGbMGbMNbMHbTJbTIcaubTJcavcaxbFCbFCbFCbFCbFCbSibSjbSibSibSibSibSibSibSibNvbFObWfbSubWkbWhbWobWmbWscaAbWubWtbWxbWwbXGbWubWabWybWabWybWabWybWabWzbWAcrAbTZbWBbWDbWCbWFbWEbXNbXsbXubXtbXvcbdcbdcbecbdcbfcbicbfcbfcbfcbhcblcbjcbjcbkcbmcbocbnbZUcbpcbrcbqbYAcbsbYBbYjdbObGGbGHbGHaYSaYSaYSaYSaYSaYSaYSaYSaYSaYSaYSdaCdaDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPIbPIbPIbPIbPIbPIbRGbTobRAcbzbRAcbxcbycbAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbDcbBbOccbCbOccbEcbFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbGaabaaaaaaaaaaaacamcbIcbHcbKcbJbYMcbNcbLcbMcbRbYMbOwbTycbOcbPcbQbXwcbVcbTcbUcbWcbYcbXbXxcbZcccccbccfccdcceccgccjcchccibXybXzcclccmbEnccnbFOccoccpccrbFObXBbQVbXCcaAcaAbXDbXDcaAbXFbXEbZhbXHbZibXIbWabXKbXMbXLbXMbXObWabXPbWAbXRbWdbXSbXUbXTbXSbXSbWibXVbXWbXQbYkcbdccTccSccVccUccXccWcdbcbfceFchSchTcbjcbjcdccbocddcdfbPEcdhcdgcdicbscdkbYjcdndfcbZZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIcdlcdmcdpcdlcdobRGbRAbRAbRGbRAcdrcdqcdsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacdvcdtcducducducdtcdwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacamcdycdxcdAcdzbYLcdBcdDcdCcdEbYMbOwbNwcdFbTybTybYmbYncdIcdJcclcdObYobYpcdMcdNcdNcdQcdPcdRcdNcdNcdTcdNcdNcdScclccmbEncdVcdUcdXbYqcdZcdYbFOchfbYrcaAbZjbYsbYsbXJbZhbZkbZnbZlcaBbZmbZpbZobZrbZqbZtbZsbZvbZubWAcuvchrbZwbZybZxbZAbZzbZBccQbXWbXQbZBcbdcezceyceBceAceDceCceGcbfcjMchScjNcjNcbjceHceJceIceLceKceNceMbGnceOceSbYjcaccLhbGpdbPdbPdbPdbZdbXdbXdcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9052,16 +9061,16 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIbPIbPIbPIbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabafOcgQcngcngcgQcngcngcgQaaaaaacgFcnhcnicnjcgFbYPbYPbYPcamcnmcnlcnocnocnocamcamcgQcnncnpcnrcnqcgQcnscntcgSclRcktcktcktcnvcgWckvckwckwcnuchHcgWcpicHDcnAchcchcchcchcchcchIchcchccnCdgCcsLcsLcsLchfcABchJcsLcbvchfchLchKciEchNcfEciFcfGcfFcfIcfHciOciJciQciPcDfciRciScDfciUbSVchrciVciXciWchrchrcepciYcjaciZclpcjbcodcoicoicoicodcogcodcodconcoocmVcmVcbjcokclscbncpZcqacqecqgcorcopcoqcoqcotcoscovcoucoxcowcozcoycoCcoAcoBcoDcoEcoFcoHcoGcoIaabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacidciecbwcbScbSckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaacgQcoKcoLcgQcoKcoLcgQaaaaaacoOceZcoNceZcoQaaaaabaaacamcamcamcamcamcamcamcoPcgQcoScoRcoUcoTclPcoVcoWcgScoYcoXcpfcktcjccgWcjdckwcjfcjecjgcgWcjicjhcjkcjjcpqcpqcpqcpqcjlcpmcppcpocjncjmcjmcjocjqcjpcjscjrcjtchfcjwcjucjycjxcjAcjzcjCcjBcjCcjDckrcjEckxcksckzckyckAcDfckBcuvckCcjvckDcmDckFckEciYckJckLcgacpRcpTcpRcpUcpWcpVcpRcpXcpYcodcqicwLchTcbjcbjcqccqbcqfcqdcwMcxacIpcqhcqlcqjcqkcqncqmcqpcqocqtcqqcqrcqqcqscqrcqrcqucqwcqvcqycqxcqCaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacieciecdHckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOaaaafOcgQcqzcoLcgQcqzcoLcgQaaaaaaaabaabaabaabaabaabaabaabaabcgQcoLcqAcqBcgQcqEcqGcgQcqHcgQcgQcqFcgQcgQciCcgScqRcqIcqJcqKcqLcgWckMcqOcqScqQcqTcgWckOckNckPcJZcsDcsDcsDcsDcsDcrdcqZcrackQchfcucckRcsLckSckTcsLcsKchfckVckUckXckWcCWckYclackZclbcDfcldclcclfclecDfcDfcDfcDfclhclgckCchCcljclicllclkciYcmdcgacmfcpRcrNcrQcrLcrMcrLcrTcrOcrPcodcbjcrUcbjcbjcrRcrSclsbLRbPtcgscrVcgscgscrWcrYcrXcsacrZcsdcsbcsfcsecsgcsecsgcshcsgcsicgEcsncrwcsqcsraabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacieckbckbckbckbckbckbcdKckbcmzckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcqPcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsNcsOcsGcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIdewctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecmCcmCcmCcmCcmCcmCcmEckbcoJcmCcmzckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcqPcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsNcsOcsGcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIctoctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecmCcmCcmCcmCcmCcmCcmEckbcoJcmCcmzckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOafOcngcoLcoLcoLcoLctMctNcoLcoLcoSctUctUctVctUctUctUctUctUctUctUctUctUctUctUctUcoRcgQcskcqzctWcgQcqPctRctRctRctRctRctRcgWcgWcgWcgWcgWcgWcgWcuactXcmBcoMcpgcqDcmFcmFcmGcuicsJcmHcsLcubcuccmIcsLckScmJchicsLcsLcsKcCWcmLcmKcmNcCWcHWcnxcnBcnzcnEcnDcnGcnFcnIcnHcnKcnJcnMcnLckCcnNcnPcnOcnRcnQciYbQXcgacgacpRcuGcnTcnScnUcrLcuKcuJcuOcuLcuScuRcuVbLRcuXcrSclscuMbIibPAcuNcuYcuPcuQbGGbGGcgscvccvecuTcuUcvfcuWcvgcvicuZcvacvbcgEcvjdoKdoFcvraaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaacvscjZcjZcjZcjZcjZcjZcjZcvhcvtckbckbckbckbcvvckccieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabaabafOcngcvkcvlcvmcoLcoLcvncoLcoLcsucgQcgQcgQcgQcgQcgQcqFcgQcgQcgQcgQcvocvocvocvocvocvocvocvocvocgQcqPcvpaaaaaaaaaaaacvqcvwcvzcvycvucvAcvDcvxcvJcvGcvKcvBcvCcvLcvEcvEcvFcvMcvHcvIcvIcvIcvIcvNcvIckScmJchfcnVcKOdercCWcnXcnWcnZcnYcobcoacoccoccofcoecpacoZcpccpbcpecpdcphciTciYciYciYciYciYciYciYciYcpkcpjcpRcwjcplcwqcptcpncpvcpucpRcpRbIicwpbIibIibIicwvcwJcwwbIibGGcuNcwKcwucuQcuQcuQcgscgscgscgscgscgscgscgscgscgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecbScbScbScbScbScbScssckbcbwcbScstckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgQcwxcwxcwxcwxcwxcwxcwycwxcsucwzcgQcoLcwAcwBcwCcoLcwCcwDcwEcwBcvocwFcwFcvocwGcvocwHcwIcvocoLciCcngaaacwPcwUcwQcwVcwNcwOcwWcwXcwRcwScwTcwZcwYcxbctJcxdcxccxfcxecxjcxgcvHcxkcxmcxmcxmcxocvIckScmJchfdgmcQkcQkcQkcQkcpwcpxcQkcpycpycpycpycQkcpzcpBcpAcQkcQncQncpCcpDcuocukbQXbQXcpEbQXbQXbQXbQXbQXcpFcpRcpRcpRcpRcpGcpRcpRcpRcxIcpHcpIcxKcxUcxMcxNcxOcxWcxQcxNbGGcuNcylbGGbGGcxScxZcyactFbGGbGGbGGbGGbGGbGGbGGcxVcymbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieckbckbckbckbckbckbcdKckbcstckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxXcxYcxYcxYcxYcxYcxYcyocyncybcyccydcyecyfcwycsucygcgQcoLcoLcwBcoLcoLcoLcwDcqBcwBcvocwFcyicwIcwIcyjcwIcykcvocypciCcngaaacyrcytcyscyvcyqcwOcywcyAcyycyucvxcyCcsHcyEcvBcyxctYcyFctYcyzcyGcyBcyHcyDcyDcyDcyIcvIckScmJchfcQkcQkcpKcpJcQkcQkcQkcQkcpMcpLcpOcpNcQkcQkcpPcQkcQkcTBdgmbQVcpScuvcqMcqMcqMcqMcqMcqMcHfbQXcqWcqUcqXcqXcqXcqYcrccrbcrbcrfcrbcrbcrbcrgczmczmcricrhcrjczwczzczyczBczAczCczCczDczCczCczCczCczGczIczCczCczCczOczLbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieciecdHckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczEczFczFczFczFczPczHczQczJczKczKczRcwxcsucoLcqFcoLcoLcoLcoLcoLcoLcoLcoLcoLcvocvocwIczMcwIcvocwIczMcvoczNcqPcngaaacyrczTczSczVczUczXczWczYczUczUcAacAccAbcAdczZczZcAecAfctYcAhcAgcyBcyDcyDcyDcyDcAicvIcrkcmJcrlcQkcrmcrocrncUTcrpcrrcrqcrtcrscrvcrucQncrxctecrycQkcrzcsLcukcrBcuvcrEcrCcrGcrFcrHcqMcqMbUxcrJcrIcrKcrKcrKcrKcsBcsAcsMcsFcsRcsPcsPcAKcAKcAJcALcAVcAYcAWcAPcAPcAQcAZcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAScBecAUbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacnkcieciecmCcmCckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicBgcAXcBjcAXcBmcBacBbcBccBdcBncwxcsucgQcgQcBfcngcngcngcngcngcngcngcBocvocwIcwIcwIcwIcBhcwIcwIcvocygciCcngaaacyrcBrcBqcBkcBlcwOcBscBucBtcBpcvxcyCcsHcnycBvcsDcBzcsDcvBcvBcvBcBDcBBcyDcyDcBFcBEcvIckScmJcsLcQkcsScsVcsTcsXcsWcsZcsYctbctactdctcctfctgcthcuqcQkcsLcJGbQVctjctictlctkctnctmctpctocqMctqctrcfZcepcepcepcepcepctsctsctscepcepaaaaaaaaaaaacBRcBScCacBUcAPcCdcCfcCecCgcBZcChcCbcCccCicCkcCjcCmcClcCncAPcAScCocCrcCpcCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCvcCucieclBcieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicCwcCxcCqcCyczJcCtcCzcCBczJcCDcCCcCEcskcgQcoLcngaaaaaaaaaaaaaaacngcoLcCFcwFcCAcwIcwIcwIcwIcCGcCIcCHcsvcngaaacCMcwUcCNcwVcCOcwOcwOcCRcCPcCKcCLcCUcCTcCVcBvcsDcCYcCQcCZcCScDacvHcDccyDcyDcyDcDdcvIckScmJctZcQkcudcufcuecUTcugcujcuhcumculcupcuncQncurcvdcuscQkcsLcrDcrDcuucutcuxcuwcuzcuycuBcuAcqMcuCcuDbQXcepaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcDycDAcDzcDucDBcDwcDwcDCcDwcDwcDwcDwcDwcDEdexcDGcDFcDHbGHcDIcjYbGHbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciecDJcDMcDKciecieckbckbcDNckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicDPcAXcDUcAXcDVcDLcDXcDZcBbcDOcwxcAFcqBcgQcqzcvpaaaaaaaaaaaaaaacvpcDQcvocwFcwFcwFcDScDTcwIcEbcvocoLciCcvpaaaaaaaaaaaacvqcEdcDWcEecEecvxcDYcvxcEfcsHcnycEicEjcEccElcEkcEkcEkcEscEgcyDcEhcyDcEtcvIckScmJcuEcQkcuFcuIcqNcQkcvOcUTcvPcvQcQncQncQncQkcQkcQkcQkcQkcsLcrDcvRcvTcvScuxcvUcvWcvVcvYcvXcqMcsLctrbQXcepaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcEHcEOcENcERcEQcEXcEVcEZcDwcDwcEPcDwcDwcDEcDGcDGcDGcFbbGHcFcbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciccEScETclAcidciecieckbckcckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacEUcEUcEUcEUcEUcwxcFdcEWcEWcEWcEWcEWcFecEYcEYcEYcEWcEWcEWcEWcEWcEWcEWcEYcEYcEYcvocvocvocvocvocvocvocqFcCJcFacFacFacFacFacvqcvxcvxcvxcvxcvxcvxcvxcFgcsHcnycFhcFjcFicFlcFkcFrcFocFucFtcFwcFmcFncFBcvIckScmJcKOcBPcvZdcCcQkcQkcwacwbcUTcwdcwccwfcwecwhcwgcwicQkcPccnVcrDcwkcwmcwlcuxcuxbUAcwncwscwrcqMcsLctrbQXctsaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcFNcFPcFOcFKcFQcFMcFRcFScDwcDwcDwcDwcFTcFYcFUcGacFZcGdbGHcFcbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacicciccicciccidcidcieciecieciecijaabaabaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczEczFczFczFczFczPczHczQczJczKczKczRcwxcsucoLcqFcoLcoLcoLcoLcoLcoLcoLcoLcoLcvocvocwIczMcwIcvocwIczMcvoczNcqPcngaaacyrczTczSczVczUczXczWczYczUczUcAacAccAbcAdczZczZcAecAfctYcAhcAgcyBcyDcyDcyDcyDcAicvIcrkcmJcrlcQkcrmcrocrncUTcrpcrrcrqcrtcrscrvcrucQncrxctecrycQkcrzcsLcukcrBcuvcrEcuwcuAcrFcvUcqMcqMbUxcrJcrIcrKcrKcrKcrKcsBcsAcsMcsFcsRcsPcsPcAKcAKcAJcALcAVcAYcAWcAPcAPcAQcAZcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAScBecAUbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacnkcieciecmCcmCckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicBgcAXcBjcAXcBmcBacBbcBccBdcBncwxcsucgQcgQcBfcngcngcngcngcngcngcngcBocvocwIcwIcwIcwIcBhcwIcwIcvocygciCcngaaacyrcBrcBqcBkcBlcwOcBscBucBtcBpcvxcyCcsHcnycBvcsDcBzcsDcvBcvBcvBcBDcBBcyDcyDcBFcBEcvIckScmJcsLcQkcsScsVcsTcsXcsWcsZcsYctbctactdctcctfctgcthcuqcQkcsLcJGbQVctjcticvXctkctnctmctpcwncqMctqctrcfZcepcepcepcepcepctsctsctscepcepaaaaaaaaaaaacBRcBScCacBUcAPcCdcCfcCecCgcBZcChcCbcCccCicCkcCjcCmcClcCncAPcAScCocCrcCpcCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCvcCucieclBcieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicCwcCxcCqcCyczJcCtcCzcCBczJcCDcCCcCEcskcgQcoLcngaaaaaaaaaaaaaaacngcoLcCFcwFcCAcwIcwIcwIcwIcCGcCIcCHcsvcngaaacCMcwUcCNcwVcCOcwOcwOcCRcCPcCKcCLcCUcCTcCVcBvcsDcCYcCQcCZcCScDacvHcDccyDcyDcyDcDdcvIckScmJctZcQkcudcufcuecUTcugcujcuhcumculcupcuncQncurcvdcuscQkcsLcrDcrDcuucutcuxcwrcuzcuycuBcwscqMcuCcuDbQXcepaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcDycDAcDzcDucDBcDwcDwcDCcDwcDwcDwcDwcDwcDEcDDcDGcDFcDHbGHcDIcjYbGHbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciecDJcDMcDKciecieckbckbcDNckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicDPcAXcDUcAXcDVcDLcDXcDZcBbcDOcwxcAFcqBcgQcqzcvpaaaaaaaaaaaaaaacvpcDQcvocwFcwFcwFcDScDTcwIcEbcvocoLciCcvpaaaaaaaaaaaacvqcEdcDWcEecEecvxcDYcvxcEfcsHcnycEicEjcEccElcEkcEkcEkcEscEgcyDcEhcyDcEtcvIckScmJcuEcQkcuFcuIcqNcQkcvOcUTcvPcvQcQncQncQncQkcQkcQkcQkcQkcsLcrDcvRcvTcvScuxcQRcvWcvVcvYcRucqMcsLctrbQXcepaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcEHcEOcENcERcEQcEXcEVcEZcDwcDwcEPcDwcDwcDEcDGcDGcDGcFbbGHcFcbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciccEScETclAcidciecieckbckcckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacEUcEUcEUcEUcEUcwxcFdcEWcEWcEWcEWcEWcFecEYcEYcEYcEWcEWcEWcEWcEWcEWcEWcEYcEYcEYcvocvocvocvocvocvocvocqFcCJcFacFacFacFacFacvqcvxcvxcvxcvxcvxcvxcvxcFgcsHcnycFhcFjcFicFlcFkcFrcFocFucFtcFwcFmcFncFBcvIckScmJcKOcBPcvZdcCcQkcQkcwacwbcUTcwdcwccwfcwecwhcwgcwicQkcPccnVcrDcwkcwmcwlcuxcuxbUAcSQdaIdaHcqMcsLctrbQXctsaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcFNcFPcFOcFKcFQcFMcFRcFScDwcDwcDwcDwcFTcFYcFUcGacFZcGdbGHcFcbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacicciccicciccidcidcieciecieciecijaabaabaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaacFVcFWcFXcGecFXcGfcFWcGgcGbcGccGccGicAGcGkcDRcGmcGlcGocGncGqcGpcGpcGrcGpcGscGtcGtcFfcGucGxcGwcGycGwcGwcGwcGxcGwcGwcGzcGBcGAcGDcsHcnycGJcGNcGMcGCcsDcGOczZcGEcGFcGGcGHcxicwtcGKckScmJcxlchfdcDcxpcxncQkcxqcxrcUTcxtcxscxvcxucUTcxwcxxcQkcsLcBwcrDcxycmycxzcxBcuxcBPcBPcBPcBPchfcebctrbQXctsaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaacBScBRcHmcHgcBScHncHicHjcHvcHtcHxcHwcDwcDwcHocHpcHqcHrcHsbGHcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacFVcFWcFXcFXcFXcGfcFWcHycFXcANcFXcHBcEacHEcGjcHzcHucHzcHFcHJcHDclXcHDcHDcHKcnAcnAcHDcHGcHDcHDcHDcHDcHDcHDcHDcHDcHDcHDcHHcHIcHMcHLcHOcHNcHUcHTcHPcHQcHRbWTcdGcaycHVcHYcxDcxCcGKckScmJctZcucdducxEddwcQkcxFcxGcUTcxJcxHcxPcxLcUTcxRcxTcQkcyJcsLcrDcyKcyMcyLcpQcrDcyNcyNchfcmAcyPcebctrbQXctsaaaaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaacBRcHAcHXcHCcBRcAPcAPcAPcAPcAPcAPcICcHwcIDcIHcIFcIEcAPcAPbGHcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacFVcIIcFXcIGcFXcGfcIJcIMcIKcINcILcITcIzcIBcIAcIQcIRcIScIVcIXcIWcJacIYcJbcqVctScqVcIXcJccIXcIXcIXcIXcIXcIXcIXcIXcIXcIXcJdcHDcKmcJecJicJhcJgcJjcJodcdcfjcfhcgRcfucJycJpcyRcyQcGKckScmJcsLchfchfcySchfcQkcQkcQkcQkcyVcyUcyXcyWcUTcyYczacyZcyJcsLchfchfchfchfchfchfcsLcyNchfczbchfcsLctrbQXcepaaaaaaaaaaaaaabcepcBRcBRcBRcBRcBRcBRcBRcBRcIOcJNcIPcxNcJKcJKcJLcBRaabcAPcAPcJOcAPcJTcJRcJPcAPcJQcuQcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9071,7 +9080,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabhnaaaalwaaacNFcMBcNMaaacNFcMBcNMaaacNFcMBcNMaaaaaacLicNAcNBcNCcLicNDcNNcLmcLmcLmcLmcLmcLmcLmcLmcLmcNRcKfcNGcJxcMycMCcJxcJxcJxcMEcJxcNGcNGcJxcJxcJxcJxcNwcNKcMGcNLcHDcNScyEcHQcHQcNTcLOcNOcNPcNQcLOcNUcHVcJMcKocKccAHcGKcsKcsLcNYcsLcAIdfMcAOcAMcARcARcARcARcBxcATcBycBycBycBycBAcyJcMfczqcyJcyJcebcsLcsLcBCcAvcAvczqcBCcBYcsLcsLcBGcBHciYbQXcBIcepcxNcxNcxNcxNcKpcEHcOlcOncOmcOpcOocxNcKscKVcKTcBRaaaaaacLbcOvcOucOscLecODcLbcOCbGGcFcbGHaabaabaabaabaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwaaacNFcNEcNMaaacNFcNEcNMaaacNFcNEcNMaaaayicLicNBcNBcNBcLicLicOwcOxcLicLicOxcOxcLicLicOxcOxcLwcKfcNGcNHcJxcNIcNJcNZcNZcMxcJxcNGcOGcJxcJxcJxcJxcOHcOycOJcOIclXcOKcOMcOLcOYcORcLOcNOcOZcONcLOcOOcHVcGKcGKcGKcBJcGKcZScOTcOUcOTcOWcOTcOTcOTcOTcOTcBKcBPcBPcBPcBPcBPcBPcBPcBLcnVcBQcsLcBOcBMcBTcsLcsLchfcBWcBVcBXchfcDbcCXcPhcDecDgciYbQXcDhcepcKPcKQcKRcPmcLccNocPncPjcPocPqcPpcPscPrcPpcPtcBRaaaaaacLbcLbcPycPAcPzcLbcLbbGHbGGcPBcuQcuQcuQbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaayiaabcNFcNEcNMaaacNFcNEcNMaabcNFcNEcNMaaaaabcLicMrcPucNDcLiaaaaabaaaaaaaaaaaaaaaaabaaaaaacOxcLwcKbcOzcJxcJxcOAcOBcLfcLdcLfcLncLfcOEcOQcLDcPvcNGcNGcNKcPLcPJcPNcPMcPPcPKcPVcPSbgYcPObHWcPQcPRcPYcPTcPUcPUaPdcDjcDicQdcPZcQfcDkcQhcQgcDlcQicQocQmcQpcQpcQpcQpcQpcQpcPwcBPcBLcsLcDmchfchfcBQcBQchfcDnchfchfchfchfchfciYcDobQXctrbQXciYcDpbQXcepcJKcKZcJKcQxcJrcEHcQzcQAcQrcQscEHcEHcQtcEHcQBcBRaaaaabaabcLbcLbcQvcLbcLbaaabGHbGGcFccuQcQwcQCbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacNFcNEcNMaabcNFcNEcNMaaacNFcNEcNMaabaaacLicLicOxcLicLiaaaaabaabaaaaabaaaaabaabaaaaaacQycQDcKbcLqcLvcLvcLPcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcJZcQIcJZcQEcJZcFacQKcxAbHYcQNcQNcQNcyhcQScPTcQLcQMbhCcDtcDscQQcPZcDxcDvcQTcEmcEncRacRdcRcaabcQZcQZcQZcQZcQZcPxcBPcEocsLcMfcsLcyJcyJcsLcsLcsLchfcEpchfcsKcEqciYciYciYctrbQXciYciYciYcepcJKcJKcJKcRDcLQcNocRHcRIcRtdeycRvcRvcRJcEHcRxcBRaabaabaaaaaaaaacRyaaaaaaaaabGHbGGcFccuQbGGbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacNFcNEcNMaabcNFcNEcNMaaacNFcNEcNMaabaaacLicLicOxcLicLiaaaaabaabaaaaabaaaaabaabaaaaaacQycQDcKbcLqcLvcLvcLPcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcJZcQIcJZcQEcJZcFacQKcxAbHYcQNcQNcQNcyhcQScPTcQLcQMbhCcDtcDscQQcPZcDxcDvcQTcEmcEncRacRdcRcaabcQZcQZcQZcQZcQZcPxcBPcEocsLcMfcsLcyJcyJcsLcsLcsLchfcEpchfcsKcEqciYciYciYctrbQXciYciYciYcepcJKcJKcJKcRDcLQcNocRHcRIcRtdbDcRvcRvcRJcEHcRxcBRaabaabaaaaaaaaacRyaaaaaaaaabGHbGGcFccuQbGGbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvayiaaacNFcNEcNMaabcNFcNEcNMaaacNFcNEcNMaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcRzcRAcRAcRAcRAcQycRBcLwcRCcRKcREcREcRFcRGcRMcRLcRLcRLcRLcRNcRPcROcRQcRQcRScRScRQcRTcRVcRUcRRcRRcRYcRWcTecSabHZcRXcRXcShcRZcSjcSbbjicErcSdcSecPZcEucSlcSmcEvcSpcSocSrcSqcQpcSncSucSscSwcQZcPxcBQcEwcsLchfcExchfcEycEAcEzcyJchfcECcEBcsLcsLciYcEDcgactrbQXciYcEFcEEcepcxNcxNcxNcxNcLRcEHcQzcEIcSOcQscEHcSGcSHcSHcSPcSJcSKaabaaaaaaaaaaaaaaaaaaaaabGHbGGcPBbGGbGGcSLbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwaaaaabaaaaabaabcPCaabaabaabcPCaabaaaaabcPCaabaaaaaaaaaaaaaaaaaaaaaaaaaaacRzcRzcRzcSRcTacSTcRAcTbcTccNRcRCcRCcSScTdcKbcKbcMvcSUcSUcSUcSUcSVcSWcSXcSWcSWcSWcRRcRRcSYcSZcTfcTicTgcRXcTjcTecRXcRXcRXcRXcTkcPTcTlcThcSdcErcSdcSdcPZcEucSlcTncEJcTqcTpcTucTraabcTocTvcSwcTwcQZcPxcBQcELcEKcFpcEMchfcsLcsLcsLcFqcMfcFscyJcFscsLciYbQXcgactrcFvciYbQXcFvcepcKPcKQcKRcTJcLccNocTKcTNcTMcTGcTGcTHcTIcTPcTOcBRaabaabaabaaaaaaaaaaaaaaaaaabGHcTLcFcbGHbGHbGHbGHbGHaabaabaabdoEdoEdoEdoEdoEdoEaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcPGcPHcPHcPIcyOcyOcyOcyOcyOcyOcyOcyOcyOcyOcyOcyOcQacPHcPHcPHcPHcPHcQqcTZcTYcUbcUacUecUdcUgcUfcNBcLwcUccRCcKbcKbcKbcUhcMvcSUcUkcUjcUmcFxcUicFycFAcFzcUrcFCcUucUscUxcUwcUycFCcUtcUzcTecUvcRXcRXcRXcUAcPTcSdcSdcSdcFEcFDcFGcFFcFIcFHcFLcFJcUPcUNcUScSqcUVcSncUWcSwcSwcQZcPxcBQcGIcsLctZcmJchfchfcMfchfchfchfcyJcyJcyJcsKchfchfchfctrbQXcGLbQXbQXcepcJKcMgcJKcVecJrcEHcVfcUXcUYcEHcUZcVgcxNcxNcxNcBRaaaaaaaabaabaaaaaaaaaaaaaaabGHcJQcFcbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9079,36 +9088,36 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvalwaabcNFcSkcNMaaacNFcSkcNMaaacNFcSkcNMaabaaaaaaaaaaaaaaaaaaaaaaaaaabaabcRzcRAcRAcRAcRAcWkcWlcWmcNBcWncNBcNBcMvcWocNBcSUcWzcWycVjcHhcUicWscWtcWucWucHkcWDcWCcWFaYtaZBcHkcWBcWHcWJcWIcWLcWKcWPcWMcWScMicUGcWTcWUcWNcWOcWVcWWcWRcWYcWXcXbcXacXdcXccQpcSncXecWZcWZcQZcPxcBPcGIcsLcsLcHlchfchfchfcyPcyPchfchfchfchfcHZcIacsLchfctrcIccIbcIbcIbcIbcIbcIbcIbcIbcMjcXvcXtcXzcXxcNocXAcNocXAcNocXBcWwaaaaaaaaaaaaaabaabaaaaaaaaaaaabGHcFcbGHaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacNFcSkcNMaabcNFcSkcNMaaacNFcSkcNMaaaaaaaaaaaaaabaaaaaaaaaaaaaabaabaabaaaaaaaabaabcXucXucXucXucXucXucXucXCcXucXucSUcXwcXDcVjcHhcUicXycUicUicXEcRRcXGcXFcUwcIdcIecRRcXLcRXcTecXMcXOcXNcWPcXPcXJaZCcXRcXQcXVcXScXRcXWcXYcXXcYacSdcXTcXUcYccYbaabcTocYfcIfcXZcQZcPxcBQcIgdfMdfMcIhcIichfcIkcIjcImcIlcIocInchfcsLcAvcsLchfctrcIqciYbQXcIrcIsciYcIucItcepcMIcMQcMJcNacMIcMQcNbcNccMIcMQcNlcBRaabaabaabaabaabaabaabaabaabaabbGHcFcbGHbGHbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacYzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcNFcSkcNMaaacNFcSkcNMaaacNFcSkcNMaabaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaabaabaabcXucYtcYtcYucYAcYBcYBcYDcYCcYCcYEcYGcYFcVjcHhcVjcYHcVjcVjcVjcRRcYLcIvcIxcIwcIycYIcYJcYQcYRcYMcYMcYMcYXcYUcYZaZHcZacYSbqmcQPcYTcZbcYVcYWcZccSdcXTcZdcZgcZecZhcSncZicWZcWZcQZcPxcBQckKcExchfcyJcJqcyPcJscImcJucJtcJvcsLcJwcYjcAvcTQchfctrcIqciYbQXcpEbQXciYcJzcIrcepcZqcZscZrcxNcZtcZycZvcxNcZzcZBcZAcBRaabaabaaaaaaaaaaaaaaaaaaaaaaaabGHcFcbGGbGGbGHaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcNFcSkcNMaaacNFcSkcNMaabcNFcSkcNMaabaabaabaabaaaaabaaaaaaaabaabaaaaaaaaaaabaaaaaacXucYtcYtcYucZucZucZucZCcZwcZxcSUcJBcJAcJDcJCcJFcJEcJHcZFcZFcZLcZOcZNcVjcVjcVjcZPcZRcZQcZMcJIcNXcNVdacdabcSUcZScZSdafbqmcQPcZUdagcZWcZXcZYcSdcZZdahdajdaidadcQZcQZcQZcQZcQZcPxcBQckKdaecsLcyJcJqchfcKvcKucKwcJtcKAcIjcKCcKBcKDcTQchfctrcIqcGLbQXcKEcKFciYcKGbQXcepcMkcJKcJKcxNcMkcJKcJKcxNcMkcJKcJKcBRaaaaabaabaaaaaaaaaaaaaaacuQcuQbGHdaucuQbGGbGHbGHbGHdoEdoEaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamhaabcNFcTRcNMaaacNFcTRcNMaaacNFcTRcNMaabalvaabaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaabcXudaodapcZucZucZudaxdardardardardardardarcKHcKJcKIcKKdawdawdawdaFdaydaJdaAdaBdawdaydaKdaRcKLcNXcObdacdabdaGdaHdaIdaTdaUdaLdaMdaNcZcdaOdaPdaVdaYdaWcOkcXcdbacSndbcdbbdbbcQZcPxcBPckKchfcBNdaXcJqchfcKNcKMcJtcIjcJtcKScJtcJucJtcsLchfctrcIqciYbQXciYciYciYbQXbQXcepdbfcKZcJKcxNdbfcKZcJKcxNdbfcKZcJKcBRaaaaaaaabaabaaaaaaaaaaaacuQdbgbGGcFccuQdbhcuQdbibGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaaaaabaaaaaaaaaaabaabaabaaaaaaaabaabaaaalvaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaabcXudbjcZucZucZucZucZudardbtdblcOqcOtcOrdarcKUdbqdbrcHhcVjcVjdbsdbBdbydbEdbCdbGdbFdbzcSUdbAcKLcNXcPgdacdbJcSUdbDcZSdbKdbLcSddaMdaNdbNcSddaPdaVcXTcXUcPicYbdbIcTodbScLVdbWcQZcPxcBPckKchfdbMdbMcJqchfcLYcsLcLZcIjcMccMbcMecMdcJGcJvcyPctrcIqciYbQXbQXcMhciYbQXaqFcepdbRcJKcJKcxNdbRcJKcJKcxNdbRcJKcJKcBRaaaaaaaaaaabaabaaaaaaaaacuQbGGbGGcFccuQbGGbGGbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvalwalwamhalvalvalvalvalwalvalvalwdbTaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacXudbUcZwcZucZucZudbVdardblcPkcMOcMTcMScMVcMUcMYcMWcMZcVjdcmdcldchcPlcPEcPDcPWcPFdcndcwdbrcHhcWecPXcZMcQccSUdcscZSdctdcLcSddaMdaNcZccSddcvdaVcXTdcOcQecZedcScSndcTdbbdbbcQZcPxcBQckKcTUcuccABcJqchfchfcNdcNecDncNfcNfcNgchfchfchfchfctrcIqciYbQXcNhcKFciYcepcepcepcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRaaaaaaaaaaaaaabaabaaaaaabGHbGHbGHcFccuQdcJdcKbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcXucXucXudcUdcMdcMdcMdardcNcQjdcPdcPdcQdcWdawcNidcXcNkcNjcNjcNWcQVcQFcOaddbcOccQGcQVcOdcOfcOecOhcOgcOicQHddrdbDcZSddmddscSddaMcSdddtcSddaPdaVcXTcXUddxcYbdbIcQZcQZcQZcQZcQZcPxcBQcOjcYlcuccTBcOScOPcOVcOPcOXcsLcsLcsLcsLczfchfcPacPecPbcPfcGLbQXcFvcepcepaaaaaaddFaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaabaaabGHcJQddBddKcuQddJddIbGGbZZaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddLcXucZucZucZudcMaabaabdarddGcQJdcPdcPcQUdarcRgcRwcRrcSvcStcSNcSxcSUcUBcQbddScVjcVccSUcVpcVqcVqcSvcSvcVucVrcSUddZcZSdeadehcSddaMcSdcZUdagdecdeidaYdejdekcXcdelcSndendemdemcQZcPxcBQcsLckKchfchfcPdchfchfcsLcQlcyJcyJcyJcsLcQucGvcQOcQXcQWcDocepcepcepcepaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaabbGHdbgcAScaccuQcuQcuQbGGbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcXucZucZucZudcMaabaaadardescQJdcPdcPcVvdardeucQYcSUdeFcRbcRbcRfcSUcVwdeAdeBdeCcVycSUcRbcRbcRbdeFcSUcRhdeucSUdbDcZSdeOdePdeHdeIdeJdeKdeQdeRcXbdeUcXUdeVcYbdbIcTodeXcRideYcQZcPxcBPcBPckKcprdeScRjdeTchfcsLdfadeZdffcRkcRmcRlchfciYciYcRncepcepaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabGHbGHbGHbGHbGHdfhcaccuQdfidfcbGGbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacXucXudcMdcUdfdaaaaaadardfecVzdcPdcPcVAdardfwcRodfzdfkcRpcRqcRpdfocVBdfqdfrdfscQHdfocRpcRpcRpdftdfzcRsdfvcSUdbDdfEdaMdfxdfydeQdfFdfGdfBdfIdfHdfKdfJdfNcZedcScSndfOdemdemcQZcPxcBPcsLcOjcSfcScdfgcsKchfdgmcTBcsLcYidfLcsLcYicBNchfcSgcFcbGHaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabGHbGGbGGbGGcJQdfSdfUcuQdfPbGGbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadfWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadfXdfYdfYdfZdfYdfYdgadardfVcQjdcPdcPcVCdardaGcSicSUcSUdfodfodfodfocVGcVScVNcSvcVTdfodfodfodfocSUcSUcSydglcSUdbDcZSdgrdgsdfydggdghcSdcSddgtcXWdggcXUdgjcYbdbIcQZcQZcQZcQZcQZcPxcBPcTBcsLdgkdgCcsLdgmchfchfdgnchfdgocpscJGcYichfchfcuQcFcbGHaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaabGHbGHcuQdgAdgycJQdfScacbGGbGGbGGdgBbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdgwdgvdgxdgFdardgzcVWcMMdcPcVXdarcSUcSzcSUdgJafOdgEdfodfodfodfocSAdfodfodfodfodgEafOdgJcSUcSBcSUcSUdbDcZSdgMdeHdgNdgPdgOdgRdgQdgPdgQdgPdgVdeQdgWdbIdmodmodmodmodmocPxdgSdgTdgTdgUdhjdgTdgTdgTdhkdgXdgYdgodgZchfdgochfdhacuQcFcbGHbZZbZZbZZbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHbGHbGHbGHbGHbGHbGHbGHbGHbGHcMsbGHcJQcuQcTSbGGcQwdfScaccuQcuQdbhcuQbGHaabdhcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdgwdgwdhdbJMdardhfcVYdcPdcPcVZdarcSCcSDdhoafOcSEcSFcSFcSFcSFcSFcSIcSFcSFcSFcSFcSFcSMafOdhvcTscTmcSUdhsdaIdhzdhBdhAdhCdhxdhEdhDdhFcSddhHdhGdhJdhIdbIdmoaaaaabaabaaadhMdhLcTVcTXcUCcVkcVHcWxdgTdhYcsLcsLdhPcpsdhQcYicTUcsLcEGdhZdiadiadiadiadiadiadiadiadiadiadiadiadiadiadiediadiadiadiaczLcuQbPAcAUbGGdiccMscuQcuQcuQdbhcuQdfScaccuQdidbGGbGGbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdhWdgvdhXdifdardfVcQjdcPdcPcWadarcTtdibdibaaacTxafOafOafOafOafOafOafOafOafOafOafOcTxaaadibdibcTtcSUdaGcZSdhIdikdijdipdioditdhIdipdhIcYbdhIcYbdhIdbIdmoaaaalwalwdiudhLcXmcYgcYydavdcrdcudcxdgTcsLcsLchfdgodiqchfcYicXrdfMdhRdizdiAdiAdiAdiAdiAdiAdiCdiBdiAdiAdiAdiAdiAdiAdiEdiDcTTdiFdiJdiIdiLdiLdiLdiLdiNdiMdiOdiLdiLdiLdiLdiQcjYcuQdfcbGGdiHbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadiSdfYdfYdfYdfYdfYdiTdardiKcWbdcPdcPcWcdarcTycTzdiPaabcTxafOdjqaaaaaaaaaaaadjqaaaaaadjqafOcTxaabdiRcTCcTAcSUdaGcSUaabdiUaabdiVdiWdiXdiYdiZdiYdjadiYdjadjbdjcdmoaaaalwaabdjddgSdcydczdcAdcFdcHdcIdcRdgTdjlcsLcsLcYidjmchfcYicYidjzbGHbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHdjobGGcuQcTLbGGcuQcuQbZZbZZcxScuQdjAbGGdjAcuQdjCcacdjrbGHbGHbGHbGHbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadardjscWbdcPdcPcWddarcTtdibdjvaaacTDcTEaaaaaaaaaaaaaaadjyaaaaaaaaacUlcTFaaadibdibcTtcSUdaGcSUcQZdjBcTodjBcQZdjBcTodjBcQZdjScTodjUcQZaabdmoaaaalwaabdjEdgSdcVdczddaddcdcHdddddedjKdirdjYdjMcYicpscsLdjNdgochfcBPaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaabGHdjXcLhcuQdjPbGGcuQaaaaaaaaaaaacuQbGGbGGdbgdjQdjQdkadkbdjQaaaaabaabaabaabdjTaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadardkccQjdcPdcPcWadarcUncTmdibaaacTxafOaaaaaaaabaabaabaabaabaaaaaaafOcTxaaadibcSCcUocSUdjZcSUcQZdkidkhdkkcQZdkqdkpdkscQZdkwdkudkxcQZaabdmoaaaalwaaadjEdkjddfddgddhddiddjddkddldgTdkrdgochfdgodkGchfdktdgocBNcBPcBQcBQcBQdmoaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaabGHdkFcuQcuQcQCbGGcuQcuQbZZbZZcuQcuQbGGdkvcLhdjQdkIdkHdkMdjQaaaaaaaabaabaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOdardardardardardardarcSUcTtdibaaacTxafOdjqaabaabdkzdkAdkBaabdkCaaaafOcTxaaadibcTtcSUcSUdaGcSUcQZdkObbMdkOcQZdkTbbOdkTcQZdkVbdGdkVcQZaabdmoaaaalwaaadjddgSddnddoddpddqddvddyddzdgTdkPdkQdkZdkSdlacsLcYicYidlbdlddlccsLdlhdmoaaaaabaaabZZbZZbZZbGHbGHbGHbGHbGHbGHdlicJQcuQdljbGGbGGcuQbGGbGGbGGbGGcTSbGGdfPdjQdlodlkdlqdjQaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabafOafOaabaabaabalwalwcSUcSUcUpdibaaacTDcTEaaaaaaaabdledlfdlgaabaaaaaacUlcTFaaadibcUqcSUcSUdaGcSUcQZdkOdlvdkOcQZdkTdlwdkTcQZdkVdlxdkVcQZaabdmoaaaalwaaadjddgSdgSdgSdlldlmdlndlydlndlmdkPdlpcsLdlAdlrdfMddHcYidlscBPcBQcBQcBQddAaabaabaaabZZdlBdlCcuQbGGdlDdlJdbgcuQdlPbGGcuQdlzbGGbGGdlLbGGbGHbGHbGHbZZbZZbGHdjQdlSdlRdlUdjQaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaabaabaaaaaaaabaabalwcSUcSUcTtdibaaacTxafOaaadlEaabdlFdlGdlHaabaabdjqafOcTxaaadibcTtcSUcSUdaGcSUcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZaabdmoaaaayiaaadjdaaaaaaaaadlIdlmdlVdlXdlWdlmcsLdlMcsLcsLdlNdlOcXrdmcdlQcBPaaaaaaaaaaaaaaaaabaaabZZdlZdmbdlLbGGdgybGGbGGdlLdjobGGcuQcuQcuQcuQcuQbGGbGHaabaaaaaaaaaaabdlTdlTdmddlTdlTaabaabdhcaabaabdjTaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabcSUcSCcUodibaaacTxafOaaaaaaaabaabaabaabaabaaaaaaafOcTxaaadibcUncTmcSUdmecSUcSUcSUcSUddCdmodmodmodmodmodmodmodmodmodmodmoaabaabaabdjEaaaaaaaaadlYdlmdlndmhdlndlmdmadmidfMdfMdmldmrdmmcBPcBPcBPaaaaaaaaaaaaaaaaabaaabZZdlBdmncuQdbgbGGbGGdmpcuQdmqbGGbGGbGGbGGbGGbGGbGGbGHaabaaaaaaaaaaabaaadlTdmsdlTaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaabcSUcTtdibdmjaaacTDcTEaaaaaaaaaaabaaaaaaaaaaaaaaacUlcTFaaadibdibcTtcSUdmkcQRdmvdaGdcqdmoaabaabaabaabaabaabaabdmoaabaabaabaabaabaabdjEaabaabaabdlYdlmdmydmAdmzdmEaabdmacBPcBQdmtcBQcBPcBPaaaaabaaaaaaaaaaaaaaaaabaabbZZbZZbZZbGHbGHbGHbGGcuQbGHdmubGHbGHdbgbPAcLhbKlcMsbGHaabaaaaaaaaaaabaaadlTdmGdlTaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcSUcUDdbudiPaabcTxafOdjqaaaaaadjqaaaaaaaaaaaadjqafOcTxaaadiRdbQcUEcSUdmLcSUcSUcSUcSUcSUcSUaaaaaaaabaaaaaaaaadmoaaaaaadmBdmBdmBdmBdmCaaaaaaaabdlYdmDdlmdmOdlmdlmaaaaabaaaaaadmFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaabGHdmbdmMbGHdmNaabbGHbGHbZZbZZcMsbGHaaaaabaaaaaaaaaaabaaaaaaddDaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUcUFcUIcUHaaacTxafOafOdcfafOafOdcfafOafOdcfafOafOcTxaaacUJcUIcUKcSUdmPdmQdnjdnldnkcSQdmVdmWdmWdmXdmWdmWdmWddEdmWdmWdmZdnadnbdnodmCaaaaaaaabdnddmodlmdnedlmddMaabaabaaaaaadngaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaabpaaaaaabGHdnqdnnbGHdnpaabaaaaabaaaaaaaabaaaaaaaabaaaaaaaaaaabaaaaaaddNaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadnscSUcSUcULaaacUMcSFcSFcUOcSFcSFcUOcSFcSFcUOcSFcSFcUQaaacULcSUcSUcSUdmPdnBdnAdnEdnCdnHdfoaaaaaaaabaaaaaaaaadmodmBdmBdmBbfmbJNdnvdmCaaaaaaaabaabdmodnxdnIdnxdmoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaaaaaaaaabZZdnJbZZbZZaabdhcaaaaabaaaaaaaabaaaamWamWalwayiaabaabaabaabddNaabaabaabaabdhcamhamWamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcSUcYXcURcUHaabaabaabaabaaaaaaaaaaaaaaaaabaabaabaabcUJcUUcYXcSUcSUdnDcSUcSUcSUcSUdfocSUaabaabaabaabaabaabddObfubjbbhybkJdnGdnFdmCaaaaaaaaaaabdmoaaaaaaaaadmoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaabZZdnPbZZaaaaaaaaaaaaaabaaaaaaaabaaaamWaaaaaaaabaaaaabaaaaaaddPaaaaaaaabaaaaabaaaaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacSUcSUcURcVacVacVacVacVacVacVacVacVacVacVacVacVacUUcSUcSUcSUdnKdnScSUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddQdnTdnWdnVdobdoadofdoeaaaaaaaaaaabdmodmodmodmodmoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaabZZdogbZZaaaaaaaaaaaaaabaaaaaaaabaaaamWaaadohdohdohdohdohaabcTWaabdohdohdohdohdohaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUaaacSUcSUdnXcSUcSUcSUcSUaaaaaaaaaaaaaaaaaaaaaaaacPxdnZdnZdnZdnZdojdokdocdoddolaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaabZZdombZZaaaaaaaaaaaaaaaaaaaaaaabaaaamWaabddRddTddTddTddTddUcTWddVddWddWddWddWddXaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUdaGdaGddYdoudoudowaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdnZdoydoxdoAdnZdnZdnZdnZdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabdebdoEdoEaaaaaaaaaaaaaaaaaaaaaaabaaaamWaabdoGdoGdoGdoGdoGaaacTWaaadoGdoGdoGdoGdoGaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUdjZdaGdoLdoIdoMdozaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdoNdoOdoCdoDdoQdoSdoRdoHdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaabaaaamWaaaaabaaaaabaabaabaaacTWaaaaabaaaaabaaaaabaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadoTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUdoJdaGdeddoudoudoVaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdoWdoYdoXdoPdoZdpcdpadpgdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaamWaaadohdohdohdohdohaabcTWaabdohdohdohdohdohaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadnscSUcSUcSUcSUcSUcSUaaaaaaaaaaaaaaaaaaaabaabdjEaabdnZdphdpjdpidpndpkdpsdprdpbdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamWaabddRddTddTddTddTddUcTWddVddWddWddWddWdeeaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcNFcSkcNMaaacNFcSkcNMaabcNFcSkcNMaabaabaabaabaaaaabaaaaaaaabaabaaaaaaaaaaabaaaaaacXucYtcYtcYucZucZucZucZCcZwcZxcSUcJBcJAcJDcJCcJFcJEcJHcZFcZFcZLcZOcZNcVjcVjcVjcZPcZRcZQcZMcJIcNXcNVdacdabdcqdcqdcqdafbqmcQPcZUdagcZWcZXcZYcSdcZZdahdajdaidadcQZcQZcQZcQZcQZcPxcBQckKdaecsLcyJcJqchfcKvcKucKwcJtcKAcIjcKCcKBcKDcTQchfctrcIqcGLbQXcKEcKFciYcKGbQXcepcMkcJKcJKcxNcMkcJKcJKcxNcMkcJKcJKcBRaaaaabaabaaaaaaaaaaaaaaacuQcuQbGHdaucuQbGGbGHbGHbGHdoEdoEaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamhaabcNFcTRcNMaaacNFcTRcNMaaacNFcTRcNMaabalvaabaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaabcXudaodapcZucZucZudaxdardardardardardardarcKHcKJcKIcKKdawdawdawdaFdaydaJdaAdaBdawdaydaKdaRcKLcNXcObdacdabddrdcsddZdaTdaUdaLdaMdaNcZcdaOdaPdaVdaYdaWcOkcXcdbacSndbcdbbdbbcQZcPxcBPckKchfcBNdaXcJqchfcKNcKMcJtcIjcJtcKScJtcJucJtcsLchfctrcIqciYbQXciYciYciYbQXbQXcepdbfcKZcJKcxNdbfcKZcJKcxNdbfcKZcJKcBRaaaaaaaabaabaaaaaaaaaaaacuQdbgbGGcFccuQdbhcuQdbibGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaaaaabaaaaaaaaaaabaabaabaaaaaaaabaabaaaalvaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaabcXudbjcZucZucZucZucZudardbtdblcOqcOtcOrdarcKUdbqdbrcHhcVjcVjdbsdbBdbydbEdbCdbGdbFdbzcSUdbAcKLcNXcPgdacdbJdcqdetdcqdbKdbLcSddaMdaNdbNcSddaPdaVcXTcXUcPicYbdbIcTodbScLVdbWcQZcPxcBPckKchfdbMdbMcJqchfcLYcsLcLZcIjcMccMbcMecMdcJGcJvcyPctrcIqciYbQXbQXcMhciYbQXaqFcepdbRcJKcJKcxNdbRcJKcJKcxNdbRcJKcJKcBRaaaaaaaaaaabaabaaaaaaaaacuQbGGbGGcFccuQbGGbGGbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvalwalwamhalvalvalvalvalwalvalvalwdbTaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacXudbUcZwcZucZucZudbVdardblcPkcMOcMTcMScMVcMUcMYcMWcMZcVjdcmdcldchcPlcPEcPDcPWcPFdcndcwdbrcHhcWecPXcZMcQcdcqdevdcqdctdcLcSddaMdaNcZccSddcvdaVcXTdcOcQecZedcScSndcTdbbdbbcQZcPxcBQckKcTUcuccABcJqchfchfcNdcNecDncNfcNfcNgchfchfchfchfctrcIqciYbQXcNhcKFciYcepcepcepcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRaaaaaaaaaaaaaabaabaaaaaabGHbGHbGHcFccuQdcJdcKbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcXucXucXudcUdcMdcMdcMdardcNcQjdcPdcPdcQdcWdawcNidcXcNkcNjcNjcNWcQVcQFcOaddbcOccQGcQVcOdcOfcOecOhcOgcOicQHdexdewdcqddmddscSddaMcSdddtcSddaPdaVcXTcXUddxcYbdbIcQZcQZcQZcQZcQZcPxcBQcOjcYlcuccTBcOScOPcOVcOPcOXcsLcsLcsLcsLczfchfcPacPecPbcPfcGLbQXcFvcepcepaaaaaaddFaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaabaaabGHcJQddBddKcuQddJddIbGGbZZaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddLcXucZucZucZudcMaabaabdarddGcQJdcPdcPcQUdarcRgcRwcRrcSvcStcSNcSxcSUcUBcQbddScVjcVccSUcVpcVqcVqcSvcSvcVucVrdcqdeydcqdeadehcSddaMcSdcZUdagdecdeidaYdejdekcXcdelcSndendemdemcQZcPxcBQcsLckKchfchfcPdchfchfcsLcQlcyJcyJcyJcsLcQucGvcQOcQXcQWcDocepcepcepcepaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaabbGHdbgcAScaccuQcuQcuQbGGbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcXucZucZucZudcMaabaaadardescQJdcPdcPcVvdardeucQYcSUdeFcRbcRbcRfcSUcVwdeAdeBdeCcVycSUcRbcRbcRbdeFcSUcRhdeudcqdezdcqdeOdeDdeHdeIdeJdeKdeQdeRcXbdeUcXUdeVcYbdbIcTodeXcRideYcQZcPxcBPcBPckKcprdeScRjdeTchfcsLdfadeZdffcRkcRmcRlchfciYciYcRncepcepaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabGHbGHbGHbGHbGHdfhcaccuQdfidfcbGGbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacXucXudcMdcUdfdaaaaaadardfecVzdcPdcPcVAdardfwcRodfzdfkcRpcRqcRpdfocVBdfqdfrdfscQHdfocRpcRpcRpdftdfzcRsdfvdcqdeEdeLdeGdeMdfydeQdfFdfGdfBdfIdfHdfKdfJdfNcZedcScSndfOdemdemcQZcPxcBPcsLcOjcSfcScdfgcsKchfdgmcTBcsLcYidfLcsLcYicBNchfcSgcFcbGHaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabGHbGGbGGbGGcJQdfSdfUcuQdfPbGGbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadfWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadfXdfYdfYdfZdfYdfYdgadardfVcQjdcPdcPcVCdardaGcSicSUcSUdfodfodfodfocVGcVScVNcSvcVTdfodfodfodfocSUcSUcSydgldcqdetdcqdgrdgsdfydggdghcSdcSddgtcXWdggcXUdgjcYbdbIcQZcQZcQZcQZcQZcPxcBPcTBcsLdgkdgCcsLdgmchfchfdgnchfdgocpscJGcYichfchfcuQcFcbGHaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaabGHbGHcuQdgAdgycJQdfScacbGGbGGbGGdgBbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdgwdgvdgxdgFdardgzcVWcMMdcPcVXdarcSUcSzcSUdgJafOdgEdfodfodfodfocSAdfodfodfodfodgEafOdgJcSUcSBcSUdcqdetdcqdgMdeHdgNdgPdgOdgRdgQdgPdgQdgPdgVdeQdgWdbIdmodmodmodmodmocPxdgSdgTdgTdgUdhjdgTdgTdgTdhkdgXdgYdgodgZchfdgochfdhacuQcFcbGHbZZbZZbZZbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHbGHbGHbGHbGHbGHbGHbGHbGHbGHcMsbGHcJQcuQcTSbGGcQwdfScaccuQcuQdbhcuQbGHaabdhcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdgwdgwdhdbJMdardhfcVYdcPdcPcVZdarcSCcSDdhoafOcSEcSFcSFcSFcSFcSFcSIcSFcSFcSFcSFcSFcSMafOdhvcTscTmdcqdeNddZdhzdhBdhAdhCdhxdhEdhDdhFcSddhHdhGdhJdhIdbIdmoaaaaabaabaaadhMdhLcTVcTXcUCcVkcVHcWxdgTdhYcsLcsLdhPcpsdhQcYicTUcsLcEGdhZdiadiadiadiadiadiadiadiadiadiadiadiadiadiadiediadiadiadiaczLcuQbPAcAUbGGdiccMscuQcuQcuQdbhcuQdfScaccuQdidbGGbGGbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgDdgudgvdhWdgvdhXdifdardfVcQjdcPdcPcWadarcTtdibdibaaacTxafOafOafOafOafOafOafOafOafOafOafOcTxaaadibdibcTtdcqddrdcqdhIdikdijdipdioditdhIdipdhIcYbdhIcYbdhIdbIdmoaaaalwalwdiudhLcXmcYgcYydavdcrdcudcxdgTcsLcsLchfdgodiqchfcYicXrdfMdhRdizdiAdiAdiAdiAdiAdiAdiCdiBdiAdiAdiAdiAdiAdiAdiEdiDcTTdiFdiJdiIdiLdiLdiLdiLdiNdiMdiOdiLdiLdiLdiLdiQcjYcuQdfcbGGdiHbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadiSdfYdfYdfYdfYdfYdiTdardiKcWbdcPdcPcWcdarcTycTzdiPaabcTxafOdjqaaaaaaaaaaaadjqaaaaaadjqafOcTxaabdiRcTCcTAdcqddrdcqaabdiUaabdiVdiWdiXdiYdiZdiYdjadiYdjadjbdjcdmoaaaalwaabdjddgSdcydczdcAdcFdcHdcIdcRdgTdjlcsLcsLcYidjmchfcYicYidjzbGHbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHbZZbZZbZZbZZbGHdjobGGcuQcTLbGGcuQcuQbZZbZZcxScuQdjAbGGdjAcuQdjCcacdjrbGHbGHbGHbGHbGHaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadardjscWbdcPdcPcWddarcTtdibdjvaaacTDcTEaaaaaaaaaaaaaaadjyaaaaaaaaacUlcTFaaadibdibcTtdcqddrdcqcQZdjBcTodjBcQZdjBcTodjBcQZdjScTodjUcQZaabdmoaaaalwaabdjEdgSdcVdczddaddcdcHdddddedjKdirdjYdjMcYicpscsLdjNdgochfcBPaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaabGHdjXcLhcuQdjPbGGcuQaaaaaaaaaaaacuQbGGbGGdbgdjQdjQdkadkbdjQaaaaabaabaabaabdjTaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadardkccQjdcPdcPcWadarcUncTmdibaaacTxafOaaaaaaaabaabaabaabaabaaaaaaafOcTxaaadibcSCcUodcqdePdcqcQZdkidkhdkkcQZdkqdkpdkscQZdkwdkudkxcQZaabdmoaaaalwaaadjEdkjddfddgddhddiddjddkddldgTdkrdgochfdgodkGchfdktdgocBNcBPcBQcBQcBQdmoaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaabGHdkFcuQcuQcQCbGGcuQcuQbZZbZZcuQcuQbGGdkvcLhdjQdkIdkHdkMdjQaaaaaaaabaabaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOdardardardardardardarcSUcTtdibaaacTxafOdjqaabaabdkzdkAdkBaabdkCaaaafOcTxaaadibcTtcSUdcqddrdcqcQZdkObbMdkOcQZdkTbbOdkTcQZdkVbdGdkVcQZaabdmoaaaalwaaadjddgSddnddoddpddqddvddyddzdgTdkPdkQdkZdkSdlacsLcYicYidlbdlddlccsLdlhdmoaaaaabaaabZZbZZbZZbGHbGHbGHbGHbGHbGHdlicJQcuQdljbGGbGGcuQbGGbGGbGGbGGcTSbGGdfPdjQdlodlkdlqdjQaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabafOafOaabaabaabalwalwcSUcSUcUpdibaaacTDcTEaaaaaaaabdledlfdlgaabaaaaaacUlcTFaaadibcUqcSUdcqddrdcqcQZdkOdlvdkOcQZdkTdlwdkTcQZdkVdlxdkVcQZaabdmoaaaalwaaadjddgSdgSdgSdlldlmdlndlydlndlmdkPdlpcsLdlAdlrdfMddHcYidlscBPcBQcBQcBQddAaabaabaaabZZdlBdlCcuQbGGdlDdlJdbgcuQdlPbGGcuQdlzbGGbGGdlLbGGbGHbGHbGHbZZbZZbGHdjQdlSdlRdlUdjQaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaabaabaaaaaaaabaabalwcSUcSUcTtdibaaacTxafOaaadlEaabdlFdlGdlHaabaabdjqafOcTxaaadibcTtcSUdcqddrdcqcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZcQZaabdmoaaaayiaaadjdaaaaaaaaadlIdlmdlVdlXdlWdlmcsLdlMcsLcsLdlNdlOcXrdmcdlQcBPaaaaaaaaaaaaaaaaabaaabZZdlZdmbdlLbGGdgybGGbGGdlLdjobGGcuQcuQcuQcuQcuQbGGbGHaabaaaaaaaaaaabdlTdlTdmddlTdlTaabaabdhcaabaabdjTaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabcSUcSCcUodibaaacTxafOaaaaaaaabaabaabaabaabaaaaaaafOcTxaaadibcUncTmdcqdeWdcqdcqdcqdcqddCdmodmodmodmodmodmodmodmodmodmodmoaabaabaabdjEaaaaaaaaadlYdlmdlndmhdlndlmdmadmidfMdfMdmldmrdmmcBPcBPcBPaaaaaaaaaaaaaaaaabaaabZZdlBdmncuQdbgbGGbGGdmpcuQdmqbGGbGGbGGbGGbGGbGGbGGbGHaabaaaaaaaaaaabaaadlTdmsdlTaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaabcSUcTtdibdmjaaacTDcTEaaaaaaaaaaabaaaaaaaaaaaaaaacUlcTFaaadibdibcTtdcqdfbdfldfjddrdfmdmoaabaabaabaabaabaabaabdmoaabaabaabaabaabaabdjEaabaabaabdlYdlmdmydmAdmzdmEaabdmacBPcBQdmtcBQcBPcBPaaaaabaaaaaaaaaaaaaaaaabaabbZZbZZbZZbGHbGHbGHbGGcuQbGHdmubGHbGHdbgbPAcLhbKlcMsbGHaabaaaaaaaaaaabaaadlTdmGdlTaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcSUcUDdbudiPaabcTxafOdjqaaaaaadjqaaaaaaaaaaaadjqafOcTxaaadiRdbQcUEdcqdfndcqdcqdcqdcqdcqdcqaaaaaaaabaaaaaaaaadmoaaaaaadmBdmBdmBdmBdmCaaaaaaaabdlYdmDdlmdmOdlmdlmaaaaabaaaaaadmFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaabGHdmbdmMbGHdmNaabbGHbGHbZZbZZcMsbGHaaaaabaaaaaaaaaaabaaaaaaddDaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUcUFcUIcUHaaacTxafOafOdcfafOafOdcfafOafOdcfafOafOcTxaaacUJcUIcUKdcqdfpdfxdfudfCdfAdfEdfDdmWdmWdmXdmWdmWdmWddEdmWdmWdmZdnadnbdnodmCaaaaaaaabdnddmodlmdnedlmddMaabaabaaaaaadngaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaabpaaaaaabGHdnqdnnbGHdnpaabaaaaabaaaaaaaabaaaaaaaabaaaaaaaaaaabaaaaaaddNaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadnscSUcSUcULaaacUMcSFcSFcUOcSFcSFcUOcSFcSFcUOcSFcSFcUQaaacULcSUcSUdcqdfpdfRdfQdgbdfTdgddgcaaaaaaaabaaaaaaaaadmodmBdmBdmBbfmbJNdnvdmCaaaaaaaabaabdmodnxdnIdnxdmoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaaaaaaaaabZZdnJbZZbZZaabdhcaaaaabaaaaaaaabaaaamWamWalwayiaabaabaabaabddNaabaabaabaabdhcamhamWamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcSUcYXcURcUHaabaabaabaabaaaaaaaaaaaaaaaaabaabaabaabcUJcUUcYXcSUdcqdgedcqdcqdcqdcqdgcdcqaabaabaabaabaabaabddObfubjbbhybkJdnGdnFdmCaaaaaaaaaaabdmoaaaaaaaaadmoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaabZZdnPbZZaaaaaaaaaaaaaabaaaaaaaabaaaamWaaaaaaaabaaaaabaaaaaaddPaaaaaaaabaaaaabaaaaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacSUcSUcURcVacVacVacVacVacVacVacVacVacVacVacVacVacUUcSUcSUcSUdgidgfdcqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddQdnTdnWdnVdobdoadofdoeaaaaaaaaaaabdmodmodmodmodmoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaabZZdogbZZaaaaaaaaaaaaaabaaaaaaaabaaaamWaaadohdohdohdohdohaabcTWaabdohdohdohdohdohaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUcSUaaadcqdcqdgpdcqdcqdcqdcqaaaaaaaaaaaaaaaaaaaaaaaacPxdnZdnZdnZdnZdojdokdocdoddolaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaabZZdombZZaaaaaaaaaaaaaaaaaaaaaaabaaaamWaabddRddTddTddTddTddUcTWddVddWddWddWddWddXaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadcqddrddrddYdoudoudowaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdnZdoydoxdoAdnZdnZdnZdnZdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabdebdoEdoEaaaaaaaaaaaaaaaaaaaaaaabaaaamWaabdoGdoGdoGdoGdoGaaacTWaaadoGdoGdoGdoGdoGaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadcqdePddrdoLdoIdoMdozaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdoNdoOdoCdoDdoQdoSdoRdoHdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaabaaaamWaaaaabaaaaabaabaabaaacTWaaaaabaaaaabaaaaabaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadoTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadcqdgqddrdeddoudoudoVaaaaaaaaaaaaaaaaaaaaaaaadjdaaadnZdoWdoYdoXdoPdoZdpcdpadpgdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaamWaaadohdohdohdohdohaabcTWaabdohdohdohdohdohaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadgGdcqdcqdcqdcqdcqdcqaaaaaaaaaaaaaaaaaaaabaabdjEaabdnZdphdpjdpidpndpkdpsdprdpbdnZaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamWaabddRddTddTddTddTddUcTWddVddWddWddWddWdeeaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabdpddpedpddpfdpudpwdpvdpydpxdpfdpfdpfdpfaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamWaabdoGdoGdoGdoGdoGaaacTWaabdoGdoGdoGdoGdoGaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpddpddpldpmdpddpfdpfdpzdpodpfdppdpqdpqdppdppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayiaaaaabaaaaabaaaaabaaadefaaaaabaaaaabaabaabaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadpddpCdpEdpDdpFdpfdpIdpHdpJdpfdpKdpAdpAdpLdppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamWaaadohdohdohdohdohaabddNaabdohdohdohdohdohaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm index 9b145bd1eb3..785d58520a0 100644 --- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm @@ -261,4 +261,4 @@ return . if("toggleadvcontrol" in href_list) advcontrol = !advcontrol - return MT_UPDATE + return TRUE diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm index c47893fc9dd..613d0f0794e 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm @@ -413,7 +413,7 @@ /obj/machinery/atmospherics/unary/vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) if("toggleadvcontrol" in href_list) advcontrol = !advcontrol - return MT_UPDATE + return TRUE if("set_id" in href_list) var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src.id_tag) as null|text), 1, MAX_MESSAGE_LEN) @@ -426,7 +426,7 @@ id_tag = newid broadcast_status() - return MT_UPDATE + return TRUE return ..() diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm index e22d00c3f80..8416a784019 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm @@ -351,7 +351,7 @@ /obj/machinery/atmospherics/unary/vent_scrubber/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) if("toggleadvcontrol" in href_list) advcontrol = !advcontrol - return MT_UPDATE + return TRUE if("set_id" in href_list) var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) @@ -365,7 +365,7 @@ id_tag = newid broadcast_status() - return MT_UPDATE + return TRUE return ..() diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 0a4ac519d9e..3b31e34b2f4 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -47,9 +47,9 @@ //End positions #define COMPONENT_EXNAME_CHANGED 1 #define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom) +#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) #define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) #define COMPONENT_ATOM_BLOCK_EXIT 1 -#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) #define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) #define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity) #define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume) @@ -106,9 +106,9 @@ #define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) #define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) +#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable) #define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable) #define COMPONENT_MOVABLE_BLOCK_UNCROSS 1 -#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable) #define COMSIG_MOVABLE_BUMP "movable_bump" //from base of atom/movable/Bump(): (/atom) #define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum) #define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index ae6943d553a..444077aacd7 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -134,4 +134,6 @@ //resistance_flags #define INDESTRUCTIBLE 64 //doesn't take damage +#define CHECK_RICOCHET_1 (1<<4) + GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 2862010d316..c2e56d8338c 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -11,6 +11,7 @@ #define isconstruct(A) (istype(A, /mob/living/simple_animal/hostile/construct)) //Objects +#define isitem(A) (istype(A, /obj/item)) #define ismecha(A) (istype(A, /obj/mecha)) diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index 2af0fd6ade8..cfc568afb66 100644 --- a/code/__DEFINES/language.dm +++ b/code/__DEFINES/language.dm @@ -11,8 +11,6 @@ //Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. #define RESTRICTED 2 // Language can only be accquired by spawning or an admin. -#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight -#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand. #define HIVEMIND 16 // Broadcast to all mobs with this language. #define NONGLOBAL 32 // Do not add to general languages list #define INNATE 64 // All mobs can be assumed to speak and understand this language (audible emotes) diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 809567a0a75..7a691c44df2 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -32,11 +32,6 @@ #define HYDRO_SPEED_MULTIPLIER 1 -// multitool_topic() shit -#define MT_ERROR -1 -#define MT_UPDATE 1 -#define MT_REINIT 2 - //Modular computer/NTNet defines //Modular computer part defines diff --git a/code/__DEFINES/math.dm b/code/__DEFINES/math.dm index dd0045a2105..7115cc677f6 100644 --- a/code/__DEFINES/math.dm +++ b/code/__DEFINES/math.dm @@ -38,6 +38,10 @@ #define SHORT_REAL_LIMIT 16777216 +// Real modulus that handles decimals +#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) ) + + //"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks //percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio) //collapsed to percent_of_tick_used * tick_lag @@ -53,3 +57,10 @@ // round() acts like floor(x, 1) by default but can't handle other values #define FLOOR(x, y) ( round((x) / (y)) * (y) ) + + +// Will filter out extra rotations and negative rotations +// E.g: 540 becomes 180. -180 becomes 180. +#define SIMPLIFY_DEGREES(degrees) (MODULUS((degrees), 360)) + +#define GET_ANGLE_OF_INCIDENCE(face, input) (MODULUS((face) - (input), 360)) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index f8c11dd6a69..c7380d9f402 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -455,7 +455,7 @@ proc/checkhtml(var/t) // Pencode -/proc/pencode_to_html(text, mob/user, obj/item/pen/P = null, format = 1, sign = 1, fields = 1, deffont = PEN_FONT, signfont = SIGNFONT, crayonfont = CRAYON_FONT) +/proc/pencode_to_html(text, mob/user, obj/item/pen/P = null, format = 1, sign = 1, fields = 1, deffont = PEN_FONT, signfont = SIGNFONT, crayonfont = CRAYON_FONT, no_font = FALSE) text = replacetext(text, "\[b\]", "") text = replacetext(text, "\[/b\]", "") text = replacetext(text, "\[i\]", "") @@ -509,10 +509,12 @@ proc/checkhtml(var/t) text = replacetext(text, "\[cell\]", "") text = replacetext(text, "\[logo\]", "") text = replacetext(text, "\[time\]", "[station_time_timestamp()]") // TO DO - if(P) - text = "[text]" - else - text = "[text]" + if(!no_font) + if(P) + text = "[text]" + else + text = "[text]" + text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN) return text diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 9e8b9b9c3a6..e36d5c027f5 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -7,6 +7,8 @@ // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) + if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT) + return return /obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby! @@ -28,9 +30,12 @@ return I.attack(src, user) /obj/item/proc/attack(mob/living/M, mob/living/user, def_zone) + SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user) if(flags & (NOBLUDGEON)) return 0 - + if(check_martial_counter(M, user)) + return 0 if(can_operate(M)) //Checks if mob is lying down on table for surgery if(istype(src,/obj/item/robot_parts))//popup override for direct attach if(!attempt_initiate_surgery(src, M, user,1)) @@ -74,6 +79,8 @@ //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) + if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ) + return if(flags & (NOBLUDGEON)) return user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm new file mode 100644 index 00000000000..e9b6bb6e42a --- /dev/null +++ b/code/datums/components/squeak.dm @@ -0,0 +1,88 @@ +// Squeak component ported over from tg + +/datum/component/squeak + var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1) + var/list/override_squeak_sounds + var/squeak_chance = 100 + var/volume = 30 + + // This is so shoes don't squeak every step + var/steps = 0 + var/step_delay = 1 + + // This is to stop squeak spam from inhand usage + var/last_use = 0 + var/use_delay = 20 + +/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak) + if(ismovableatom(parent)) + RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak) + RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed) + RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react) + if(isitem(parent)) + RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) + if(istype(parent, /obj/item/clothing/shoes)) + RegisterSignal(parent, COMSIG_SHOES_STEP_ACTION, .proc/step_squeak) + + override_squeak_sounds = custom_sounds + if(chance_override) + squeak_chance = chance_override + if(volume_override) + volume = volume_override + if(isnum(step_delay_override)) + step_delay = step_delay_override + if(isnum(use_delay_override)) + use_delay = use_delay_override + +/datum/component/squeak/proc/play_squeak() + if(prob(squeak_chance)) + if(!override_squeak_sounds) + playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) + else + playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) + +/datum/component/squeak/proc/step_squeak() + if(steps > step_delay) + play_squeak() + steps = 0 + else + steps++ + +/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot) + RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE) + +/datum/component/squeak/proc/on_drop(datum/source, mob/user) + UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING) + +/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM) + if(isitem(AM)) + var/obj/item/I = AM + if(I.flags & ABSTRACT) + return + else if(istype(AM, /obj/item/projectile)) + var/obj/item/projectile/P = AM + if(P.original != parent) + return + var/atom/current_parent = parent + if(isturf(current_parent.loc)) + play_squeak() + +/datum/component/squeak/proc/use_squeak() + if(last_use + use_delay < world.time) + last_use = world.time + play_squeak() + +/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/holder, obj/machinery/disposal/source) + //We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted + RegisterSignal(holder, COMSIG_ATOM_DIR_CHANGE, .proc/holder_dir_change) + +/datum/component/squeak/proc/holder_dir_change(datum/source, old_dir, new_dir) + //If the dir changes it means we're going through a bend in the pipes, let's pretend we bumped the wall + if(old_dir != new_dir) + play_squeak() \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 6f1fb59e8f8..18f229bdc4c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -58,6 +58,10 @@ var/rev_cooldown = 0 + var/isholy = FALSE // is this person a chaplain or admin role allowed to use bibles + var/isblessed = FALSE // is this person blessed by a chaplain? + var/num_blessed = 0 // for prayers + // the world.time since the mob has been brigged, or -1 if not at all var/brigged_since = -1 var/suicided = FALSE @@ -375,9 +379,9 @@ /** SILICON ***/ if(issilicon(current)) sections["silicon"] = memory_edit_silicon() - /* - This prioritizes antags relevant to the current round to make them appear at the top of the panel. - Traitorchan and traitorvamp are snowflaked in because they have multiple sections. + /* + This prioritizes antags relevant to the current round to make them appear at the top of the panel. + Traitorchan and traitorvamp are snowflaked in because they have multiple sections. */ if(ticker.mode.config_tag == "traitorchan") if(sections["traitor"]) diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index bf296acd589..2761a8063ee 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -64,34 +64,14 @@ if(istype(R)) R.set_frequency(SYND_FREQ) -/datum/outfit/admin/syndicate/infiltrator + +/datum/outfit/admin/syndicate_infiltrator name = "Syndicate Infiltrator" - uniform = /obj/item/clothing/under/chameleon - glasses = /obj/item/clothing/glasses/hud/security/chameleon - shoes = /obj/item/clothing/shoes/syndigaloshes - r_pocket = null - pda = /obj/item/pda +/datum/outfit/admin/syndicate_infiltrator/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + . = H.equip_syndicate_infiltrator(0, 20, FALSE) + H.sec_hud_set_ID() - backpack_contents = list( - /obj/item/storage/box/engineer = 1, - /obj/item/flashlight = 1, - /obj/item/reagent_containers/food/snacks/syndidonkpocket = 1 - ) - -/datum/outfit/admin/syndicate/infiltrator/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) - . = ..() - if(visualsOnly) - return - if(H.gloves) - H.gloves.name = "black gloves" - - var/obj/item/implant/uplink/U = new /obj/item/implant/uplink(H) - U.implant(H) - U.hidden_uplink.uses = uplink_uses - - var/obj/item/implant/dust/D = new /obj/item/implant/dust(H) - D.implant(H) /datum/outfit/admin/syndicate/operative name = "Syndicate Nuclear Operative" @@ -126,17 +106,20 @@ var/obj/item/implant/explosive/E = new(H) E.implant(H) + /datum/outfit/admin/syndicate/operative/freedom name = "Syndicate Freedom Operative" suit = /obj/item/clothing/suit/space/hardsuit/syndi/freedom head = /obj/item/clothing/head/helmet/space/hardsuit/syndi/freedom + /datum/outfit/admin/syndicate_strike_team name = "Syndicate Strike Team" /datum/outfit/admin/syndicate_strike_team/equip(mob/living/carbon/human/H, visualsOnly = FALSE) return H.equip_syndicate_commando() + /datum/outfit/admin/syndicate/officer name = "Syndicate Officer" @@ -156,7 +139,9 @@ /obj/item/clothing/shoes/magboots/syndie/advance = 1, /obj/item/lighter/zippo/gonzofist = 1 ) - + implants = list( + /obj/item/implant/dust + ) id_icon = "commander" id_access = "Syndicate Operative Leader" @@ -169,8 +154,17 @@ U.implant(H) U.hidden_uplink.uses = 500 - var/obj/item/implant/dust/D = new(H) - D.implant(H) + +/datum/outfit/admin/syndicate/spy + name = "Syndicate Spy" + uniform = /obj/item/clothing/under/suit_jacket/really_black + shoes = /obj/item/clothing/shoes/syndigaloshes/black + uplink_uses = 40 + id_access = "Syndicate Agent" + + implants = list( + /obj/item/implant/dust + ) /datum/outfit/admin/nt_vip @@ -196,7 +190,7 @@ var/obj/item/card/id/I = H.wear_id if(istype(I)) apply_to_card(I, H, get_centcom_access("VIP Guest"), "VIP Guest") - + H.sec_hud_set_ID() /datum/outfit/admin/nt_navy_captain name = "NT Navy Captain" @@ -228,6 +222,7 @@ var/obj/item/card/id/I = H.wear_id if(istype(I)) apply_to_card(I, H, get_centcom_access("Nanotrasen Navy Captain"), "Nanotrasen Navy Captain") + H.sec_hud_set_ID() /datum/outfit/admin/nt_diplomat name = "NT Diplomat" @@ -258,39 +253,35 @@ var/obj/item/card/id/I = H.wear_id if(istype(I)) apply_to_card(I, H, get_centcom_access("Nanotrasen Navy Representative"), "Nanotrasen Diplomat") - + // Will show as ? on sec huds, as this is not a recognized rank. /datum/outfit/admin/nt_undercover name = "NT Undercover Operative" - // Disguised NT special forces, sent to quietly eliminate mutinous people in high positions (e.g: captain) + // Disguised NT special forces, sent to quietly eliminate or keep tabs on people in high positions (e.g: captain) - uniform = /obj/item/clothing/under/chameleon + uniform = /obj/item/clothing/under/color/black back = /obj/item/storage/backpack belt = /obj/item/storage/belt/utility/full/multitool gloves = /obj/item/clothing/gloves/combat - shoes = /obj/item/clothing/shoes/syndigaloshes - l_ear = /obj/item/radio/headset/heads/captain - id = /obj/item/card/id/syndicate + shoes = /obj/item/clothing/shoes/syndigaloshes/black + l_ear = /obj/item/radio/headset/centcom + id = /obj/item/card/id pda = /obj/item/pda backpack_contents = list( /obj/item/storage/box/engineer = 1, /obj/item/flashlight = 1, - /obj/item/gun/projectile/automatic/proto = 1, // NT saber SMG - /obj/item/suppressor = 1, // silencer for SMG - /obj/item/ammo_box/magazine/smgm9mm = 3, // SMG ammo - /obj/item/door_remote/omni = 1, - /obj/item/implanter/mindshield = 1, // not implanted by default, as that would make them suspicious - /obj/item/implanter/storage = 1 // do not auto-implant this, that causes a bug + /obj/item/pinpointer/crew = 1 ) implants = list( /obj/item/implant/dust ) cybernetic_implants = list( + /obj/item/organ/internal/cyberimp/eyes/shield, /obj/item/organ/internal/cyberimp/eyes/hud/security, /obj/item/organ/internal/cyberimp/eyes/xray, - /obj/item/organ/internal/cyberimp/brain/anti_drop, /obj/item/organ/internal/cyberimp/brain/anti_stun, - /obj/item/organ/internal/cyberimp/chest/nutriment/plus + /obj/item/organ/internal/cyberimp/chest/nutriment/plus, + /obj/item/organ/internal/cyberimp/arm/combat/centcom ) /datum/outfit/admin/nt_undercover/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -300,16 +291,14 @@ var/obj/item/card/id/I = H.wear_id if(istype(I)) - apply_to_card(I, H, get_all_accesses(), "Civilian") - I.icon_state = "deathsquad" - + apply_to_card(I, H, get_centcom_access("NT Undercover Operative"), "Civilian") + H.sec_hud_set_ID() // Force it to show as Civ on sec huds var/obj/item/radio/R = H.l_ear if(istype(R)) R.name = "radio headset" R.icon_state = "headset" - /datum/outfit/admin/death_commando name = "NT Death Commando" @@ -321,11 +310,15 @@ uniform = /obj/item/clothing/under/pirate back = /obj/item/storage/backpack/satchel + belt = /obj/item/storage/belt/utility/full/multitool + gloves = /obj/item/clothing/gloves/combat shoes = /obj/item/clothing/shoes/brown + l_ear = /obj/item/radio/headset id = /obj/item/card/id r_hand = /obj/item/melee/energy/sword/pirate backpack_contents = list( - /obj/item/storage/box/survival = 1 + /obj/item/storage/box/survival = 1, + /obj/item/flashlight = 1 ) /datum/outfit/admin/pirate/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -405,7 +398,11 @@ backpack_contents = list( /obj/item/storage/box/survival = 1, /obj/item/flashlight = 1, - /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana = 1 + /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana = 1, + /obj/item/grenade/clown_grenade = 1, + /obj/item/melee/baton/cattleprod = 1, + /obj/item/stock_parts/cell/super = 1, + /obj/item/bikehorn/rubberducky = 1 ) /datum/outfit/admin/tunnel_clown/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -436,8 +433,10 @@ /obj/item/storage/box/survival = 1, /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing = 1, /obj/item/toy/crayon/mime = 1, - /obj/item/storage/box/syndie_kit/caneshotgun = 1, - /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath = 2, + /obj/item/gun/projectile/automatic/pistol = 1, + /obj/item/ammo_box/magazine/m10mm = 1, + /obj/item/suppressor = 1, + /obj/item/card/emag = 1, /obj/item/radio/uplink = 1, /obj/item/reagent_containers/food/snacks/syndidonkpocket = 1, /obj/item/flashlight = 1 @@ -463,6 +462,7 @@ var/obj/item/card/id/I = H.wear_id if(istype(I)) apply_to_card(I, H, list(access_mime, access_theatre, access_maint_tunnels), "Mime") + H.sec_hud_set_ID() /datum/outfit/admin/greytide name = "Greytide" @@ -538,6 +538,45 @@ if(istype(I)) apply_to_card(I, H, list(access_maint_tunnels), "Legit Xenomorph") + + +/datum/outfit/admin/musician + name = "Musician" + + uniform = /obj/item/clothing/under/singerb + back = /obj/item/storage/backpack + shoes = /obj/item/clothing/shoes/singerb + gloves = /obj/item/clothing/gloves/color/white + l_ear = /obj/item/radio/headset + r_ear = /obj/item/clothing/ears/headphones + pda = /obj/item/pda + id = /obj/item/card/id + backpack_contents = list( + /obj/item/storage/box/survival = 1, + /obj/item/flashlight = 1, + /obj/item/instrument/violin = 1, + /obj/item/instrument/piano_synth = 1, + /obj/item/instrument/guitar = 1, + /obj/item/instrument/eguitar = 1, + /obj/item/instrument/accordion = 1, + /obj/item/instrument/saxophone = 1, + /obj/item/instrument/trombone = 1, + /obj/item/instrument/harmonica = 1 + ) + +/datum/outfit/admin/musician/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + . = ..() + if(visualsOnly) + return + + var/obj/item/card/id/I = H.wear_id + if(istype(I)) + apply_to_card(I, H, list(access_maint_tunnels), "Bard") + + var/obj/item/clothing/ears/headphones/P = r_ear + if(istype(P)) + P.attack_self(H) // activate them, display musical notes effect + /datum/outfit/admin/soviet gloves = /obj/item/clothing/gloves/combat @@ -594,7 +633,6 @@ l_ear = /obj/item/radio/headset/syndicate r_ear = null glasses = /obj/item/clothing/glasses/thermal/eyepatch - id = null l_pocket = null r_pocket = null suit_store = null @@ -930,7 +968,8 @@ uniform = /obj/item/clothing/under/syndicate/combat suit = /obj/item/clothing/suit/space/hardsuit/singuloth - back = /obj/item/twohanded/knighthammer + back = /obj/item/storage/backpack/satchel + l_hand = /obj/item/twohanded/knighthammer belt = /obj/item/claymore/ceremonial gloves = /obj/item/clothing/gloves/combat shoes = /obj/item/clothing/shoes/magboots @@ -940,6 +979,10 @@ glasses = /obj/item/clothing/glasses/meson/cyber id = /obj/item/card/id suit_store = /obj/item/tank/oxygen + backpack_contents = list( + /obj/item/storage/box/survival = 1, + /obj/item/flashlight = 1 + ) /datum/outfit/admin/singuloth_knight/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) . = ..() @@ -950,95 +993,14 @@ if(istype(I)) apply_to_card(I, H, get_all_accesses(), "Singuloth Knight") -/datum/outfit/admin/assassin - name = "Syndicate Assassin" - - uniform = /obj/item/clothing/under/suit_jacket - suit = /obj/item/clothing/suit/wcoat - back = /obj/item/storage/backpack - gloves = /obj/item/clothing/gloves/color/black - shoes = /obj/item/clothing/shoes/black - l_ear = /obj/item/radio/headset/syndicate - glasses = /obj/item/clothing/glasses/sunglasses - id = /obj/item/card/id/syndicate - l_pocket = /obj/item/melee/energy/sword/saber - l_hand = /obj/item/storage/secure/briefcase/reaper - pda = /obj/item/pda/heads - backpack_contents = list( - /obj/item/storage/box/survival = 1, - /obj/item/flashlight = 1 - ) - implants = list( - /obj/item/implant/dust - ) - -/datum/outfit/admin/assassin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) - . = ..() - if(visualsOnly) - return - - var/obj/item/pda/PDA = H.wear_pda - if(istype(PDA)) - PDA.owner = H.real_name - PDA.ownjob = "Reaper" - PDA.name = "PDA-[H.real_name] ([PDA.ownjob])" - - var/obj/item/card/id/I = H.wear_id - if(istype(I)) - apply_to_card(I, H, get_all_accesses(), "Reaper", "syndie") - -/datum/outfit/admin/spy - name = "Spy" - - uniform = /obj/item/clothing/under/suit_jacket/really_black - back = /obj/item/storage/backpack - gloves = /obj/item/clothing/gloves/combat - shoes = /obj/item/clothing/shoes/black - l_ear = /obj/item/radio/headset/syndicate - glasses = /obj/item/clothing/glasses/hud/security/chameleon - id = /obj/item/card/id/syndicate - l_pocket = /obj/item/melee/energy/sword/saber - r_pocket = /obj/item/pen/sleepy - pda = /obj/item/pda/heads - backpack_contents = list( - /obj/item/storage/box/survival = 1, - /obj/item/gun/projectile/automatic/pistol = 1, - /obj/item/suppressor = 1, - /obj/item/card/emag = 1, - /obj/item/flashlight = 1, - /obj/item/implanter/storage = 1 // do not auto-implant this, that causes a bug - ) - implants = list( - /obj/item/implant/dust - ) - -/datum/outfit/admin/spy/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) - . = ..() - if(visualsOnly) - return - - var/obj/item/clothing/gloves/combat/G = H.gloves - if(istype(G)) - G.name = "black gloves" - - var/obj/item/pda/PDA = H.wear_pda - if(istype(PDA)) - PDA.owner = H.real_name - PDA.ownjob = "Spy" - PDA.name = "PDA-[H.real_name] ([PDA.ownjob])" - - var/obj/item/card/id/I = H.wear_id - if(istype(I)) - apply_to_card(I, H, list(access_maint_tunnels), "Spy", "syndie") - /datum/outfit/admin/dark_lord name = "Dark Lord" uniform = /obj/item/clothing/under/color/black suit = /obj/item/clothing/suit/hooded/chaplain_hoodie back = /obj/item/storage/backpack - gloves = /obj/item/clothing/gloves/color/black - shoes = /obj/item/clothing/shoes/black + gloves = /obj/item/clothing/gloves/combat + shoes = /obj/item/clothing/shoes/syndigaloshes/black l_ear = /obj/item/radio/headset/syndicate id = /obj/item/card/id/syndicate l_hand = /obj/item/twohanded/dualsaber/red @@ -1062,6 +1024,55 @@ apply_to_card(I, H, get_all_accesses(), "Dark Lord", "syndie") +/datum/outfit/admin/ancient_vampire + name = "Ancient Vampire" + + uniform = /obj/item/clothing/under/victsuit/red + suit = /obj/item/clothing/suit/draculacoat + back = /obj/item/storage/backpack + gloves = /obj/item/clothing/gloves/combat + shoes = /obj/item/clothing/shoes/syndigaloshes/black + l_ear = /obj/item/radio/headset/syndicate + id = /obj/item/card/id + backpack_contents = list( + /obj/item/storage/box/survival = 1, + /obj/item/flashlight = 1, + /obj/item/clothing/under/color/black = 1 + ) + +/datum/outfit/admin/ancient_vampire/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + . = ..() + if(visualsOnly) + return + + var/obj/item/clothing/suit/hooded/chaplain_hoodie/C = new(H.loc) + if(istype(C)) + C.name = "ancient robes" + C.hood.name = "ancient hood" + H.equip_to_slot_or_del(C, slot_in_backpack) + + var/obj/item/card/id/I = H.wear_id + if(istype(I)) + apply_to_card(I, H, get_all_accesses(), "Ancient One", "data") + + if(H.mind) + if(!H.mind.vampire) + H.make_vampire() + if(H.mind.vampire) + H.mind.vampire.bloodusable = 9999 + H.mind.vampire.bloodtotal = 9999 + H.mind.vampire.check_vampire_upgrade(0) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/bats) + to_chat(H, "You have gained the ability to shapeshift into bat form. This is a weak form with no abilities, only useful for stealth.") + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shapeshift/hellhound) + to_chat(H, "You have gained the ability to shapeshift into lesser hellhound form. This is a combat form with different abilities, tough but not invincible. It can regenerate itself over time by resting.") + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/raise_vampires) + to_chat(H, "You have gained the ability to Raise Vampires. This extremely powerful AOE ability affects all humans near you. Vampires/thralls are healed. Corpses are raised as vampires. Others are stunned, then brain damaged, then killed.") + H.dna.SetSEState(JUMPBLOCK, 1) + genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED) + H.update_mutations() + H.gene_stability = 100 + /datum/outfit/admin/wizard name = "Blue Wizard" uniform = /obj/item/clothing/under/color/lightpurple diff --git a/code/datums/spells/chaplain.dm b/code/datums/spells/chaplain.dm new file mode 100644 index 00000000000..f9c2641c50e --- /dev/null +++ b/code/datums/spells/chaplain.dm @@ -0,0 +1,73 @@ + +/obj/effect/proc_holder/spell/targeted/chaplain_bless + name = "Bless" + desc = "Blesses a single person." + + school = "transmutation" + charge_max = 60 + clothes_req = 0 + invocation = "none" + invocation_type = "none" + + max_targets = 1 + include_user = 0 + humans_only = 1 + + range = 1 + cooldown_min = 20 + action_icon_state = "shield" + + +/obj/effect/proc_holder/spell/targeted/chaplain_bless/cast(list/targets, mob/living/user = usr, distanceoverride) + + if(!istype(user)) + to_chat(user, "Somehow, you are not a living mob. This should never happen. Report this bug.") + revert_cast() + return + + if(!user.mind) + to_chat(user, "Somehow, you are mindless. This should never happen. Report this bug.") + revert_cast() + return + + if(!user.mind.isholy) + to_chat(user, "Somehow, you are not holy enough to use this ability. This should never happen. Report this bug.") + revert_cast() + return + + var/mob/living/carbon/human/target = targets[range] + + if(!istype(target)) + to_chat(user, "No target.") + revert_cast() + return + + if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. + to_chat(user, "[target] is too far away!") + revert_cast() + return + + if(!target.mind) + to_chat(user, "[target] appears to be catatonic. Your blessing would have no effect.") + revert_cast() + return + + if(!target.ckey) + to_chat(user, "[target] appears to be too out of it to benefit from this.") + revert_cast() + return + + if(target.stat == DEAD) + to_chat(user, "[target] is already dead. There is no point.") + revert_cast() + return + + spawn(0) // allows cast to complete even if recipient ignores the prompt + if(alert(target, "[user] wants to bless you, in the name of [user.p_their()] religion. Accept?", "Accept Blessing?", "Yes", "No") == "Yes") // prevents forced conversions + user.visible_message("[user] starts blessing [target] in the name of [ticker.Bible_deity_name].", "You start blessing [target] in the name of [ticker.Bible_deity_name].") + if(do_after(user, 150, target = target)) + user.visible_message("[user] has blessed [target] in the name of [ticker.Bible_deity_name].", "You have blessed [target] in the name of [ticker.Bible_deity_name].") + if(!target.mind.isblessed) + target.mind.isblessed = TRUE + user.mind.num_blessed++ + diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm index 19b30674bf6..7f1ca22b709 100644 --- a/code/datums/spells/mime.dm +++ b/code/datums/spells/mime.dm @@ -1,5 +1,5 @@ /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall - name = "Invisible wall" + name = "Invisible Wall" desc = "The mime's performance transmutates into physical reality." school = "mime" panel = "Mime" @@ -12,7 +12,7 @@ range = 0 cast_sound = null human_req = 1 - + action_icon_state = "mime" action_background_icon_state = "bg_mime" @@ -60,3 +60,107 @@ to_chat(H, "You make a vow of silence.") else to_chat(H, "You break your vow of silence.") + +//Advanced Mimery traitor item spells + +/obj/effect/proc_holder/spell/targeted/forcewall/mime + name = "Invisible Greater Wall" + desc = "Form an invisible three tile wide blockade." + school = "mime" + panel = "Mime" + wall_type = /obj/effect/forcefield/mime/advanced + invocation_type = "emote" + invocation_emote_self = "You form a blockade in front of yourself." + charge_max = 600 + sound = null + clothes_req = FALSE + range = -1 + include_user = TRUE + + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + +/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click() + if(usr && usr.mind) + if(!usr.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first.") + return + invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]." + else + invocation_type ="none" + ..() + +/obj/effect/proc_holder/spell/targeted/mime/fingergun + name = "Finger Gun" + desc = "Shoot stunning, invisible bullets out of your fingers! 6 bullets available per cast. Use your fingers to holster them manually." + school = "mime" + panel = "Mime" + clothes_req = 0 + charge_max = 600 + range = -1 + include_user = 1 + human_req = 1 + + action_icon_state = "fingergun" + action_background_icon_state = "bg_mime" + var/gun = /obj/item/gun/projectile/revolver/fingergun + +/obj/effect/proc_holder/spell/targeted/mime/fingergun/cast(list/targets, mob/user = usr) + for(var/mob/living/carbon/human/C in targets) + if(!istype(C.get_active_hand(), gun) && !istype(C.get_inactive_hand(), gun)) + to_chat(user, "You draw your fingers!") + C.drop_item() + C.put_in_hands(new gun) + else + to_chat(user, "Holster your fingers first.") + revert_cast(user) + +/obj/effect/proc_holder/spell/targeted/mime/fingergun/fake + desc = "Pretend you're shooting bullets out of your fingers! 6 bullets available per cast. Use your fingers to holster them manually." + gun = /obj/item/gun/projectile/revolver/fingergun/fake + +// Mime Spellbooks + +/obj/item/spellbook/oneuse/mime + spell = /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall + spellname = "Invisible Wall" + name = "Miming Manual : " + desc = "It contains various pictures of mimes mid-performance, aswell as some illustrated tutorials." + icon_state = "bookmime" + +/obj/item/spellbook/oneuse/mime/attack_self(mob/user) + var/obj/effect/proc_holder/spell/S = new spell + for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list) + if(knownspell.type == S.type) + if(user.mind) + to_chat(user, "You've already read this one.") + return + if(used) + recoil(user) + else + user.mind.AddSpell(S) + to_chat(user, "You flip through the pages. Your understanding of the boundaries of reality increases. You can cast [spellname]!") + user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).") + onlearned(user) + +/obj/item/spellbook/oneuse/mime/recoil(mob/user) + to_chat(user, "You flip through the pages. Nothing of interest to you.") + +/obj/item/spellbook/oneuse/mime/onlearned(mob/user) + used = 1 + if(!locate(/obj/effect/proc_holder/spell/targeted/mime/speak) in user.mind.spell_list) //add vow of silence if not known by user + user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak) + to_chat(user, "You have learned how to use silence to improve your performance.") + +/obj/item/spellbook/oneuse/mime/fingergun + spell = /obj/effect/proc_holder/spell/targeted/mime/fingergun + spellname = "Finger Gun" + desc = "It contains illustrations of guns and how to mime them." + +/obj/item/spellbook/oneuse/mime/fingergun/fake + spell = /obj/effect/proc_holder/spell/targeted/mime/fingergun/fake + +/obj/item/spellbook/oneuse/mime/greaterwall + spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime + spellname = "Invisible Greater Wall" + desc = "It contains illustrations of the great walls of human history." \ No newline at end of file diff --git a/code/datums/spells/shapeshift.dm b/code/datums/spells/shapeshift.dm index a814c84fa59..5dd388779ce 100644 --- a/code/datums/spells/shapeshift.dm +++ b/code/datums/spells/shapeshift.dm @@ -79,4 +79,36 @@ shapeshift_type = /mob/living/simple_animal/hostile/megafauna/dragon/lesser list/current_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser) list/current_casters = list() - list/possible_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser) \ No newline at end of file + list/possible_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser) + +/obj/effect/proc_holder/spell/targeted/shapeshift/bats + name = "Bat Form" + desc = "Take on the shape of a swarm of bats." + invocation = "none" + invocation_type = "none" + action_icon_state = "vampire_bats" + + shapeshift_type = /mob/living/simple_animal/hostile/scarybat/batswarm + list/current_shapes = list(/mob/living/simple_animal/hostile/scarybat/batswarm) + list/current_casters = list() + list/possible_shapes = list(/mob/living/simple_animal/hostile/scarybat/batswarm) + +/obj/effect/proc_holder/spell/targeted/shapeshift/hellhound + name = "Lesser Hellhound Form" + desc = "Take on the shape of a Hellhound." + invocation = "none" + invocation_type = "none" + action_background_icon_state = "bg_demon" + action_icon_state = "glare" + + shapeshift_type = /mob/living/simple_animal/hostile/hellhound + list/current_shapes = list(/mob/living/simple_animal/hostile/hellhound) + list/current_casters = list() + list/possible_shapes = list(/mob/living/simple_animal/hostile/hellhound) + +/obj/effect/proc_holder/spell/targeted/shapeshift/hellhound/greater + name = "Greater Hellhound Form" + shapeshift_type = /mob/living/simple_animal/hostile/hellhound/greater + list/current_shapes = list(/mob/living/simple_animal/hostile/hellhound/greater) + list/current_casters = list() + list/possible_shapes = list(/mob/living/simple_animal/hostile/hellhound/greater) \ No newline at end of file diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index 0816659e414..dffde794d51 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -166,6 +166,32 @@ action_icon_state = "shield" cast_sound = 'sound/magic/ForceWall.ogg' +/obj/effect/proc_holder/spell/targeted/forcewall + name = "Greater Forcewall" + desc = "Create a magical barrier that only you can pass through." + + school = "transmutation" + charge_max = 100 + clothes_req = FALSE + invocation = "TARCOL MINTI ZHERI" + invocation_type = "shout" + sound = 'sound/magic/ForceWall.ogg' + action_icon_state = "shield" + range = -1 + include_user = TRUE + cooldown_min = 50 //12 deciseconds reduction per rank + var/wall_type = /obj/effect/forcefield/wizard + +/obj/effect/proc_holder/spell/targeted/forcewall/cast(list/targets,mob/user = usr) + new wall_type(get_turf(user),user) + if(user.dir == SOUTH || user.dir == NORTH) + new wall_type(get_step(user, EAST),user) + new wall_type(get_step(user, WEST),user) + else + new wall_type(get_step(user, NORTH),user) + new wall_type(get_step(user, SOUTH),user) + + /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop name = "Stop Time" desc = "This spell stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen." diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 4d8bd9432f4..89108071b09 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -737,6 +737,15 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine cost = 10 containername = "advanced first aid kits crate" +/datum/supply_packs/medical/firstaidmachine + name = "Machine First Aid Kits Crate" + contains = list(/obj/item/storage/firstaid/machine, + /obj/item/storage/firstaid/machine, + /obj/item/storage/firstaid/machine, + /obj/item/storage/firstaid/machine) + cost = 10 + containername = "machine first aid kits crate" + /datum/supply_packs/medical/firstaibrute name = "Brute Treatment Kits Crate" contains = list(/obj/item/storage/firstaid/brute, diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index d2d56fa9f3b..8d871447cd3 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -2,6 +2,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /proc/get_uplink_items(var/job = null) var/list/uplink_items = list() + var/list/sales_items = list() + var/newreference = 1 if(!uplink_items.len) var/list/last = list() @@ -22,6 +24,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) uplink_items[I.category] = list() uplink_items[I.category] += I + if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1) + sales_items += I for(var/datum/uplink_item/I in last) if(!uplink_items[I.category]) @@ -29,6 +33,30 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) uplink_items[I.category] += I + for(var/i in 1 to 3) + var/datum/uplink_item/I = pick_n_take(sales_items) + var/datum/uplink_item/A = new I.type + var/discount = 0.5 + A.limited_stock = 1 + I.refundable = FALSE + A.refundable = FALSE + if(A.cost >= 20) + discount *= 0.5 // If the item costs 20TC or more, it's only 25% off. + A.cost = max(round(A.cost * (1-discount)),1) + A.category = "Discounted Gear" + A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)" + A.job = null // If you get a job specific item selected, actually lets you buy it in the discount section + A.reference = "DIS[newreference]" + A.desc += " Limit of [A.limited_stock] per uplink. Normally costs [initial(A.cost)] TC." + A.surplus = 0 // stops the surplus crate potentially giving out a bit too much + A.item = I.item + newreference++ + + if(!uplink_items[A.category]) + uplink_items[A.category] = list() + + uplink_items[A.category] += A + return uplink_items /datum/nano_item_lists @@ -51,22 +79,27 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something. var/list/job = null var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it) + var/cant_discount = FALSE + var/limited_stock = -1 // Can you only buy so many? -1 allows for infinite purchases var/hijack_only = FALSE //can this item be purchased only during hijackings? var/refundable = FALSE var/refund_path = null // Alternative path for refunds, in case the item purchased isn't what is actually refunded (ie: holoparasites). var/refund_amount // specified refund amount in case there needs to be a TC penalty for refunds. /datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/uplink/U) + if(hijack_only) if(!(locate(/datum/objective/hijack) in usr.mind.objectives)) to_chat(usr, "The Syndicate lacks resources to provide you with this item.") return + if(item) U.uses -= max(cost, 0) U.used_TC += cost feedback_add_details("traitor_uplink_items_bought", name) return new item(loc) + /datum/uplink_item/proc/description() if(!desc) // Fallback description @@ -97,7 +130,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) if(I) if(ishuman(user)) var/mob/living/carbon/human/A = user - log_game("[key_name(user)] purchased [name]") + if(limited_stock > 0) + log_game("[key_name(user)] purchased [name]. [name] was discounted to [cost].") + else + log_game("[key_name(user)] purchased [name].") A.put_in_any_hand_if_possible(I) if(istype(I,/obj/item/storage/box/) && I.contents.len>0) @@ -117,8 +153,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) */ //Work in Progress, job specific antag tools +//Discounts (dynamically filled above) + +/datum/uplink_item/discounts + category = "Discounted Gear" + +//Job specific gear + /datum/uplink_item/jobspecific category = "Job Specific Tools" + cant_discount = TRUE //Clown /datum/uplink_item/jobspecific/clowngrenade @@ -146,6 +190,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 10 job = list("Mime") +/datum/uplink_item/jobspecific/mimery + name = "Guide to Advanced Mimery Series" + desc = "Contains two manuals to teach you advanced Mime skills. You will be able to shoot stunning bullets out of your fingers, and create large walls that can block an entire hallway!" + reference = "AM" + item = /obj/item/storage/box/syndie_kit/mimery + cost = 10 + job = list("Mime") + //Chef /datum/uplink_item/jobspecific/specialsauce name = "Chef Excellence's Special Sauce" @@ -556,6 +608,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) gamemodes = list(/datum/game_mode/nuclear) surplus = 0 refundable = TRUE + cant_discount = TRUE /datum/uplink_item/dangerous/foamsmg name = "Toy Submachine Gun" @@ -586,12 +639,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/dangerous/guardian name = "Holoparasites" - desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel." + desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel. \ + The holoparasites are unable to incoporate themselves to changeling and vampire agents." item = /obj/item/storage/box/syndie_kit/guardian excludefrom = list(/datum/game_mode/nuclear) cost = 12 refund_path = /obj/item/guardiancreator/tech/choose refundable = TRUE + cant_discount = TRUE // Ammunition @@ -755,11 +810,21 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/stealthy_weapons/martialarts name = "Martial Arts Scroll" desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \ - deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry." + deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry. \ + Unable to be understood by vampire and changeling agents." reference = "SCS" item = /obj/item/sleeping_carp_scroll cost = 17 excludefrom = list(/datum/game_mode/nuclear) + refundable = TRUE + cant_discount = TRUE + +/datum/uplink_item/stealthy_weapons/cqc + name = "CQC Manual" + desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage, but cannot be used alongside Gloves of the North Star." + reference = "CQC" + item = /obj/item/CQC_manual + cost = 9 /datum/uplink_item/stealthy_weapons/throwingweapons name = "Box of Throwing Weapons" @@ -1183,8 +1248,17 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) sends you a small beacon that will teleport the larger beacon to your location upon activation." reference = "SNGB" item = /obj/item/radio/beacon/syndicate - cost = 12 + cost = 10 surplus = 0 + hijack_only = TRUE //This is an item only useful for a hijack traitor, as such, it should only be available in those scenarios. + cant_discount = TRUE + excludefrom = list(/datum/game_mode/nuclear) + +/datum/uplink_item/device_tools/singularity_beacon/nuke + reference = "SNGBN" + hijack_only = FALSE // This inherited version exists so nukies can use it while keeping the original hijack only + excludefrom = list() + gamemodes = list(/datum/game_mode/nuclear) /datum/uplink_item/device_tools/syndicate_bomb name = "Syndicate Bomb" @@ -1224,6 +1298,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/stack/telecrystal cost = 1 surplus = 0 + cant_discount = TRUE /datum/uplink_item/device_tools/telecrystal/five name = "5 Raw Telecrystals" @@ -1301,6 +1376,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/implanter/uplink cost = 14 surplus = 0 + cant_discount = TRUE /datum/uplink_item/implants/storage name = "Storage Implant" @@ -1405,6 +1481,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/storage/box/syndicate cost = 20 excludefrom = list(/datum/game_mode/nuclear) + cant_discount = TRUE /datum/uplink_item/badass/syndiecards name = "Syndicate Playing Cards" @@ -1438,6 +1515,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) reference = "BABA" item = /obj/item/toy/syndicateballoon cost = 20 + cant_discount = TRUE /datum/uplink_item/implants/macrobomb name = "Macrobomb Implant" @@ -1480,6 +1558,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 20 item = /obj/item/storage/box/syndicate excludefrom = list(/datum/game_mode/nuclear) + cant_discount = TRUE // You fucking wish /datum/uplink_item/badass/surplus_crate/spawn_item(turf/loc, obj/item/uplink/U) var/obj/structure/closet/crate/C = new(loc) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 49bc85959f5..7c66666af04 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -1505,7 +1505,7 @@ var/list/ghostteleportlocs = list() /area/medical/biostorage - name = "\improper Secondary Storage" + name = "\improper Medical Storage" icon_state = "medbaysecstorage" music = 'sound/ambience/signal.ogg' @@ -1553,8 +1553,8 @@ var/list/ghostteleportlocs = list() icon_state = "CMO" /area/medical/cmostore - name = "\improper Secure Storage" - icon_state = "CMO" + name = "\improper Medical Secondary Storage" + icon_state = "medbaysecstorage" /area/medical/robotics name = "\improper Robotics" diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 9abe6c2bc92..c6edd09575e 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -63,7 +63,7 @@ var/global/max_secret_rooms = 6 treasureitems = list(/mob/living/simple_animal/bot/medbot/mysterious=1, /obj/item/circular_saw=1, /obj/structure/closet/critter/cat=2) fluffitems = list(/obj/effect/decal/cleanable/blood=5,/obj/item/organ/internal/appendix=2,/obj/structure/closet/crate/freezer=2, /obj/machinery/optable=1,/obj/item/scalpel=1,/obj/item/storage/firstaid/regular=3, - /obj/item/tank/anesthetic=1, /obj/item/surgical_drapes=2, /obj/item/mass_spectrometer/adv=1,/obj/item/clothing/glasses/hud/health=1) + /obj/item/tank/anesthetic=1, /obj/item/surgical_drapes=2, /obj/item/reagent_scanner/adv=1,/obj/item/clothing/glasses/hud/health=1) if("cult") theme = "cult" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 5ca34ceb57e..30b901875b3 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -15,6 +15,7 @@ var/atom_say_verb = "says" var/dont_save = 0 // For atoms that are temporary by necessity - like lighting overlays + ///Chemistry. var/container_type = NONE var/datum/reagents/reagents = null @@ -150,9 +151,11 @@ //Hook for running code when a dir change occurs /atom/proc/setDir(newdir) + SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) dir = newdir /atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) user.changeNext_move(CLICK_CD_MELEE) add_attack_logs(user, src, "Punched with hulk powers") @@ -305,8 +308,8 @@ /atom/proc/ex_act() return -/atom/proc/blob_act() - return +/atom/proc/blob_act(obj/structure/blob/B) + SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B) /atom/proc/fire_act() return @@ -696,6 +699,9 @@ var/list/blood_splatter_icons = list() /atom/proc/ratvar_act() return +/atom/proc/handle_ricochet(obj/item/projectile/P) + return + //This proc is called on the location of an atom when the atom is Destroy()'d /atom/proc/handle_atom_del(atom/A) return @@ -734,3 +740,14 @@ var/list/blood_splatter_icons = list() if(!L) return null return L.AllowDrop() ? L : get_turf(L) + +/atom/Entered(atom/movable/AM, atom/oldLoc) + SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc) + +/atom/Exit(atom/movable/AM, atom/newLoc) + . = ..() + if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT) + return FALSE + +/atom/Exited(atom/movable/AM, atom/newLoc) + SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 36d3ce81ea2..a5d2366c46c 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -126,10 +126,11 @@ // Previously known as HasEntered() // This is automatically called when something enters your square /atom/movable/Crossed(atom/movable/AM) - return + SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) /atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). if(A && yes) + SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A) if(throwing) throwing.hit_atom(A) . = 1 @@ -213,6 +214,7 @@ //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum) set waitfor = 0 + SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) if(!QDELETED(hit_atom)) return hit_atom.hitby(src) diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index 5ae1a040ab6..1fb293be2cf 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -3,9 +3,9 @@ icon = 'icons/mob/blob.dmi' icon_state = "blob_idle" desc = "Some blob creature thingy" - health = 75 + health = 75 fire_resist = 2 - + var/maxHealth = 75 /obj/structure/blob/shield/update_icon() if(health <= 0) @@ -19,3 +19,34 @@ /obj/structure/blob/shield/CanPass(atom/movable/mover, turf/target, height=0) if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 return 0 + +/obj/structure/blob/shield/reflective + name = "reflective blob" + desc = "A solid wall of slightly twitching tendrils with a reflective glow." + icon_state = "blob_idle_glow" + brute_resist = 0 + health = 50 + maxHealth = 50 + flags_2 = CHECK_RICOCHET_1 + var/reflect_chance = 80 //80% chance to reflect + +/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P) + if(P.is_reflectable && prob(reflect_chance)) + var/P_turf = get_turf(P) + var/face_direction = get_dir(src, P_turf) + var/face_angle = dir2angle(face_direction) + var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180)) + if(abs(incidence_s) > 90 && abs(incidence_s) < 270) + return FALSE + var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s) + P.setAngle(new_angle_s) + P.firer = src //so people who fired the lasers are not immune to them when it reflects + visible_message("[P] reflects off [src]!") + return -1// complete projectile permutation + else + playsound(src, P.hitsound, 50, 1) + visible_message("[src] is hit by \a [P]!") + take_damage(P.damage, P.damage_type) + +/obj/structure/blob/shield/reflective/bullet_act() + return diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index d65fcb24ee6..c0f2e4a4a9e 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -56,6 +56,7 @@ to_chat(src, "You are the overmind and can control the blob! You can expand, which will attack people, and place new blob pieces such as...") to_chat(src, "Normal Blob will expand your reach and allow you to upgrade into special blobs that perform certain functions.") to_chat(src, "Shield Blob is a strong and expensive blob which can take more damage. It is fireproof and can block air, use this to protect yourself from station fires.") + to_chat(src, "Reflective Blobis an upgraded Shield Blob which has a high chance of deflecting energy projectiles, but is vulnerable to ballistics and brute damage.") to_chat(src, "Resource Blob is a blob which will collect more resources for you, try to build these earlier to get a strong income. It will benefit from being near your core or multiple nodes, by having an increased resource rate; put it alone and it won't create resources at all.") to_chat(src, "Node Blob is a blob which will grow, like the core. Unlike the core it won't give you a small income but it can power resource and factory blobs to increase their rate.") to_chat(src, "Factory Blob is a blob which will spawn blob spores which will attack nearby food. Putting this nearby nodes and your core will increase the spawn rate; put it alone and it will not spawn any spores.") diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index 35f3c935013..4491b80d2e4 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -33,34 +33,51 @@ /mob/camera/blob/verb/create_shield_power() set category = "Blob" - set name = "Create Shield Blob (10)" - set desc = "Create a shield blob." + set name = "Create/Upgrade Shield Blob (15)" + set desc = "Create/Upgrade a shield blob. Using this on an existing shield blob turns it into a reflective blob, capable of reflecting most energy projectiles but making it much weaker than usual to brute attacks." var/turf/T = get_turf(src) create_shield(T) /mob/camera/blob/proc/create_shield(var/turf/T) - var/obj/structure/blob/B = (locate(/obj/structure/blob) in T) + var/obj/structure/blob/B = locate(/obj/structure/blob) in T + var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T + + if(!S) + if(!B)//We are on a blob + to_chat(src, "There is no blob here!") + return - if(!B)//We are on a blob - to_chat(src, "There is no blob here!") - return + else if(!istype(B, /obj/structure/blob/normal)) + to_chat(src, "Unable to use this blob, find a normal one.") + return - if(!istype(B, /obj/structure/blob/normal)) - to_chat(src, "Unable to use this blob, find a normal one.") - return + else if(!can_buy(15)) + return - if(!can_buy(10)) - return + B.color = blob_reagent_datum.color + B.change_to(/obj/structure/blob/shield) + else + + if(istype(S, /obj/structure/blob/shield/reflective)) + to_chat(src, "There's already a reflector blob here!") + return - B.color = blob_reagent_datum.color - B.change_to(/obj/structure/blob/shield) + else if(S.health < S.maxHealth * 0.5) + to_chat(src, "This shield blob is too damaged to be modified properly!") + return + + else if (!can_buy(15)) + return + + to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect energy projectiles at the cost of reduced intregrity.") + + S.change_to(/obj/structure/blob/shield/reflective) + S.color = blob_reagent_datum.color return - - /mob/camera/blob/verb/create_resource() set category = "Blob" set name = "Create Resource Blob (40)" diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index 6d0084b9000..493c0da90c9 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -19,7 +19,7 @@ src.update_icon() ..(loc) for(var/atom/A in loc) - A.blob_act() + A.blob_act(src) return @@ -126,7 +126,7 @@ qdel(B) for(var/atom/A in T)//Hit everything in the turf - A.blob_act() + A.blob_act(src) return 1 /obj/structure/blob/ex_act(severity) @@ -141,7 +141,7 @@ /obj/structure/blob/Crossed(var/mob/living/L) ..() - L.blob_act() + L.blob_act(src) /obj/structure/blob/tesla_act(power) ..() diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 477a0de2573..6f3f62fc3ba 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -131,6 +131,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" return /datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1) + SEND_SOUND(changeling.current, 'sound/ambience/antag/ling_aler.ogg') if(you_are) to_chat(changeling.current, "You are a changeling!") to_chat(changeling.current, "Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them.") diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 441292366f0..da7cb876fc5 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -114,6 +114,7 @@ var/global/list/all_cults = list() summon_spots += summon for(var/datum/mind/cult_mind in cult) + SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg') equip_cultist(cult_mind.current) cult_mind.current.faction |= "cult" var/datum/action/innate/cultcomm/C = new() diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 6cdfdc736d9..5ba8d1360b0 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -3,7 +3,6 @@ real_name = "host brain" /mob/living/captive_brain/say(message) - if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (muted).") @@ -152,13 +151,13 @@ stat("Chemicals", chemicals) /mob/living/simple_animal/borer/say(var/message) - var/datum/language/dialect = parse_language(message) - if(!dialect) - dialect = get_default_language() - if(!istype(dialect, /datum/language/corticalborer) && loc == host && !talk_inside_host) - to_chat(src, "You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.") - return - ..() + var/list/message_pieces = parse_languages(message) + for(var/datum/multilingual_say_piece/S in message_pieces) + if(!istype(S.speaking, /datum/language/corticalborer) && loc == host && !talk_inside_host) + to_chat(src, "You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.") + return + + . = ..() /mob/living/simple_animal/borer/verb/Communicate() set category = "Borer" diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 9c72ffc9bef..cc96f206aba 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -216,6 +216,7 @@ proc/issyndicate(mob/living/M as mob) /datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1) + SEND_SOUND(syndicate.current, 'sound/ambience/antag/ops.ogg') if(you_are) to_chat(syndicate.current, "You are a [syndicate_name()] agent!") var/obj_count = 1 diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index ec667bbad86..61986b34f94 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -391,3 +391,12 @@ /obj/item/pinpointer/crew/examine(mob/user) ..(user) + +/obj/item/pinpointer/crew/centcom + name = "centcom pinpointer" + desc = "A handheld tracking device that tracks crew based on remote centcom sensors." + +/obj/item/pinpointer/crew/centcom/trackable(mob/living/carbon/human/H) + var/turf/here = get_turf(src) + var/turf/there = get_turf(H) + return there && there.z == here.z \ No newline at end of file diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 5b00868dc3d..317f9e55b80 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -51,7 +51,8 @@ Made by Xhuis var/shadowling_ascended = 0 //If at least one shadowling has ascended var/shadowling_dead = 0 //is shadowling kill var/objective_explanation - + var/warning_threshold + var/victory_warning_announced = FALSE /proc/is_thrall(var/mob/living/M) return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.shadowling_thralls) @@ -101,6 +102,8 @@ Made by Xhuis var/thrall_scaling = round(num_players() / 3) required_thralls = Clamp(thrall_scaling, 15, 25) + warning_threshold = round(0.66 * required_thralls) + ..() return 1 @@ -164,7 +167,9 @@ Made by Xhuis to_chat(new_thrall_mind.current, "You may communicate with your allies by speaking in the Shadowling Hivemind (:8).") if(jobban_isbanned(new_thrall_mind.current, ROLE_SHADOWLING) || jobban_isbanned(new_thrall_mind.current, ROLE_SYNDICATE)) replace_jobbanned_player(new_thrall_mind.current, ROLE_SHADOWLING) - + if(!victory_warning_announced && (length(shadowling_thralls) >= warning_threshold))//are the slings very close to winning? + victory_warning_announced = TRUE //then let's give the station a warning + command_announcement.Announce("Large concentration of psychic bluespace energy detected by long-ranged scanners. Shadowling ascension event imminent. Prevent it at all costs!", "Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg') return 1 /datum/game_mode/proc/remove_thrall(datum/mind/thrall_mind, var/kill = 0) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index d79dbc3c224..c4f39867115 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -178,6 +178,10 @@ /datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + SEND_SOUND(traitor.current, 'sound/ambience/antag/malf.ogg') + else + SEND_SOUND(traitor.current, 'sound/ambience/antag/tatoralert.ogg') to_chat(traitor.current, "You are the traitor.") var/obj_count = 1 for(var/datum/objective/objective in traitor.objectives) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index c45da8ac279..28dc6b29a45 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -76,8 +76,8 @@ //Vampires who have reached their full potential can affect nearly everything if(user.mind.vampire.get_ability(/datum/vampire_passive/full)) return 1 - //Chaplains are resistant to vampire powers - if(target.mind && target.mind.assigned_role == "Chaplain") + //Holy characters are resistant to vampire powers + if(target.mind && target.mind.isholy) return 0 return 1 @@ -535,3 +535,73 @@ /datum/vampire_passive/full gain_desc = "You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly." + + +/obj/effect/proc_holder/spell/targeted/raise_vampires + name = "Raise Vampires" + desc = "Summons deadly vampires from bluespace." + school = "transmutation" + charge_max = 100 + clothes_req = 0 + human_req = 1 + invocation = "none" + invocation_type = "none" + max_targets = 0 + range = 3 + cooldown_min = 20 + action_icon_state = "revive_thrall" + sound = 'sound/magic/WandODeath.ogg' + +/obj/effect/proc_holder/spell/targeted/raise_vampires/cast(list/targets, mob/user = usr) + new /obj/effect/temp_visual/cult/sparks(user.loc) + var/turf/T = get_turf(user) + to_chat(user, "You call out within bluespace, summoning more vampiric spirits to aid you!") + for(var/mob/living/carbon/human/H in targets) + T.Beam(H, "sendbeam", 'icons/effects/effects.dmi', time=30, maxdistance=7, beam_type=/obj/effect/ebeam) + new /obj/effect/temp_visual/cult/sparks(H.loc) + H.raise_vampire(user) + + +/mob/living/carbon/human/proc/raise_vampire(var/mob/M) + if(!istype(M)) + log_debug("human/proc/raise_vampire called with invalid argument.") + return + if(!mind) + visible_message("[src] looks to be too stupid to understand what is going on.") + return + if(dna && (NO_BLOOD in dna.species.species_traits) || dna.species.exotic_blood || !blood_volume) + visible_message("[src] looks unfazed!") + return + if(mind.vampire || mind.special_role == SPECIAL_ROLE_VAMPIRE || mind.special_role == SPECIAL_ROLE_VAMPIRE_THRALL) + visible_message("[src] looks refreshed!") + adjustBruteLoss(-60) + adjustFireLoss(-60) + for(var/obj/item/organ/external/E in bodyparts) + if(prob(25)) + if(E.mend_fracture()) + E.perma_injury = 0 + return + if(stat != DEAD) + if(weakened) + visible_message("[src] looks to be in pain!") + adjustBrainLoss(60) + else + visible_message("[src] looks to be stunned by the energy!") + Weaken(20) + return + for(var/obj/item/implant/mindshield/L in src) + if(L && L.implanted) + qdel(L) + for(var/obj/item/implant/traitor/T in src) + if(T && T.implanted) + qdel(T) + visible_message("[src] gets an eerie red glow in their eyes!") + var/datum/objective/protect/protect_objective = new + protect_objective.owner = mind + protect_objective.target = M.mind + protect_objective.explanation_text = "Protect [M.real_name]." + mind.objectives += protect_objective + add_attack_logs(M, src, "Vampire-sired") + mind.make_Vampire() + revive() + Weaken(20) \ No newline at end of file diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index d6657ef98c1..5951814660b 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -105,6 +105,7 @@ /datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) + addtimer(CALLBACK(wizard.current, /mob/.proc/playsound_local, null, 'sound/ambience/antag/ragesmages.ogg', 100, 0), 30) if(you_are) to_chat(wizard.current, "You are the Space Wizard!") to_chat(wizard.current, "The Space Wizards Federation has given you the following tasks:") diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 4bf351019ea..22a27a3b94c 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -84,7 +84,7 @@ /var/const/access_cent_storage = 105//Storage areas. /var/const/access_cent_shuttles = 106//Shuttle docks. /var/const/access_cent_telecomms = 107//Telecomms. -/var/const/access_cent_teleporter = 108//Telecomms. +/var/const/access_cent_teleporter = 108//Teleporter /var/const/access_cent_specops = 109//Special Ops. /var/const/access_cent_specops_commander = 110//Special Ops Commander. /var/const/access_cent_blackops = 111//Black Ops. @@ -207,6 +207,8 @@ var/const/access_trade_sol = 160 return list(access_cent_general, access_cent_living, access_cent_medical, access_cent_security, access_cent_storage, access_cent_specops, access_cent_specops_commander, access_cent_blackops) + get_all_accesses() if("Deathsquad Officer") return get_all_centcom_access() + get_all_accesses() + if("NT Undercover Operative") + return get_all_centcom_access() + get_all_accesses() if("Special Operations Officer") return get_all_centcom_access() + get_all_accesses() if("Nanotrasen Navy Representative") @@ -224,6 +226,8 @@ var/const/access_trade_sol = 160 return list(access_syndicate) if("Syndicate Operative Leader") return list(access_syndicate, access_syndicate_leader) + if("Syndicate Agent") + return list(access_syndicate, access_maint_tunnels) if("Vox Raider") return list(access_vox) if("Vox Trader") diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm index 6ee7c9af634..6f6ea6ca67a 100644 --- a/code/game/jobs/job/central.dm +++ b/code/game/jobs/job/central.dm @@ -35,7 +35,9 @@ ) backpack = /obj/item/storage/backpack/satchel box = /obj/item/storage/box/centcomofficer - + cybernetic_implants = list( + /obj/item/organ/internal/cyberimp/chest/nutriment/plus + ) // CC Officials who lead ERTs, Death Squads, etc. /datum/job/ntspecops @@ -61,7 +63,7 @@ uniform = /obj/item/clothing/under/rank/centcom_commander suit = /obj/item/clothing/suit/space/deathsquad/officer back = /obj/item/storage/backpack/security - belt = /obj/item/gun/energy/pulse/pistol/m1911 + belt = /obj/item/storage/belt/military/assault gloves = /obj/item/clothing/gloves/combat shoes = /obj/item/clothing/shoes/combat mask = /obj/item/clothing/mask/cigarette/cigar/cohiba @@ -75,7 +77,6 @@ backpack = /obj/item/storage/backpack/satchel backpack_contents = list( /obj/item/clothing/shoes/magboots/advance = 1, - /obj/item/twohanded/dualsaber/red = 1, /obj/item/storage/box/zipties = 1 ) implants = list( @@ -84,7 +85,7 @@ ) cybernetic_implants = list( /obj/item/organ/internal/cyberimp/eyes/xray, - /obj/item/organ/internal/cyberimp/brain/anti_drop, /obj/item/organ/internal/cyberimp/brain/anti_stun, - /obj/item/organ/internal/cyberimp/chest/nutriment/plus + /obj/item/organ/internal/cyberimp/chest/nutriment/plus, + /obj/item/organ/internal/cyberimp/arm/combat/centcom ) \ No newline at end of file diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index d7bd9c1c4cb..cfb2de566ce 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -112,7 +112,7 @@ backpack_contents = list( /obj/item/clothing/head/surgery/black = 1, /obj/item/autopsy_scanner = 1, - /obj/item/mass_spectrometer = 1, + /obj/item/reagent_scanner = 1, /obj/item/storage/box/bodybags = 1) /datum/outfit/job/doctor/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm index 6b13b78c2bb..18edfc1e6c2 100644 --- a/code/game/jobs/job/support_chaplain.dm +++ b/code/game/jobs/job/support_chaplain.dm @@ -25,6 +25,7 @@ backpack_contents = list( /obj/item/camera/spooky = 1 ) + r_hand = /obj/item/nullrod /datum/outfit/job/chaplain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) . = ..() @@ -32,13 +33,16 @@ if(visualsOnly) return - var/obj/item/storage/bible/B = new /obj/item/storage/bible(H) + if(H.mind) + H.mind.isholy = TRUE spawn() + + var/obj/item/storage/bible/B = new /obj/item/storage/bible(H) H.equip_to_slot_or_del(B, slot_l_hand) var/religion_name = "Christianity" - var/new_religion = sanitize(copytext(input(H, "You are the crew services officer. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name),1,MAX_NAME_LEN)) + var/new_religion = sanitize(copytext(input(H, "You are the Chaplain. What name do you give your beliefs? Default is Christianity.", "Name change", religion_name),1,MAX_NAME_LEN)) if(!new_religion) new_religion = religion_name @@ -72,12 +76,14 @@ feedback_set_details("religion_name","[new_religion]") var/deity_name = "Space Jesus" - var/new_deity = sanitize(copytext(input(H, "Would you like to change your deity? Default is Space Jesus.", "Name change", deity_name),1,MAX_NAME_LEN)) + var/new_deity = sanitize(copytext(input(H, "Who or what do you worship? Default is Space Jesus.", "Name change", deity_name),1,MAX_NAME_LEN)) if((length(new_deity) == 0) || (new_deity == "Space Jesus") ) new_deity = deity_name B.deity_name = new_deity + H.AddSpell(new /obj/effect/proc_holder/spell/targeted/chaplain_bless(null)) + var/accepted = 0 var/outoftime = 0 spawn(200) // 20 seconds to choose @@ -85,8 +91,9 @@ var/new_book_style = "Bible" while(!accepted) - if(!B) break // prevents possible runtime errors - new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon", "Greentext") + if(!B) + break // prevents possible runtime errors + new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "PlainRed", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon", "Greentext") switch(new_book_style) if("Koran") B.icon_state = "koran" @@ -107,13 +114,9 @@ if("Holy Light") B.icon_state = "holylight" B.item_state = "syringe_kit" - if("Athiest") + if("PlainRed") B.icon_state = "athiest" B.item_state = "syringe_kit" - for(var/area/chapel/main/A in world) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 10 if("Tome") B.icon_state = "tome" B.item_state = "syringe_kit" @@ -165,3 +168,5 @@ ticker.Bible_deity_name = B.deity_name feedback_set_details("religion_deity","[new_deity]") feedback_set_details("religion_book","[new_book_style]") + + diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 2e41ec49c0a..61547f270bf 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -57,14 +57,14 @@ output &= ~bitflag_value else//can't not be off output |= bitflag_value - return MT_UPDATE + return TRUE if("toggle_bolts" in href_list) bolts = !bolts if(bolts) visible_message("You hear a quite click as the [src] bolts to the floor", "You hear a quite click") else visible_message("You hear a quite click as the [src]'s floor bolts raise", "You hear a quite click") - return MT_UPDATE + return TRUE /obj/machinery/air_sensor/attackby(var/obj/item/W as obj, var/mob/user as mob) if(istype(W, /obj/item/multitool)) @@ -301,19 +301,19 @@ sensor_list|=G.id_tag if(!sensor_list.len) to_chat(user, "No sensors on this frequency.") - return MT_ERROR + return FALSE // Have the user pick one of them and name its label var/sensor = input(user, "Select a sensor:", "Sensor Data") as null|anything in sensor_list if(!sensor) - return MT_ERROR + return FALSE var/label = reject_bad_name( input(user, "Choose a sensor label:", "Sensor Label") as text|null, allow_numbers=1) if(!label) - return MT_ERROR + return FALSE // Add the sensor's information to general_air_controler sensors[sensor] = label - return MT_UPDATE + return TRUE if("edit_sensor" in href_list) var/list/sensor_list = list() @@ -322,14 +322,14 @@ sensor_list|=G.id_tag if(!sensor_list.len) to_chat(user, "No sensors on this frequency.") - return MT_ERROR + return FALSE var/label = sensors[href_list["edit_sensor"]] var/sensor = input(user, "Select a sensor:", "Sensor Data", href_list["edit_sensor"]) as null|anything in sensor_list if(!sensor) - return MT_ERROR + return FALSE sensors.Remove(href_list["edit_sensor"]) sensors[sensor] = label - return MT_UPDATE + return TRUE /obj/machinery/computer/general_air_control/unlinkFrom(mob/user, obj/O) ..() diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index d3d23e96bba..dba1d942e2d 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -4,17 +4,17 @@ icon = 'icons/obj/meter.dmi' icon_state = "meterX" var/obj/machinery/atmospherics/pipe/target = null - anchored = 1 + anchored = TRUE armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100) power_channel = ENVIRON - var/frequency = 0 + var/frequency = ATMOS_DISTRO_FREQ var/id var/id_tag use_power = IDLE_POWER_USE idle_power_usage = 2 active_power_usage = 5 req_one_access_txt = "24;10" - Mtoollink = 1 + Mtoollink = TRUE settagwhitelist = list("id_tag") /obj/machinery/meter/New() diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 8655c8e0602..49a05371050 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -374,19 +374,19 @@ var/list/holopads = list() /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/hologram/holopad/hear_talk(atom/movable/speaker, message, verb, datum/language/message_language) +/obj/machinery/hologram/holopad/hear_talk(atom/movable/speaker, list/message_pieces, verb) if(speaker && masters.len)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. for(var/mob/living/silicon/ai/master in masters) if(masters[master] && speaker != master) - master.relay_speech(speaker, message, verb, message_language) + master.relay_speech(speaker, message_pieces, verb) for(var/I in holo_calls) var/datum/holocall/HC = I if(HC.connected_holopad == src && speaker != HC.hologram) - HC.user.hear_say(message, verb, message_language, speaker = speaker) + HC.user.hear_say(message_pieces, verb, speaker = speaker) if(outgoing_call && speaker == outgoing_call.user) - outgoing_call.hologram.atom_say(message) + outgoing_call.hologram.atom_say(multilingual_to_message(message_pieces)) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 4ccaa246578..7890110aabc 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -65,6 +65,9 @@ overlays += filling /obj/machinery/iv_drip/MouseDrop(mob/living/target) + if(usr.incapacitated()) + return + if(!ishuman(usr) || !iscarbon(target)) return diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index b0ab09be91b..553016400ad 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -222,11 +222,11 @@ Class Procs: var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) if(newid) src:id_tag = newid - return MT_UPDATE|MT_REINIT + return TRUE if("set_freq" in href_list) if(!("frequency" in vars)) warning("set_freq: [type] has no frequency var.") - return 0 + return FALSE var/newfreq=src:frequency if(href_list["set_freq"]!="-1") newfreq=text2num(href_list["set_freq"]) @@ -235,90 +235,81 @@ Class Procs: if(newfreq) if(findtext(num2text(newfreq), ".")) newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - src:frequency = newfreq - return MT_UPDATE|MT_REINIT - return 0 + src:frequency = sanitize_frequency(newfreq, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + return TRUE + return FALSE /obj/machinery/proc/handle_multitool_topic(var/href, var/list/href_list, var/mob/user) if(!allowed(user))//no, not even HREF exploits - return 0 + return FALSE var/obj/item/multitool/P = get_multitool(usr) if(P && istype(P)) - var/update_mt_menu=0 - var/re_init=0 + var/update_mt_menu = FALSE if("set_tag" in href_list) if(!(href_list["set_tag"] in settagwhitelist))//I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. (seriously though, this is a powerfull HREF, I originally found this loophole, I'm not leaving it in on my PR) message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name_admin(user)] on [src] (JMP)") - return 1 + return FALSE if(!(href_list["set_tag"] in vars)) to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!") - return 1 + return FALSE var/current_tag = vars[href_list["set_tag"]] var/newid = copytext(reject_bad_text(input(usr, "Specify the new value", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) if(newid) vars[href_list["set_tag"]] = newid - re_init=1 + update_mt_menu = TRUE if("unlink" in href_list) var/idx = text2num(href_list["unlink"]) if(!idx) - return 1 + return FALSE var/obj/O = getLink(idx) if(!O) - return 1 + return FALSE if(!canLink(O)) to_chat(usr, "You can't link with that device.") - return 1 + return FALSE if(unlinkFrom(usr, O)) to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.") else to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.") - update_mt_menu=1 + update_mt_menu = TRUE if("link" in href_list) var/obj/O = P.buffer if(!O) - return 1 + return FALSE if(!canLink(O,href_list)) to_chat(usr, "You can't link with that device.") - return 1 + return FALSE if(isLinkedWith(O)) to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.") - return 1 + return FALSE if(linkWith(usr, O, href_list)) to_chat(usr, "A green light flashes on \the [P], confirming the link was added.") else to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.") - update_mt_menu=1 + update_mt_menu = TRUE if("buffer" in href_list) P.buffer = src to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.") - update_mt_menu=1 + update_mt_menu = TRUE if("flush" in href_list) to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.") P.buffer = null - update_mt_menu=1 + update_mt_menu = TRUE var/ret = multitool_topic(usr,href_list,P.buffer) - if(ret == MT_ERROR) - return 1 - if(ret & MT_UPDATE) - update_mt_menu=1 - if(ret & MT_REINIT) - re_init=1 + if(ret) + update_mt_menu = TRUE - if(re_init) - Initialize() if(update_mt_menu) - //usr.set_machine(src) update_multitool_menu(usr) - return 1 + return TRUE /obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state) if(..(href, href_list, nowindow, state)) diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 10451c758be..8e34e2e19bc 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -57,7 +57,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"],, signal.data["compression"], signal.data["level"], signal.frequency, - signal.data["verb"], signal.data["language"] ) + signal.data["verb"] ) /** #### - Simple Broadcast - #### **/ @@ -83,7 +83,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, - signal.data["verb"], signal.data["language"]) + signal.data["verb"]) if(!message_delay) message_delay = 1 @@ -146,7 +146,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency, - signal.data["verb"], signal.data["language"]) + signal.data["verb"]) else if(intercept) Broadcast_Message(signal.data["connection"], signal.data["mob"], @@ -154,7 +154,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, - signal.data["verb"], signal.data["language"]) + signal.data["verb"]) #define CREW_RADIO_TYPE 0 #define CENTCOMM_RADIO_TYPE 1 @@ -234,9 +234,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept **/ /proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M, - var/vmask, var/vmessage, var/obj/item/radio/radio, - var/message, var/name, var/job, var/realname, var/vname, - var/data, var/compression, var/list/level, var/freq, var/verbage = "says", var/datum/language/speaking = null, + var/vmask, list/vmessage_pieces, var/obj/item/radio/radio, + list/message_pieces, var/name, var/job, var/realname, var/vname, + var/data, var/compression, var/list/level, var/freq, var/verbage = "says", var/atom/follow_target = null) @@ -339,7 +339,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept else // - The speaker has a prespecified "voice message" to display if not understood - - if(vmessage) + if(vmessage_pieces) heard_voice += R // - Just display a garbled message - @@ -364,12 +364,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // --- Filter the message; place it in quotes apply a verb --- - var/quotedmsg = null if(M) - quotedmsg = M.say_quote(message) + quotedmsg = "[M.say_quote(multilingual_to_message(message_pieces))], \"[multilingual_to_message(message_pieces)]\"" else - quotedmsg = "says, \"[message]\"" + quotedmsg = "says, \"[multilingual_to_message(message_pieces)]\"" // --- This following recording is intended for research and feedback in the use of department radio channels --- @@ -414,38 +413,38 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept if(length(heard_masked)) for(var/mob/R in heard_masked) - R.hear_radio(message,verbage, speaking, part_a, part_b, M, 0, name, follow_target=follow_target) + R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, name, follow_target=follow_target) /* --- Process all the mobs that heard the voice normally (understood) --- */ if(length(heard_normal)) for(var/mob/R in heard_normal) - R.hear_radio(message, verbage, speaking, part_a, part_b, M, 0, realname, follow_target=follow_target) + R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, realname, follow_target=follow_target) /* --- Process all the mobs that heard the voice normally (did not understand) --- */ if(length(heard_voice)) for(var/mob/R in heard_voice) - R.hear_radio(message,verbage, speaking, part_a, part_b, M,0, vname, follow_target=follow_target) + R.hear_radio(message_pieces, verbage, part_a, part_b, M,0, vname, follow_target=follow_target) /* --- Process all the mobs that heard a garbled voice (did not understand) --- */ // Displays garbled message (ie "f*c* **u, **i*er!") if(length(heard_garbled)) for(var/mob/R in heard_garbled) - R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1, vname, follow_target=follow_target) + R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, vname, follow_target=follow_target) /* --- Complete gibberish. Usually happens when there's a compressed message --- */ if(length(heard_gibberish)) for(var/mob/R in heard_gibberish) - R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1, follow_target=follow_target) + R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, follow_target=follow_target) return 1 -/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level) - +/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level) + var/text = multilingual_to_message(message_pieces) /* ###### Prepare the radio connection ###### */ var/mob/living/carbon/human/H diff --git a/code/game/machinery/telecomms/ntsl2.dm b/code/game/machinery/telecomms/ntsl2.dm index ee9fabd272a..d24b51389ec 100644 --- a/code/game/machinery/telecomms/ntsl2.dm +++ b/code/game/machinery/telecomms/ntsl2.dm @@ -1,3 +1,7 @@ +#define JOB_STYLE_1 "Name (Job)" +#define JOB_STYLE_2 "Name - Job" +#define JOB_STYLE_3 "\[Job\] Name" +#define JOB_STYLE_4 "(Job) Name" GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) // Custom Implementations for NTTC /* NTTC Configuration Datum @@ -5,16 +9,125 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) * as well as allowing users to save and load configurations. */ /datum/nttc_configuration + // ALL OF THE JOB CRAP + // Dict of all jobs and their colors + var/all_jobs = list( + // AI + "AI" = "#FF00FF", + "Android" = "#FF00FF", + "Cyborg" = "#FF00FF", + "Personal AI" = "#FF00FF", + "Robot" = "#FF00FF", + // Civilian + Varients + "Assistant" = "#408010", + "Businessman" = "#408010", + "Civilian" = "#408010", + "Tourist" = "#408010", + "Trader" = "#408010", + // Command (Solo command, not department heads) + "Blueshield" = "#204090", + "Captain" = "#204090", + "Head of Personnel" = "#204090", + "Nanotrasen Representative" = "#204090", + // Engineeering + "Atmospheric Technician" = "#A66300", + "Chief Engineer" = "#A66300", + "Electrician" = "#A66300", + "Engine Technician" = "#A66300", + "Life Support Specialist" = "#A66300", + "Maintenance Technician" = "#A66300", + "Mechanic" = "#A66300", + "Station Engineer" = "#A66300", + // ERT + "Emergency Response Team Engineer" = "#5C5C7C", + "Emergency Response Team Leader" = "#5C5C7C", + "Emergency Response Team Medic" = "#5C5C7C", + "Emergency Response Team Member" = "#5C5C7C", + "Emergency Response Team Officer" = "#5C5C7C", + // Medical + "Chemist" = "#009190", + "Chief Medical Officer" = "#009190", + "Coroner" = "#009190", + "Medical Doctor" = "#009190", + "Microbiologist" = "#009190", + "Nurse" = "#009190", + "Paramedic" = "#009190", + "Pharmacologist" = "#009190", + "Pharmacist" = "#009190", + "Psychiatrist" = "#009190", + "Psychologist" = "#009190", + "Surgeon" = "#009190", + "Therapist" = "#009190", + "Virologist" = "#009190", + // Science + "Anomalist" = "#993399", + "Biomechanical Engineer" = "#993399", + "Chemical Researcher" = "#993399", + "Geneticist" = "#993399", + "Mechatronic Engineer" = "#993399", + "Plasma Researcher" = "#993399", + "Research Director" = "#993399", + "Roboticist" = "#993399", + "Scientist" = "#993399", + "Xenoarcheologist" = "#993399", + "Xenobiologist" = "#993399", + // Security + "Brig Physician" = "#A30000", + "Detective" = "#A30000", + "Forensic Technician" = "#A30000", + "Head of Security" = "#A30000", + "Human Resources Agent" = "#A30000", + "Internal Affairs Agent" = "#A30000", + "Magistrate" = "#A30000", + "Security Officer" = "#A30000", + "Security Pod Pilot" = "#A30000", + "Warden" = "#A30000", + // Supply + "Quartermaster" = "#7F6539", + "Cargo Technician" = "#7F6539", + "Shaft Miner" = "#7F6539", + "Spelunker" = "#7F6539", + // Service + "Barber" = "#80A000", + "Bartender" = "#80A000", + "Beautician" = "#80A000", + "Botanical Researcher" = "#80A000", + "Botanist" = "#80A000", + "Butcher" = "#80A000", + "Chaplain" = "#80A000", + "Chef" = "#80A000", + "Clown" = "#80A000", + "Cook" = "#80A000", + "Culinary Artist" = "#80A000", + "Custodial Technician" = "#80A000", + "Hair Stylist" = "#80A000", + "Hydroponicist" = "#80A000", + "Janitor" = "#80A000", + "Journalist" = "#80A000", + "Librarian" = "#80A000", + "Mime" = "#80A000", + ) + // Just command members + var/heads = list("Captain", "Head of Personnel", "Nanotrasen Representative", "Blueshield", "Chief Engineer", "Chief Medical Officer", "Research Director", "Head of Security") + // Just ERT + var/ert_jobs = list("Emergency Response Team Officer", "Emergency Response Team Engineer", "Emergency Response Team Medic", "Emergency Response Team Leader", "Emergency Response Team Member") + // Defined so code compiles and incase someone has a non-standard job + var/job_color = "#000000" + // NOW FOR ACTUAL TOGGLES /* Simple Toggles */ var/toggle_activated = TRUE var/toggle_jobs = FALSE + var/toggle_job_color = FALSE + var/toggle_name_color = FALSE var/toggle_timecode = FALSE + var/toggle_command_bold = FALSE // Hack section var/toggle_gibberish = FALSE var/toggle_honk = FALSE /* Strings */ var/setting_language = null + var/job_indicator_type = null /* Tables */ var/list/regex = list() @@ -38,7 +151,11 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) var/list/to_serialize = list( "toggle_activated", "toggle_jobs", + "toggle_job_color", + "toggle_name_color", + "job_indicator_type", "toggle_timecode", + "toggle_command_bold", "toggle_gibberish", "toggle_honk", "setting_language", @@ -50,7 +167,11 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) var/list/serialize_sanitize = list( "toggle_activated" = "bool", "toggle_jobs" = "bool", + "toggle_job_color" = "bool", + "toggle_name_color" = "bool", + "job_indicator_type" = "string", "toggle_timecode" = "bool", + "toggle_command_bold" = "bool", "toggle_gibberish" = "bool", "toggle_honk" = "bool", "setting_language" = "string", @@ -58,6 +179,10 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) "firewall" = "array" ) + // These are the job card styles + var/list/job_card_styles = list( + JOB_STYLE_1, JOB_STYLE_2, JOB_STYLE_3, JOB_STYLE_4 + ) // Used to determine what languages are allowable for conversion. Generated during runtime. var/list/valid_languages = list("--DISABLE--") @@ -65,13 +190,17 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) /* Simple Toggles */ toggle_activated = initial(toggle_activated) toggle_jobs = initial(toggle_jobs) + toggle_job_color = initial(toggle_job_color) + toggle_name_color = initial(toggle_name_color) toggle_timecode = initial(toggle_timecode) + toggle_command_bold = initial(toggle_command_bold) // Hack section toggle_gibberish = initial(toggle_gibberish) toggle_honk = initial(toggle_honk) /* Strings */ setting_language = initial(setting_language) + job_indicator_type = initial(job_indicator_type) /* Tables */ regex = list() @@ -142,10 +271,42 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) if(firewall.Find(signal.data["name"])) signal.data["reject"] = 1 - // These two stack properly. - // Simple job indicator switch. + // All job and coloring shit + if(toggle_job_color || toggle_name_color) + var/job = signal.data["job"] + job_color = all_jobs[job] + + if(toggle_name_color) + var/new_name = "" + signal.data["name"] + "" + signal.data["name"] = new_name + signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on + if(toggle_jobs) - var/new_name = signal.data["name"] + " ([signal.data["job"]]) " + var/new_name = "" + var/job = signal.data["job"] + if(job in ert_jobs) + job = "ERT" + if(toggle_job_color) + switch(job_indicator_type) + if(JOB_STYLE_1) + new_name = signal.data["name"] + " ([job]) " + if(JOB_STYLE_2) + new_name = signal.data["name"] + " - [job] " + if(JOB_STYLE_3) + new_name = "\[[job]\] " + signal.data["name"] + " " + if(JOB_STYLE_4) + new_name = "([job]) " + signal.data["name"] + " " + else + switch(job_indicator_type) + if(JOB_STYLE_1) + new_name = signal.data["name"] + " ([job]) " + if(JOB_STYLE_2) + new_name = signal.data["name"] + " - [job] " + if(JOB_STYLE_3) + new_name = "\[[job]\] " + signal.data["name"] + " " + if(JOB_STYLE_4) + new_name = "([job]) " + signal.data["name"] + " " + signal.data["name"] = new_name signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on @@ -155,10 +316,20 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) signal.data["name"] = new_name signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on + // This is hacky stuff for multilingual messages... + var/list/message_pieces = signal.data["message"] + + // Makes heads of staff bold + if(toggle_command_bold) + var/job = signal.data["job"] + if((job in ert_jobs) || (job in heads)) + for(var/datum/multilingual_say_piece/S in message_pieces) + S.message = "[S.message]" + // Hacks! // Censor dat shit like nobody's business if(toggle_gibberish) - signal.data["message"] = Gibberish(signal.data["message"], 80) + Gibberish_all(message_pieces, 80) // Replace everything with HONK! if(toggle_honk) @@ -167,25 +338,25 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) var/new_message = "" for(var/i in 1 to honklength) new_message += pick("HoNK!", "HONK", "HOOOoONK", "HONKHONK!", "HoNnnkKK!!!", "HOOOOOOOOOOONK!!!!11!", "henk!") + " " - signal.data["message"] = new_message - + signal.data["message"] = message_to_multilingual(new_message) // Language Conversion if(setting_language && valid_languages[setting_language]) if(setting_language == "--DISABLE--") setting_language = null else - signal.data["language"] = GLOB.all_languages[setting_language] + for(var/datum/multilingual_say_piece/S in message_pieces) + S.speaking = GLOB.all_languages[setting_language] // Regex replacements if(islist(regex) && regex.len > 0) - var/original = signal.data["message"] - var/new_message = original - for(var/reg in regex) - var/replacePattern = pencode_to_html(regex[reg]) - var/regex/start = regex(reg, "gi") - new_message = start.Replace(new_message, replacePattern) - signal.data["message"] = new_message + for(var/datum/multilingual_say_piece/S in message_pieces) + var/new_message = S.message + for(var/reg in regex) + var/replacePattern = pencode_to_html(regex[reg]) + var/regex/start = regex("[reg]", "gi") + new_message = start.Replace(new_message, replacePattern) + S.message = new_message // Make sure the message is valid after we tinkered with it, otherwise reject it if(signal.data["message"] == "" || !signal.data["message"]) @@ -202,6 +373,15 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) vars[var_to_toggle] = !vars[var_to_toggle] log_action(user, "toggled NTTC variable [var_to_toggle] [vars[var_to_toggle] ? "on" : "off"]") + // Job Format + if(href_list["setting_job_card_style"]) + var/card_style = input(user, "Pick a job card format.", "Job Card Format") as null|anything in job_card_styles + if(!card_style) + return + job_indicator_type = card_style + to_chat(user, "Jobs will now have the style of [card_style].") + log_action(user, "has set NTTC job card format to [card_style]", TRUE) + // Strings if(href_list["setting_language"]) var/new_language = input(user, "Pick a language to convert messages to.", "Language Conversion") as null|anything in valid_languages @@ -252,7 +432,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) var/list/array = vars[href_list["array"]] array.Add(new_value) to_chat(user, "Added row [new_value].") - log_action(user, "updated [href_list["array"]] - new value [new_value]") + log_action(user, "updated [href_list["array"]] - new value [new_value]", TRUE) if(href_list["delete_item"]) if(href_list["array"] && href_list["array"] in arrays) @@ -316,3 +496,4 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) dat += "window.updateConfig = function(config) { window.config = JSON.parse(config); window.reload_tab() };" dat += "" return dat + diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index b38eca98817..06eacdd8da1 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -438,7 +438,6 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() var/encryption = "null" // encryption key: ie "password" var/salt = "null" // encryption salt: ie "123comsat" // would add up to md5("password123comsat") - var/language = "human" var/obj/item/radio/headset/server_radio = null /obj/machinery/telecomms/server/Initialize() @@ -463,11 +462,10 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() log.parameters["mobtype"] = signal.data["mobtype"] log.parameters["race"] = signal.data["race"] log.parameters["job"] = signal.data["job"] - log.parameters["language"] = signal.data["language"] log.parameters["key"] = signal.data["key"] - log.parameters["vmessage"] = signal.data["message"] + log.parameters["vmessage"] = multilingual_to_message(signal.data["message"]) log.parameters["vname"] = signal.data["vname"] - log.parameters["message"] = signal.data["message"] + log.parameters["message"] = multilingual_to_message(signal.data["message"]) log.parameters["name"] = signal.data["name"] log.parameters["realname"] = signal.data["realname"] @@ -478,7 +476,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() // If the signal is still compressed, make the log entry gibberish if(signal.data["compression"] > 0) - log.parameters["message"] = Gibberish(signal.data["message"], signal.data["compression"] + 50) + log.parameters["message"] = Gibberish(multilingual_to_message(signal.data["message"]), signal.data["compression"] + 50) log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 2205a9f6a72..998228beee5 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -171,9 +171,9 @@ for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment) to_chat(user, "[bicon(ME)] [ME]") -/obj/mecha/hear_talk(mob/M, text) +/obj/mecha/hear_talk(mob/M, list/message_pieces) if(M == occupant && radio.broadcasting) - radio.talk_into(M, text) + radio.talk_into(M, message_pieces) /obj/mecha/proc/click_action(atom/target, mob/user, params) if(!occupant || occupant != user ) diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm index 2305e33249e..71219b44d16 100644 --- a/code/game/objects/effects/forcefields.dm +++ b/code/game/objects/effects/forcefields.dm @@ -11,6 +11,18 @@ /obj/effect/forcefield/CanAtmosPass(turf/T) return !density +/obj/effect/forcefield/wizard + var/mob/wizard + +/obj/effect/forcefield/wizard/Initialize(mapload, mob/summoner) + . = ..() + wizard = summoner + +/obj/effect/forcefield/wizard/CanPass(atom/movable/mover, turf/target) + if(mover == wizard) + return TRUE + return FALSE + ///////////Mimewalls/////////// /obj/effect/forcefield/mime @@ -22,4 +34,9 @@ /obj/effect/forcefield/mime/New() ..() if(lifetime) - QDEL_IN(src, lifetime) \ No newline at end of file + QDEL_IN(src, lifetime) + +/obj/effect/forcefield/mime/advanced + name = "invisible blockade" + desc = "You might be here a while." + lifetime = 60 SECONDS \ No newline at end of file diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 4d901261bbd..048396e4eed 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -151,6 +151,7 @@ /obj/item/implanter/storage = 1, /obj/item/toy/cards/deck/syndicate = 2, /obj/item/storage/secure/briefcase/syndie = 2, + /obj/item/storage/fancy/cigarettes/cigpack_syndicate = 2, "" = 70 ) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 9af8b04580a..f8798d77c5d 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -310,6 +310,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d return ..() /obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args) if(prob(final_block_chance)) owner.visible_message("[owner] blocks [attack_text] with [src]!") return 1 @@ -324,6 +325,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d A.Remove(user) if(flags & DROPDEL) qdel(src) + SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user) // called just as an item is picked up (loc is not yet changed) /obj/item/proc/pickup(mob/user) @@ -351,6 +353,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d // for items that can be placed in multiple slots // note this isn't called during the initial dressing of a player /obj/item/proc/equipped(var/mob/user, var/slot) + SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot) for(var/X in actions) var/datum/action/A = X if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. @@ -498,6 +501,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d /obj/item/throw_impact(atom/A) if(A && !QDELETED(A)) + SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A) var/itempush = 1 if(w_class < WEIGHT_CLASS_BULKY) itempush = 0 // too light to push anything @@ -548,6 +552,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d return I == src /obj/item/Crossed(atom/movable/AM) + . = ..() if(prob(trip_chance) && ishuman(AM)) var/mob/living/carbon/human/H = AM on_trip(H) @@ -558,3 +563,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d /obj/item/attack_hulk(mob/living/carbon/human/user) return FALSE + +/obj/item/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user) //handles block for CQC + if(target.check_block()) + target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!", + "You block the attack!") + user.Stun(2) + return TRUE \ No newline at end of file diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 5056c90793f..c24fcc3c68a 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -194,7 +194,7 @@ /obj/item/flash/armimplant name = "photon projector" - desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocals fix the flashbulb if it ever burns out." + desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocols fix the flashbulb if it ever burns out." var/flashcd = 20 var/overheat = 0 var/obj/item/organ/internal/cyberimp/arm/flash/I = null diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 43515ed5241..59a7a650383 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -47,8 +47,10 @@ message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN)) if(!message) return - message = user.handle_speech_problems(message)[1] message = capitalize(message) + var/list/message_pieces = message_to_multilingual(message) + user.handle_speech_problems(message_pieces) + message = multilingual_to_message(message_pieces) if((loc == user && !user.incapacitated())) if(emagged) if(insults) @@ -69,7 +71,7 @@ audible_message("[user.GetVoice()] [user.GetAltName()] broadcasts, \"[message]\"", hearing_distance = 14) log_say(message, user) for(var/obj/O in oview(14, get_turf(src))) - O.hear_talk(user, "[message]") + O.hear_talk(user, message_to_multilingual("[message]")) /obj/item/megaphone/emag_act(user as mob) if(!emagged) diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index fb5e41ec663..31945743ad2 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -10,6 +10,7 @@ var/translate_binary = FALSE var/translate_hive = FALSE var/syndie = FALSE + var/change_voice = FALSE var/list/channels = list() @@ -20,7 +21,7 @@ channels = list("Syndicate" = 1) origin_tech = "syndicate=1;engineering=3;bluespace=2" syndie = TRUE //Signifies that it de-crypts Syndicate transmissions - var/change_voice = TRUE + change_voice = TRUE var/fake_name = "Agent ALERT_A_CODER" var/static/list/fakename_list diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 4bd3896c7a5..1e3acfc7812 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -50,15 +50,15 @@ to_chat(user, "The following channels are available:") to_chat(user, radio_desc) -/obj/item/radio/headset/handle_message_mode(mob/living/M as mob, message, channel) +/obj/item/radio/headset/handle_message_mode(mob/living/M as mob, list/message_pieces, channel) if(channel == "special") if(translate_binary) var/datum/language/binary = GLOB.all_languages["Robot Talk"] - binary.broadcast(M, message) + binary.broadcast(M, strip_prefixes(multilingual_to_message(message_pieces))) return RADIO_CONNECTION_NON_SUBSPACE if(translate_hive) var/datum/language/hivemind = GLOB.all_languages["Hivemind"] - hivemind.broadcast(M, message) + hivemind.broadcast(M, strip_prefixes(multilingual_to_message(message_pieces))) return RADIO_CONNECTION_NON_SUBSPACE return RADIO_CONNECTION_FAIL diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 1409c463000..68d31f075b6 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -285,7 +285,7 @@ var/global/list/default_medbay_channels = list( qdel(src) // Interprets the message mode when talking into a radio, possibly returning a connection datum -/obj/item/radio/proc/handle_message_mode(mob/living/M as mob, message, message_mode) +/obj/item/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode) // If a channel isn't specified, send to common. if(!message_mode || message_mode == "headset") return radio_connection @@ -301,11 +301,11 @@ var/global/list/default_medbay_channels = list( // If we were to send to a channel we don't have, drop it. return RADIO_CONNECTION_FAIL -/obj/item/radio/talk_into(mob/living/M as mob, message, channel, var/verb = "says", var/datum/language/speaking = null) +/obj/item/radio/talk_into(mob/living/M as mob, list/message_pieces, channel, var/verb = "says") if(!on) return 0 // the device has to be on // Fix for permacell radios, but kinda eh about actually fixing them. - if(!M || !message) + if(!M || !message_pieces) return 0 // Uncommenting this. To the above comment: @@ -328,7 +328,7 @@ var/global/list/default_medbay_channels = list( */ //#### Grab the connection datum ####// - var/message_mode = handle_message_mode(M, message, channel) + var/message_mode = handle_message_mode(M, message_pieces, channel) switch(message_mode) //special cases if(RADIO_CONNECTION_FAIL) return 0 @@ -361,7 +361,7 @@ var/global/list/default_medbay_channels = list( var/jobname // the mob's "job" if(jammed) - message = Gibberish(message, 100) + Gibberish_all(message_pieces, 100) // --- Human: use their actual job --- if(ishuman(M)) @@ -432,7 +432,7 @@ var/global/list/default_medbay_channels = list( // Other tags: "compression" = rand(45,50), // compressed radio signal - "message" = message, // the actual sent message + "message" = message_pieces, // the actual sent message "connection" = connection, // the radio connection to use "radio" = src, // stores the radio used for transmission "slow" = 0, // how much to sleep() before broadcasting - simulates net lag @@ -441,7 +441,6 @@ var/global/list/default_medbay_channels = list( "server" = null, // the last server to log this signal "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery "level" = position.z, // The source's z level - "language" = speaking, "verb" = verb ) signal.frequency = connection.frequency // Quick frequency set @@ -490,7 +489,7 @@ var/global/list/default_medbay_channels = list( "vmask" = voicemask, // 1 if the mob is using a voice gas mas "compression" = 0, // uncompressed radio signal - "message" = message, // the actual sent message + "message" = message_pieces, // the actual sent message "connection" = connection, // the radio connection to use "radio" = src, // stores the radio used for transmission "slow" = 0, @@ -499,7 +498,6 @@ var/global/list/default_medbay_channels = list( "server" = null, "reject" = 0, "level" = position.z, - "language" = speaking, "verb" = verb ) signal.frequency = connection.frequency // Quick frequency set @@ -522,15 +520,14 @@ var/global/list/default_medbay_channels = list( if(!connection) return 0 //~Carn return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), - src, message, displayname, jobname, real_name, M.voice_name, - filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking) + src, message_pieces, displayname, jobname, real_name, M.voice_name, + filter_type, signal.data["compression"], list(position.z), connection.frequency,verb) -/obj/item/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null) - +/obj/item/radio/hear_talk(mob/M as mob, list/message_pieces, var/verb = "says") if(broadcasting) if(get_dist(src, M) <= canhear_range) - talk_into(M, msg,null,verb,speaking) + talk_into(M, message_pieces, null, verb) /* diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index aece125c657..cf05ceb0bac 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -5,7 +5,6 @@ DETECTIVE SCANNER HEALTH ANALYZER GAS ANALYZER PLANT ANALYZER -MASS SPECTROMETER REAGENT SCANNER */ /obj/item/t_scanner @@ -432,95 +431,9 @@ REAGENT SCANNER amount += inaccurate return DisplayTimeText(max(1, amount)) -/obj/item/mass_spectrometer - desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample. Inject sample with syringe." - name = "mass-spectrometer" - icon = 'icons/obj/device.dmi' - icon_state = "spectrometer" - item_state = "analyzer" - w_class = WEIGHT_CLASS_SMALL - flags = CONDUCT - container_type = OPENCONTAINER - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - materials = list(MAT_METAL=150, MAT_GLASS=100) - origin_tech = "magnets=2;biotech=1;plasmatech=2" - var/details = 0 - var/datatoprint = "" - var/scanning = TRUE - actions_types = list(/datum/action/item_action/print_report) - -/obj/item/mass_spectrometer/New() - ..() - create_reagents(5) - -/obj/item/mass_spectrometer/on_reagent_change() - if(reagents.total_volume) - icon_state = initial(icon_state) + "_s" - else - icon_state = initial(icon_state) - -/obj/item/mass_spectrometer/attack_self(mob/user as mob) - if(user.stat) - return - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return - if(reagents.total_volume) - var/list/blood_traces = list() - for(var/datum/reagent/R in reagents.reagent_list) - if(R.id != "blood") - to_chat(user, "The sample was contaminated! Please insert another sample.") - reagents.clear_reagents() - return - else - blood_traces = params2list(R.data["trace_chem"]) - break - var/dat = "" - for(var/R in blood_traces) - if(details) - dat += "[R] ([blood_traces[R]] units) " - else - dat += "[R] " - to_chat(user, "Analysis completed. Chemicals found: [dat]") - scanning = FALSE - datatoprint = dat - reagents.clear_reagents() - return - -/obj/item/mass_spectrometer/adv - name = "advanced mass-spectrometer" - icon_state = "adv_spectrometer" - details = 1 - origin_tech = "magnets=4;biotech=3;plasmatech=3" - -/obj/item/mass_spectrometer/proc/print_report() - if(!scanning) - scanning = TRUE - usr.visible_message("[src] rattles and prints out a sheet of paper.") - playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) - sleep(50) - - var/obj/item/paper/P = new(get_turf(src)) - P.name = "Mass Spectrometer Scanner Report: [station_time_timestamp()]" - P.info = "
Mass Spectrometer

Data Analysis:



Trace chemicals detected:
[datatoprint]

" - - if(ismob(loc)) - var/mob/M = loc - M.put_in_hands(P) - to_chat(M, "Report printed. Log cleared.") - datatoprint = "" - else - to_chat(usr, "[src] has no logs or is already in use.") - -/obj/item/mass_spectrometer/ui_action_click() - print_report() - /obj/item/reagent_scanner name = "reagent scanner" - desc = "A hand-held reagent scanner which identifies chemical agents." + desc = "A hand-held reagent scanner which identifies chemical agents and blood types." icon = 'icons/obj/device.dmi' icon_state = "spectrometer" item_state = "analyzer" @@ -532,9 +445,9 @@ REAGENT SCANNER throw_range = 20 materials = list(MAT_METAL=30, MAT_GLASS=20) origin_tech = "magnets=2;biotech=1;plasmatech=2" - var/details = 0 + var/details = FALSE var/datatoprint = "" - var/scanning = 1 + var/scanning = TRUE actions_types = list(/datum/action/item_action/print_report) /obj/item/reagent_scanner/afterattack(obj/O, mob/user as mob) @@ -548,14 +461,19 @@ REAGENT SCANNER if(!isnull(O.reagents)) var/dat = "" + var/blood_type = "" if(O.reagents.reagent_list.len > 0) var/one_percent = O.reagents.total_volume / 100 for(var/datum/reagent/R in O.reagents.reagent_list) - dat += "
[TAB][R][details ? ": [R.volume / one_percent]%" : ""]" + if(R.id != "blood") + dat += "
[TAB][R][details ? ": [R.volume / one_percent]%" : ""]" + else + blood_type = R.data["blood_type"] + dat += "
[TAB][R][blood_type ? " [blood_type]" : ""][details ? ": [R.volume / one_percent]%" : ""]" if(dat) to_chat(user, "Chemicals found: [dat]") datatoprint = dat - scanning = 0 + scanning = FALSE else to_chat(user, "No active chemical agents found in [O].") else @@ -565,7 +483,7 @@ REAGENT SCANNER /obj/item/reagent_scanner/adv name = "advanced reagent scanner" icon_state = "adv_spectrometer" - details = 1 + details = TRUE origin_tech = "magnets=4;biotech=3;plasmatech=3" /obj/item/reagent_scanner/proc/print_report() @@ -583,7 +501,7 @@ REAGENT SCANNER M.put_in_hands(P) to_chat(M, "Report printed. Log cleared.") datatoprint = "" - scanning = 1 + scanning = TRUE else to_chat(usr, "[src] has no logs or is already in use.") @@ -673,7 +591,7 @@ REAGENT SCANNER icon_state = "bodyanalyzer_1" else icon_state = "bodyanalyzer_2" - + var/overlayid = round(percent / 10) overlayid = "bodyanalyzer_charge[overlayid]" overlays += icon(icon, overlayid) @@ -684,18 +602,18 @@ REAGENT SCANNER /obj/item/bodyanalyzer/attack(mob/living/M, mob/living/carbon/human/user) if(user.incapacitated() || !user.Adjacent(M)) return - + if(!ready) to_chat(user, "The scanner beeps angrily at you! It's currently recharging - [round((time_to_use - world.time) * 0.1)] seconds remaining.") playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1) return - + if(power_supply.charge >= usecharge) mobScan(M, user) else to_chat(user, "The scanner beeps angrily at you! It's out of charge!") playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1) - + /obj/item/bodyanalyzer/proc/mobScan(mob/living/M, mob/user) if(ishuman(M)) var/report = generate_printing_text(M, user) @@ -721,12 +639,12 @@ REAGENT SCANNER time_to_use = world.time + 600 else to_chat(user, "Scanning error detected. Invalid specimen.") - + //Unashamedly ripped from adv_med.dm /obj/item/bodyanalyzer/proc/generate_printing_text(mob/living/M, mob/user) var/dat = "" var/mob/living/carbon/human/target = M - + dat = "Target Statistics:
" var/t1 switch(target.stat) // obvious, see what their status is @@ -881,5 +799,5 @@ REAGENT SCANNER dat += "Photoreceptor abnormalities detected.
" if(target.disabilities & NEARSIGHTED) dat += "Retinal misalignment detected.
" - + return dat diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 9b36b70fdf2..4eaf0e79dce 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -85,7 +85,8 @@ icon_state = "taperecorder_idle" -/obj/item/taperecorder/hear_talk(mob/living/M as mob, msg) +/obj/item/taperecorder/hear_talk(mob/living/M as mob, list/message_pieces) + var/msg = multilingual_to_message(message_pieces) if(mytape && recording) var/ending = copytext(msg, length(msg)) mytape.timestamp += mytape.used_capacity diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index dbd7701ce93..371c6248a6e 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -75,10 +75,10 @@ return attached_device.HasProximity(AM) -/obj/item/transfer_valve/hear_talk(mob/living/M, msg) +/obj/item/transfer_valve/hear_talk(mob/living/M, list/message_pieces) ..() for(var/obj/O in contents) - O.hear_talk(M, msg) + O.hear_talk(M, message_pieces) /obj/item/transfer_valve/hear_message(mob/living/M, msg) ..() diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 1c3124a74cb..d0c0622d1e5 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -109,7 +109,7 @@ var/list/world_uplinks = list() var/list/random_items = new for(var/IR in ItemsReference) var/datum/uplink_item/UI = ItemsReference[IR] - if(UI.cost <= uses) + if(UI.cost <= uses && UI.limited_stock != 0) random_items += UI return pick(random_items) @@ -132,7 +132,12 @@ var/list/world_uplinks = list() /obj/item/uplink/proc/buy(var/datum/uplink_item/UI, var/reference) if(!UI) return + if(UI.limited_stock == 0) + to_chat(usr, "You have redeemed this discount already.") + return UI.buy(src,usr) + if(UI.limited_stock > 0) // only decrement it if it's actually limited + UI.limited_stock-- SSnanoui.update_uis(src) /* var/list/L = UI.spawn_item(get_turf(usr),src) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 165a61baa75..1143954faef 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -18,35 +18,21 @@ hitsound = null throwforce = 3 w_class = WEIGHT_CLASS_TINY + var/list/honk_sounds = list('sound/items/bikehorn.ogg' = 1) throw_speed = 3 throw_range = 15 attack_verb = list("HONKED") - var/spam_flag = 0 - var/honk_sound = 'sound/items/bikehorn.ogg' - var/cooldowntime = 20 - -/obj/item/bikehorn/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!spam_flag) - playsound(loc, honk_sound, 50, 1, -1) //plays instead of tap.ogg! - return ..() - -/obj/item/bikehorn/attack_self(mob/user) - if(!spam_flag) - spam_flag = 1 - playsound(src.loc, honk_sound, 50, 1) - src.add_fingerprint(user) - spawn(cooldowntime) - spam_flag = 0 - return +/obj/item/bikehorn/Initialize() + . = ..() + AddComponent(/datum/component/squeak, honk_sounds, 50) /obj/item/bikehorn/airhorn name = "air horn" desc = "Damn son, where'd you find this?" icon_state = "air_horn" - honk_sound = 'sound/items/AirHorn2.ogg' - cooldowntime = 50 origin_tech = "materials=4;engineering=4" + honk_sounds = list('sound/items/airhorn2.ogg' = 1) /obj/item/bikehorn/golden name = "golden bike horn" @@ -63,11 +49,10 @@ ..() /obj/item/bikehorn/golden/proc/flip_mobs(mob/living/carbon/M, mob/user) - if(!spam_flag) - var/turf/T = get_turf(src) - for(M in ohearers(7, T)) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(!H.can_hear()) - continue - M.emote("flip") + var/turf/T = get_turf(src) + for(M in ohearers(7, T)) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(!H.can_hear()) + continue + M.emote("flip") diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 8419f0b7537..2f5b48ff329 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -247,9 +247,9 @@ if(nadeassembly) nadeassembly.on_found(finder) -/obj/item/grenade/chem_grenade/hear_talk(mob/living/M, msg) +/obj/item/grenade/chem_grenade/hear_talk(mob/living/M, list/message_pieces) if(nadeassembly) - nadeassembly.hear_talk(M, msg) + nadeassembly.hear_talk(M, message_pieces) /obj/item/grenade/chem_grenade/hear_message(mob/living/M, msg) if(nadeassembly) diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 56205b17997..86160328891 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -11,6 +11,7 @@ var/reskinned = FALSE var/reskin_selectable = TRUE //set to FALSE if a subtype is meant to not normally be available as a reskin option (fluff ones will get re-added through their list) var/list/fluff_transformations = list() //does it have any special transformations only accessible to it? Should only be subtypes of /obj/item/nullrod + var/sanctify_force = 0 /obj/item/nullrod/suicide_act(mob/user) user.visible_message("[user] is killing [user.p_them()]self with \the [src.name]! It looks like [user.p_theyre()] trying to get closer to god!") @@ -25,12 +26,29 @@ to_chat(M, "The nullrod's power interferes with your own!") M.mind.vampire.nullified = max(5, M.mind.vampire.nullified + 2) +/obj/item/nullrod/pickup(mob/living/user) + . = ..() + if(sanctify_force) + if(!user.mind || !user.mind.isholy) + user.adjustBruteLoss(force) + user.adjustFireLoss(sanctify_force) + user.Weaken(5) + user.unEquip(src, 1) + user.visible_message("[src] slips out of the grip of [user] as they try to pick it up, bouncing upwards and smacking [user.p_them()] in the face!", \ + "[src] slips out of your grip as you pick it up, bouncing upwards and smacking you in the face!") + playsound(get_turf(user), 'sound/effects/hit_punch.ogg', 50, 1, -1) + throw_at(get_edge_target_turf(user, pick(alldirs)), rand(1, 3), 5) + + /obj/item/nullrod/attack_self(mob/user) - if(reskinned) - return - if(user.mind && (user.mind.assigned_role == "Chaplain" || user.mind.special_role == SPECIAL_ROLE_ERT)) + if(user.mind && (user.mind.isholy) && !reskinned) reskin_holy_weapon(user) +/obj/item/nullrod/examine(mob/living/user) + . = ..() + if(sanctify_force) + to_chat(user, "It bears the inscription: 'Sanctified weapon of the inquisitors. Only the worthy may wield. Nobody shall expect us.'") + /obj/item/nullrod/proc/reskin_holy_weapon(mob/M) var/list/holy_weapons_list = typesof(/obj/item/nullrod) for(var/entry in holy_weapons_list) @@ -60,11 +78,27 @@ holy_weapon.reskinned = TRUE M.unEquip(src) M.put_in_active_hand(holy_weapon) + if(sanctify_force) + holy_weapon.sanctify_force = sanctify_force + holy_weapon.name = "sanctified " + holy_weapon.name qdel(src) -/obj/item/nullrod/fluff //fluff subtype to be used for all donator nullrods +/obj/item/nullrod/afterattack(atom/movable/AM, mob/user, proximity) + . = ..() + if(!sanctify_force) + return + if(isliving(AM)) + var/mob/living/L = AM + L.adjustFireLoss(sanctify_force) // Bonus fire damage for sanctified (ERT) versions of nullrod + +/obj/item/nullrod/fluff // fluff subtype to be used for all donator nullrods reskin_selectable = FALSE +/obj/item/nullrod/ert // ERT subtype, applies sanctified property to any derived rod + name = "inquisitor null rod" + reskin_selectable = FALSE + sanctify_force = 10 + /obj/item/nullrod/godhand name = "god hand" icon_state = "disintegrate" @@ -126,7 +160,7 @@ hitsound = 'sound/weapons/chainsaw.ogg' /obj/item/nullrod/claymore/glowing - name = "force weapon" + name = "force blade" icon_state = "swordon" item_state = "swordon" desc = "The blade glows with the power of faith. Or possibly a battery." @@ -147,7 +181,7 @@ slot_flags = SLOT_BELT /obj/item/nullrod/claymore/saber - name = "light energy sword" + name = "light energy blade" hitsound = 'sound/weapons/blade1.ogg' icon_state = "swordblue" item_state = "swordblue" @@ -155,13 +189,13 @@ slot_flags = SLOT_BELT /obj/item/nullrod/claymore/saber/red - name = "dark energy sword" + name = "dark energy blade" icon_state = "swordred" item_state = "swordred" desc = "Woefully ineffective when used on steep terrain." /obj/item/nullrod/claymore/saber/pirate - name = "nautical energy sword" + name = "nautical energy cutlass" icon_state = "cutlass1" item_state = "cutlass1" desc = "Convincing HR that your religion involved piracy was no mean feat." @@ -279,7 +313,7 @@ /obj/item/nullrod/whip name = "holy whip" - desc = "What a terrible night to be in spess" + desc = "A whip, blessed with the power to banish evil shadowy creatures. What a terrible night to be in spess." icon_state = "chain" item_state = "chain" slot_flags = SLOT_BELT @@ -298,11 +332,11 @@ if(is_shadow(H)) var/phrase = pick("Die monster! You don't belong in this world!!!", "You steal men's souls and make them your slaves!!!", "Your words are as empty as your soul!!!", "Mankind ill needs a savior such as you!!!") user.say("[phrase]") - H.adjustBruteLoss(8) //Bonus damage + H.adjustBruteLoss(12) //Bonus damage /obj/item/nullrod/fedora - name = "athiest's fedora" - desc = "The brim of the hat is as sharp as your wit. Throwing it at someone would hurt almost as much as disproving the existence of God." + name = "binary fedora" + desc = "The brim of the hat is as sharp as the division between 0 and 1. It makes a mighty throwing weapon." icon_state = "fedora" item_state = "fedora" slot_flags = SLOT_HEAD @@ -310,7 +344,7 @@ force = 0 throw_speed = 4 throw_range = 7 - throwforce = 20 + throwforce = 25 // Yes, this is high, since you can typically only use it once in a fight. /obj/item/nullrod/armblade name = "dark blessing" @@ -335,7 +369,7 @@ /obj/item/nullrod/carp/attack_self(mob/living/user) if(used_blessing) return - if(user.mind && (user.mind.assigned_role != "Chaplain" && user.mind.special_role != SPECIAL_ROLE_ERT)) + if(user.mind && !user.mind.isholy) return to_chat(user, "You are blessed by Carp-Sie. Wild space carp will no longer attack you.") user.faction |= "carp" @@ -408,7 +442,7 @@ if(!iscarbon(M)) return ..() - if(!user.mind || (user.mind.assigned_role != "Chaplain" && user.mind.special_role != SPECIAL_ROLE_ERT)) + if(!user.mind || !user.mind.isholy) to_chat(user, "You are not close enough with [ticker.Bible_deity_name] to use [src].") return @@ -420,7 +454,7 @@ praying = 1 if(do_after(user, 150, target = M)) - if(ishuman(M)) // This probably should not work on vulps. They're unholy abominations. + if(ishuman(M)) var/mob/living/carbon/human/target = M if(target.mind) @@ -470,7 +504,7 @@ /obj/item/nullrod/salt/attack_self(mob/user) - if(!user.mind || (user.mind.assigned_role != "Chaplain" && user.mind.special_role != SPECIAL_ROLE_ERT )) + if(!user.mind || !user.mind.isholy) to_chat(user, "You are not close enough with [ticker.Bible_deity_name] to use [src].") return diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 03787385e1c..16ecd7cc72c 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -38,10 +38,6 @@ return /obj/item/storage/bible/attack(mob/living/M as mob, mob/living/user as mob) - var/chaplain = 0 - if(user.mind && (user.mind.assigned_role == "Chaplain")) - chaplain = 1 - add_attack_logs(user, M, "Hit with [src]") if(!iscarbon(user)) M.LAssailant = null @@ -51,7 +47,7 @@ if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") to_chat(user, "You don't have the dexterity to do this!") return - if(!chaplain) + if(!user.mind || !user.mind.isholy) to_chat(user, "The book sizzles in your hands.") user.take_organ_damage(0,10) return @@ -62,14 +58,7 @@ user.Paralyse(20) return -// if(..() == BLOCKED) -// return - if(M.stat !=2) - /*if((M.mind in ticker.mode.cult) && (prob(20))) - to_chat(M, "The power of [src.deity_name] clears your mind of heresy!") - to_chat(user, "You see how [M]'s eyes become clear, the cult no longer holds control over [M.p_them()]!") - ticker.mode.remove_cultist(M.mind)*/ if((istype(M, /mob/living/carbon/human) && prob(60))) bless(M) for(var/mob/O in viewers(M, null)) @@ -94,11 +83,11 @@ return if(istype(A, /turf/simulated/floor)) to_chat(user, "You hit the floor with the bible.") - if(user.mind && (user.mind.assigned_role == "Chaplain")) + if(user.mind && (user.mind.isholy)) for(var/obj/effect/rune/R in A) if(R.invisibility) R.talismanreveal() - if(user.mind && (user.mind.assigned_role == "Chaplain")) + if(user.mind && (user.mind.isholy)) if(A.reagents && A.reagents.has_reagent("water")) //blesses all the water in the holder to_chat(user, "You bless [A].") var/water2holy = A.reagents.get_reagent_amount("water") diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 9d0289f7fc3..1d23049064f 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -879,7 +879,9 @@ /obj/item/storage/box/centcomofficer name = "officer kit" icon_state = "box_ert" - + storage_slots = 14 + max_combined_w_class = 20 + /obj/item/storage/box/centcomofficer/New() ..() contents = list() @@ -893,7 +895,8 @@ new /obj/item/implanter/death_alarm(src) new /obj/item/reagent_containers/hypospray/combat/nanites(src) - new /obj/item/pinpointer/advpinpointer(src) + new /obj/item/pinpointer(src) + new /obj/item/pinpointer/crew/centcom(src) /obj/item/storage/box/responseteam name = "boxed survival kit" diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 3bed8e15333..f484d8c001b 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -158,6 +158,28 @@ /obj/item/storage/firstaid/adv/empty empty = 1 +/obj/item/storage/firstaid/machine + name = "machine repair kit" + desc = "A kit that contains supplies to repair IPCs on the go." + icon_state = "machinefirstaid" + item_state = "firstaid-machine" + med_bot_skin = "machine" + +/obj/item/storage/firstaid/machine/New() + ..() + if(empty) + return + new /obj/item/weldingtool(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/reagent_containers/food/drinks/oilcan/full(src) + new /obj/item/robotanalyzer(src) + +/obj/item/storage/firstaid/machine/empty + empty = 1 + + /obj/item/storage/firstaid/tactical name = "first-aid kit" icon_state = "bezerk" diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index d461700695d..c080715a035 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -67,7 +67,7 @@ origin_tech = null //wipe out any origin tech if it's unlocked in any way so you can't double-dip tech levels at R&D. return -/obj/item/storage/lockbox/hear_talk(mob/living/M as mob, msg) +/obj/item/storage/lockbox/hear_talk(mob/living/M as mob, list/message_pieces) /obj/item/storage/lockbox/hear_message(mob/living/M as mob, msg) diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index 0a256136d2e..aeaa7991420 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -158,7 +158,7 @@ to_chat(usr, "[src] is locked!") return 0 -/obj/item/storage/secure/hear_talk(mob/living/M as mob, msg) +/obj/item/storage/secure/hear_talk(mob/living/M as mob, list/message_pieces) return /obj/item/storage/secure/hear_message(mob/living/M as mob, msg) @@ -214,14 +214,6 @@ for(var/i = 0, i < storage_slots - 2, i++) handle_item_insertion(new /obj/item/stack/spacecash/c1000, 1) -/obj/item/storage/secure/briefcase/reaper/New() - ..() - handle_item_insertion(new /obj/item/gun/energy/kinetic_accelerator/crossbow, 1) - handle_item_insertion(new /obj/item/gun/projectile/revolver/mateba, 1) - handle_item_insertion(new /obj/item/ammo_box/a357, 1) - handle_item_insertion(new /obj/item/grenade/plastic/c4, 1) - - // ----------------------------- // Secure Safe // ----------------------------- diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 2d7c6842547..99590fe1d13 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -473,10 +473,10 @@ O.emp_act(severity) ..() -/obj/item/storage/hear_talk(mob/living/M as mob, msg) +/obj/item/storage/hear_talk(mob/living/M as mob, list/message_pieces) ..() for(var/obj/O in contents) - O.hear_talk(M, msg) + O.hear_talk(M, message_pieces) /obj/item/storage/hear_message(mob/living/M as mob, msg) ..() diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 3a821264822..8f72b7c9e04 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -215,6 +215,13 @@ new /obj/item/ammo_casing/shotgun/dart/assassination(src) new /obj/item/gun/projectile/revolver/doublebarrel/improvised/cane(src) +/obj/item/storage/box/syndie_kit/mimery + name = "advanced mimery kit" + +/obj/item/storage/box/syndie_kit/mimery/New() + ..() + new /obj/item/spellbook/oneuse/mime/greaterwall(src) + new /obj/item/spellbook/oneuse/mime/fingergun(src) /obj/item/storage/box/syndie_kit/atmosgasgrenades name = "Atmos Grenades" diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 231645ed758..f16ca21682f 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -166,6 +166,8 @@ if(ishuman(L)) var/mob/living/carbon/human/H = L + if(check_martial_counter(L, user)) + return if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that playsound(L, 'sound/weapons/Genhit.ogg', 50, 1) return diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index cc2fa8d1d69..f13806b90f1 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -173,7 +173,7 @@ return -/obj/proc/hear_talk(mob/M as mob, text) +/obj/proc/hear_talk(mob/M, list/message_pieces) return /obj/proc/hear_message(mob/M as mob, text) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/chaplain.dm b/code/game/objects/structures/crates_lockers/closets/secure/chaplain.dm index 0a44e818264..5287397a3e9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/chaplain.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/chaplain.dm @@ -20,9 +20,10 @@ new /obj/item/clothing/head/witchhunter_hat(src) new /obj/item/clothing/suit/holidaypriest(src) new /obj/item/clothing/under/wedding/bride_white(src) - new /obj/item/storage/backpack/cultpack (src) + new /obj/item/storage/backpack/cultpack(src) new /obj/item/clothing/head/helmet/riot/knight/templar(src) new /obj/item/clothing/suit/armor/riot/knight/templar(src) + new /obj/item/soulstone/anybody/chaplain(src) new /obj/item/storage/fancy/candle_box/eternal(src) new /obj/item/storage/fancy/candle_box/eternal(src) new /obj/item/storage/fancy/candle_box/eternal(src) diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 3c4875978a2..32b2bfcce40 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -194,6 +194,28 @@ return TRUE else current_action = 0 + if(iswelder(W)) + var/obj/item/weldingtool/WT = W + if(!WT.remove_fuel(0, user)) + return + to_chat(user, "You begin cutting [src] apart...") + playsound(loc, WT.usesound, 40, 1) + if(do_after(user, 150 * WT.toolspeed, 1, target = src)) + if(!WT.isOn()) + return + playsound(loc, WT.usesound, 50, 1) + visible_message("[user] slices apart [src].", + "You cut [src] apart with [WT].", + "You hear welding.") + var/turf/T = get_turf(src) + if(blade_sharpness == GUILLOTINE_BLADE_MAX_SHARP) + new /obj/item/stack/sheet/plasteel(T, 3) + else + new /obj/item/stack/sheet/plasteel(T, 2) //prevents reconstructing to sharpen the guillotine without additional plasteel + new /obj/item/stack/sheet/wood(T, 20) + new /obj/item/stack/cable_coil(T, 10) + qdel(src) + return else return ..() diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index a2b438c10d2..8e9b478382a 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -312,7 +312,7 @@ GLOBAL_LIST_EMPTY(safes) /obj/structure/safe/Destroy() GLOB.safes -= src - drill.soundloop.stop() + drill?.soundloop?.stop() return ..() /obj/structure/safe/process() diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 14ef2b08f2b..ba015c843fa 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -172,31 +172,24 @@ if(exposed_temperature > 300) PlasmaBurn(exposed_temperature) -/obj/structure/statue/plasma/bullet_act(obj/item/projectile/Proj) - var/burn = FALSE - if(Proj.damage == 0)//lasertag guns and so on don't set off plasma anymore. can't use nodamage here because lasertag guns actually don't have it. - return - if(istype(Proj,/obj/item/projectile/beam)) - PlasmaBurn(2500) - burn = TRUE - else if(istype(Proj,/obj/item/projectile/ion)) - PlasmaBurn(500) - burn = TRUE - if(burn) - if(Proj.firer) - message_admins("Plasma statue ignited by [key_name_admin(Proj.firer)]([ADMIN_QUE(Proj.firer,"?")]) ([ADMIN_FLW(Proj.firer,"FLW")]) in ([x],[y],[z] - JMP)",0,1) - log_game("Plasma statue ignited by [key_name(Proj.firer)] in ([x],[y],[z])") - investigate_log("was ignited by [key_name(Proj.firer)]","atmos") - else - message_admins("Plasma statue ignited by [Proj]. No known firer.([ADMIN_QUE(Proj.firer,"?")]) ([ADMIN_FLW(Proj.firer,"FLW")]) in ([x],[y],[z] - JMP)",0,1) - log_game("Plasma statue ignited by [Proj] in ([x],[y],[z]). No known firer.") +/obj/structure/statue/plasma/bullet_act(obj/item/projectile/P) + if(!QDELETED(src)) //wasn't deleted by the projectile's effects. + if(!P.nodamage && ((P.damage_type == BURN) || (P.damage_type == BRUTE))) + if(P.firer) + message_admins("[key_name_admin(P.firer)] ignited a plasma statue with [P.name] at [COORD(loc)]") + log_game("[key_name(P.firer)] ignited a plasma statue with [P.name] at [COORD(loc)]") + investigate_log("[key_name(P.firer)] ignited a plasma statue with [P.name] at [COORD(loc)]", "atmos") + else + message_admins("A plasma statue was ignited with [P.name] at [COORD(loc)]. No known firer.") + log_game("A plasma statue was ignited with [P.name] at [COORD(loc)]. No known firer.") + PlasmaBurn() ..() /obj/structure/statue/plasma/attackby(obj/item/W, mob/user, params) if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite - message_admins("Plasma statue ignited by [key_name_admin(user)]([ADMIN_QUE(user,"?")]) ([ADMIN_FLW(user,"FLW")]) in ([x],[y],[z] - JMP)",0,1) - log_game("Plasma statue ignited by [key_name(user)] in ([x],[y],[z])") - investigate_log("was ignited by [key_name(user)]","atmos") + message_admins("[key_name_admin(user)] ignited a plasma statue at [COORD(loc)]") + log_game("[key_name(user)] ignited plasma a statue at [COORD(loc)]") + investigate_log("[key_name(user)] ignited a plasma statue at [COORD(loc)]", "atmos") ignite(is_hot(W)) return ..() diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index e657e9f8538..b48774eb046 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -507,10 +507,8 @@ icon = 'icons/obj/watercloset.dmi' icon_state = "rubberducky" item_state = "rubberducky" + honk_sounds = list('sound/items/squeaktoy.ogg' = 1) attack_verb = list("quacked", "squeaked") - honk_sound = 'sound/items/squeaktoy.ogg' //credit to DANMITCH3LL of freesound for this - - /obj/structure/sink name = "sink" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d7ed44c3c9a..7eb81c589e1 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -136,6 +136,7 @@ /turf/Entered(atom/movable/M, atom/OL, ignoreRest = 0) + ..() if(ismob(M)) var/mob/O = M if(!O.lastarea) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 841cfb69036..5c6bf7038a1 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1699,7 +1699,7 @@ if(!istype(H)) to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") return - var/etypes = list("Borgification","Corgification","Death By Fire","Total Brain Death","Honk Tumor","Cluwne","Demotion Notice") + var/etypes = list("Borgification", "Corgification", "Death By Fire", "Total Brain Death", "Honk Tumor", "Cluwne", "Demote", "Demote with Bot", "Revoke Fax Access", "Angry Fax Machine") var/eviltype = input(src.owner, "Which type of evil fax do you wish to send [H]?","Its good to be baaaad...", "") as null|anything in etypes if(!(eviltype in etypes)) return @@ -1733,8 +1733,8 @@ P.overlays += stampoverlay P.stamps += "
" P.update_icon() - //fax.receivefax(P) // this does not work, it does not preserve the type, we have to physically teleport the fax paper instead - P.loc = fax.loc + P.faxmachineid = fax.UID() + P.loc = fax.loc // Do not use fax.receivefax(P) here, as it won't preserve the type. Physically teleporting the fax paper is required. if(istype(H) && H.stat == CONSCIOUS && (istype(H.l_ear, /obj/item/radio/headset) || istype(H.r_ear, /obj/item/radio/headset))) to_chat(H, "Your headset pings, notifying you that a reply to your fax has arrived.") to_chat(src.owner, "You sent a [eviltype] fax to [H]") @@ -1756,7 +1756,8 @@ btypes += "Super Powers" btypes += "Scarab Guardian" btypes += "Human Protector" - btypes += "Pet" + btypes += "Sentient Pet" + btypes += "All Access" var/blessing = input(owner, "How would you like to bless [M]?", "Its good to be good...", "") as null|anything in btypes if(!(blessing in btypes)) return @@ -1806,28 +1807,56 @@ spawn(700) qdel(scarab) logmsg = "scarab guardian." - if("Pet") - var/pets = subtypesof(/mob/living/simple_animal/pet) + if("Sentient Pet") + var/pets = subtypesof(/mob/living/simple_animal) var/petchoice = input("Select pet type", "Pets") as null|anything in pets if(isnull(petchoice)) return - var/mob/living/simple_animal/pet/P = new petchoice(H.loc) - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [P], pet of [H]?", poll_time = 100, min_hours = 10) + var/list/mob/dead/observer/candidates = pollCandidates("Play as the special event pet [H]?", poll_time = 200, min_hours = 10) var/mob/dead/observer/theghost = null if(candidates.len) + var/mob/living/simple_animal/pet/P = new petchoice(H.loc) theghost = pick(candidates) P.key = theghost.key P.master_commander = H + P.universal_speak = 1 + P.universal_understand = 1 + P.can_collar = 1 + P.faction = list("neutral") + var/obj/item/clothing/accessory/petcollar/C = new /obj/item/clothing/accessory/petcollar(P) + P.collar = C + C.equipped(P) + var/obj/item/card/id/I = H.wear_id + if(I) + var/obj/item/card/id/D = new /obj/item/card/id(C) + D.access = I.access + D.registered_name = P.name + D.assignment = "Pet" + C.access_id = D spawn(30) - var/newname = sanitize(copytext(input(P, "You are [P], pet of [H]. Would you like to change your name to something else?", "Name change", P.name) as null|text,1,MAX_NAME_LEN)) + var/newname = sanitize(copytext(input(P, "You are [P], special event pet of [H]. Change your name to something else?", "Name change", P.name) as null|text,1,MAX_NAME_LEN)) if(newname && newname != P.name) P.name = newname if(P.mind) P.mind.name = newname - logmsg = "pet ([P])." + logmsg = "pet ([P])." + else + to_chat(usr, "WARNING: Nobody volunteered to play the special event pet.") + logmsg = "pet (no volunteers)." if("Human Protector") usr.client.create_eventmob_for(H, 0) logmsg = "syndie protector." + if("All Access") + var/obj/item/card/id/I = H.wear_id + if(I) + var/list/access_to_give = get_all_accesses() + for(var/this_access in access_to_give) + if(!(this_access in I.access)) + // don't have it - add it + I.access |= this_access + else + to_chat(usr, "ERROR: [H] is not wearing an ID card.") + logmsg = "all access." if(logmsg) log_admin("[key_name(owner)] answered [key_name(M)]'s prayer with a blessing: [logmsg]") message_admins("[key_name_admin(owner)] answered [key_name_admin(M)]'s prayer with a blessing: [logmsg]") @@ -1850,10 +1879,10 @@ ptypes += "Cluwne" ptypes += "Mutagen Cookie" ptypes += "Hellwater Cookie" - ptypes += "Assassin" ptypes += "Hunter" ptypes += "Crew Traitor" ptypes += "Floor Cluwne" + ptypes += "Shamebrero" var/punishment = input(owner, "How would you like to smite [M]?", "Its good to be baaaad...", "") as null|anything in ptypes if(!(punishment in ptypes)) return @@ -1866,15 +1895,19 @@ M.Weaken(5) to_chat(M, "The gods have punished you for your sins!") logmsg = "a lightning bolt." - if("Brain Damage") - H.adjustBrainLoss(75) - logmsg = "75 brain damage." if("Fire Death") to_chat(M,"You feel hotter than usual. Maybe you should lowe-wait, is that your hand melting?") var/turf/simulated/T = get_turf(M) new /obj/effect/hotspot(T) M.adjustFireLoss(150) logmsg = "a firey death." + if("Gib") + M.gib(FALSE) + logmsg = "gibbed." + + if("Brain Damage") + H.adjustBrainLoss(75) + logmsg = "75 brain damage." if("Honk Tumor") if(!H.get_int_organ(/obj/item/organ/internal/honktumor)) var/obj/item/organ/internal/organ = new /obj/item/organ/internal/honktumor @@ -1884,14 +1917,16 @@ if("Hallucinate") H.Hallucinate(1000) logmsg = "hallucinations." - if("Hunger") - H.nutrition = NUTRITION_LEVEL_CURSED - logmsg = "starvation." if("Cold") H.reagents.add_reagent("frostoil", 40) H.reagents.add_reagent("ice", 40) + logmsg = "cold." + if("Hunger") + H.nutrition = NUTRITION_LEVEL_CURSED + logmsg = "starvation." if("Cluwne") H.makeCluwne() + H.mutations |= NOCLONE logmsg = "cluwned." if("Mutagen Cookie") var/obj/item/reagent_containers/food/snacks/cookie/evilcookie = new /obj/item/reagent_containers/food/snacks/cookie @@ -1912,11 +1947,10 @@ H.equip_to_slot_or_del(evilcookie, slot_l_hand) logmsg = "a hellwater cookie." if("Hunter") - logmsg = "hunter." H.mutations |= NOCLONE usr.client.create_eventmob_for(H, 1) + logmsg = "hunter." if("Crew Traitor") - logmsg = "crew traitor." var/list/possible_traitors = list() for(var/mob/living/player in GLOB.living_mob_list) if(player.client && player.mind && !player.mind.special_role && player.stat != DEAD && player != H) @@ -1947,29 +1981,22 @@ else to_chat(usr, "ERROR: Failed to create a traitor.") return - if("Lynch") - logmsg = "lynch." - for(var/datum/mind/crew in ticker.minds) - if(!crew.current) - continue - if(!isliving(crew.current)) - continue - if(crew == H.mind) - continue - to_chat(crew.current, "
The gods have given you a task: find [H.real_name], located in [get_area(H.loc)], and slay them!"); - to_chat(crew.current, "Do not harm anyone other than [H.real_name] while carrying out this task.
"); - if("Gib") - logmsg = "gibbed." - M.gib(FALSE) + logmsg = "crew traitor." if("Floor Cluwne") - logmsg = "floor cluwne" var/turf/T = get_turf(M) var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T) FC.smiting = TRUE FC.Acquire_Victim(M) + logmsg = "floor cluwne" + if("Shamebrero") + if(H.head) + H.unEquip(H.head, TRUE) + var/obj/item/clothing/head/sombrero/shamebrero/S = new(H.loc) + H.equip_to_slot_or_del(S, slot_head) + logmsg = "shamebrero" if(logmsg) - log_admin("[key_name(owner)] answered [key_name(M)]'s prayer with a smiting: [logmsg]") - message_admins("[key_name_admin(owner)] answered [key_name_admin(M)]'s prayer with a smiting: [logmsg]") + log_admin("[key_name(owner)] smited [key_name(M)] with: [logmsg]") + message_admins("[key_name_admin(owner)] smited [key_name_admin(M)] with: [logmsg]") else if(href_list["cryossd"]) if(!check_rights(R_ADMIN)) return diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index b92b304fd57..1c75421f4b7 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -3,7 +3,8 @@ set name = "Pray" msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)) - if(!msg) return + if(!msg) + return if(usr.client) if(usr.client.prefs.muted & MUTE_PRAY) @@ -29,7 +30,7 @@ deity = ticker.cultdat.entity_name log_say("(PRAYER) [msg]", usr) - msg = "[bicon(cross)][prayer_type][deity ? " (to [deity])" : ""]:[key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) (CA) ([ADMIN_SC(src,"SC")]) (BLESS) (SMITE): [msg]" + msg = "[bicon(cross)][prayer_type][deity ? " (to [deity])" : ""][mind && mind.isholy ? " (blessings: [mind.num_blessed])" : ""]: [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) (CA) ([ADMIN_SC(src,"SC")]) (BLESS) (SMITE): [msg]" for(var/client/X in GLOB.admins) if(check_rights(R_EVENT,0,X.mob)) diff --git a/code/modules/arcade/prize_datums.dm b/code/modules/arcade/prize_datums.dm index 7d8e90068c6..51356569af9 100644 --- a/code/modules/arcade/prize_datums.dm +++ b/code/modules/arcade/prize_datums.dm @@ -222,6 +222,12 @@ var/global/datum/prizes/global_prizes = new typepath = /obj/item/spellbook/oneuse/fake_gib cost = 100 +/datum/prize_item/fakefingergun + name = "Miming Manual : Finger Gun" + desc = "..." + typepath = /obj/item/spellbook/oneuse/mime/fingergun/fake + cost = 100 + /datum/prize_item/magic_conch name = "Magic Conch Shell" desc = "All hail the magic conch!" diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 25f9f6fe285..2c5a2d28883 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -85,9 +85,9 @@ if(bombassembly) bombassembly.on_found(finder) -/obj/item/onetankbomb/hear_talk(mob/living/M, msg) +/obj/item/onetankbomb/hear_talk(mob/living/M, list/message_pieces) if(bombassembly) - bombassembly.hear_talk(M, msg) + bombassembly.hear_talk(M, message_pieces) /obj/item/onetankbomb/hear_message(mob/living/M, msg) if(bombassembly) diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 19683743b3e..bc36a0543e8 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -98,11 +98,11 @@ a_right.on_found(finder) -/obj/item/assembly_holder/hear_talk(mob/living/M, msg) +/obj/item/assembly_holder/hear_talk(mob/living/M, list/message_pieces) if(a_left) - a_left.hear_talk(M, msg) + a_left.hear_talk(M, message_pieces) if(a_right) - a_right.hear_talk(M, msg) + a_right.hear_talk(M, message_pieces) /obj/item/assembly_holder/hear_message(mob/living/M, msg) if(a_left) diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm index e8462884cd4..3c7fdfa8fef 100644 --- a/code/modules/assembly/voice.dm +++ b/code/modules/assembly/voice.dm @@ -16,11 +16,11 @@ else return "[src] is deactivated." -/obj/item/assembly/voice/hear_talk(mob/living/M as mob, msg) - hear_input(M, msg, 0) +/obj/item/assembly/voice/hear_talk(mob/living/M as mob, list/message_pieces) + hear_input(M, multilingual_to_message(message_pieces), 0) /obj/item/assembly/voice/hear_message(mob/living/M as mob, msg) - hear_input(M, msg, 1) + hear_input(M, msg, 1) /obj/item/assembly/voice/proc/hear_input(mob/living/M as mob, msg, type) if(!istype(M,/mob/living)) @@ -68,7 +68,7 @@ /obj/item/assembly/voice/noise/describe() return "[src] does not appear to have any controls." -/obj/item/assembly/voice/noise/hear_talk(mob/living/M as mob, msg) +/obj/item/assembly/voice/noise/hear_talk(mob/living/M as mob, list/message_pieces) return /obj/item/assembly/voice/noise/hear_message(mob/living/M as mob, msg) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index bc6f7259ebc..855c092f3ae 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -411,6 +411,7 @@ BLIND // can't see anything ..() /obj/item/clothing/shoes/proc/step_action(var/mob/living/carbon/human/H) //squeek squeek + SEND_SIGNAL(src, COMSIG_SHOES_STEP_ACTION) if(shoe_sound) var/turf/T = get_turf(H) @@ -584,6 +585,10 @@ BLIND // can't see anything var/rolled_down = 0 var/basecolor +/obj/item/clothing/under/rank/New() + sensor_mode = pick(0,1,2,3) + ..() + /obj/item/clothing/under/Destroy() QDEL_LIST(accessories) return ..() @@ -687,34 +692,47 @@ BLIND // can't see anything else to_chat(usr, "You cannot roll down the uniform!") -/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A) - if(!(A in accessories)) - return - - A.on_removed(user) - accessories -= A - usr.update_inv_w_uniform() - /obj/item/clothing/under/verb/removetie() set name = "Remove Accessory" set category = "Object" set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - if(!accessories.len) return + handle_accessories_removal() + +/obj/item/clothing/under/proc/handle_accessories_removal() + if(!isliving(usr)) + return + if(usr.incapacitated()) + return + if(!Adjacent(usr)) + return + if(!accessories.len) + return var/obj/item/clothing/accessory/A if(accessories.len > 1) A = input("Select an accessory to remove from [src]") as null|anything in accessories else A = accessories[1] - src.remove_accessory(usr,A) + remove_accessory(usr,A) -/obj/item/clothing/under/rank/New() - sensor_mode = pick(0,1,2,3) - ..() +/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A) + if(!(A in accessories)) + return + if(!isliving(user)) + return + if(user.incapacitated()) + return + if(!Adjacent(user)) + return + A.on_removed(user) + accessories -= A + to_chat(user, "You remove [A] from [src].") + usr.update_inv_w_uniform() /obj/item/clothing/under/emp_act(severity) if(accessories.len) for(var/obj/item/clothing/accessory/A in accessories) A.emp_act(severity) ..() + +/obj/item/clothing/under/AltClick() + handle_accessories_removal() diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index c10ccf32f89..789215a0f19 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -80,12 +80,6 @@ to_chat(usr, "You lack the ability to manipulate the lock.") -/obj/item/clothing/mask/muzzle/gag - name = "gag" - desc = "Stick this in their mouth to stop the noise." - icon_state = "gag" - w_class = WEIGHT_CLASS_TINY - /obj/item/clothing/mask/muzzle/tapegag name = "tape gag" desc = "MHPMHHH!" @@ -182,9 +176,9 @@ trigger.HasProximity(AM) -/obj/item/clothing/mask/muzzle/safety/shock/hear_talk(mob/living/M as mob, msg) +/obj/item/clothing/mask/muzzle/safety/shock/hear_talk(mob/living/M as mob, list/message_pieces) if(trigger) - trigger.hear_talk(M, msg) + trigger.hear_talk(M, message_pieces) /obj/item/clothing/mask/muzzle/safety/shock/hear_message(mob/living/M as mob, msg) if(trigger) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 84b62bfd85c..304a7332bf6 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -10,6 +10,12 @@ var/list/clothing_choices = list() silence_steps = 1 +/obj/item/clothing/shoes/syndigaloshes/black + name = "black shoes" + icon_state = "black" + item_color = "black" + desc = "A pair of black shoes. They seem to have extra grip." + /obj/item/clothing/shoes/mime name = "mime shoes" icon_state = "mime" diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index dea27a5b946..ba61c78b368 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -69,6 +69,7 @@ armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75) allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/t_scanner, /obj/item/rcd) siemens_coefficient = 0 + actions_types = list(/datum/action/item_action/toggle_helmet) hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran") species_restricted = list("exclude","Diona","Wryn") @@ -156,6 +157,10 @@ H.unEquip(boots) boots.forceMove(src) +/obj/item/clothing/suit/space/hardsuit/ui_action_click() + ..() + toggle_helmet() + /obj/item/clothing/suit/space/hardsuit/verb/toggle_helmet() set name = "Toggle Helmet" set category = "Object" @@ -201,6 +206,9 @@ else to_chat(user, "You detach \the [helmet] from \the [src]'s helmet mount.") helmet.loc = get_turf(src) + if(istype(helmet,/obj/item/clothing/head/helmet/space/hardsuit/syndi)) + var/obj/item/clothing/head/helmet/space/hardsuit/syndi/S = helmet + S.linkedsuit = null src.helmet = null return if(!boots) @@ -221,7 +229,12 @@ to_chat(user, "You attach \the [W] to \the [src]'s helmet mount.") user.drop_item() W.loc = src - src.helmet = W + helmet = W + if(istype(helmet,/obj/item/clothing/head/helmet/space/hardsuit/syndi)) + var/obj/item/clothing/head/helmet/space/hardsuit/syndi/S = W + S.forceMove(src) + helmet = S + S.link_suit() return else if(istype(W,/obj/item/clothing/shoes/magboots) && can_modify(user)) @@ -312,6 +325,7 @@ item_color = "syndi" armor = list(melee = 40, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50) on = 1 + var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null actions_types = list(/datum/action/item_action/toggle_helmet_mode) flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDETAIL @@ -319,7 +333,17 @@ /obj/item/clothing/head/helmet/space/hardsuit/syndi/update_icon() icon_state = "hardsuit[on]-[item_color]" +/obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/link_suit() + . = ..() + if(istype(loc,/obj/item/clothing/suit/space/hardsuit/syndi)) + linkedsuit = loc + /obj/item/clothing/head/helmet/space/hardsuit/syndi/attack_self(mob/user) + + if(!linkedsuit) + to_chat(user, "You must attach the helmet to a syndicate hardsuit to toggle combat mode!") + return + on = !on if(on) to_chat(user, "You switch your helmet to travel mode. It will allow you to stand in zero pressure environments, at the cost of speed.") @@ -342,12 +366,38 @@ update_icon() playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) + toggle_hardsuit_mode(user) user.update_inv_head() for(var/X in actions) var/datum/action/A = X A.UpdateButtonIcon() +/obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/toggle_hardsuit_mode(mob/user) //Helmet Toggles Suit Mode + if(linkedsuit) + if(on) + linkedsuit.name = initial(linkedsuit.name) + linkedsuit.desc = initial(linkedsuit.desc) + linkedsuit.slowdown = 1 + linkedsuit.flags |= STOPSPRESSUREDMAGE | THICKMATERIAL + linkedsuit.flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + linkedsuit.cold_protection |= UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS + else + linkedsuit.name += " (combat)" + linkedsuit.desc = linkedsuit.alt_desc + linkedsuit.slowdown = 0 + linkedsuit.flags = THICKMATERIAL + linkedsuit.cold_protection &= ~(UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS) + linkedsuit.flags_inv &= ~(HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL) + + linkedsuit.update_icon() + user.update_inv_wear_suit() + user.update_inv_w_uniform() + + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + /obj/item/clothing/head/helmet/space/hardsuit/syndi/freedom name = "eagle helmet" desc = "An advanced, space-proof helmet. It appears to be modeled after an old-world eagle." @@ -360,6 +410,7 @@ /obj/item/clothing/suit/space/hardsuit/syndi name = "blood-red hardsuit" desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in travel mode. Property of Gorlex Marauders." + alt_desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit1-syndi" item_state = "syndie_hardsuit" item_color = "syndi" @@ -372,34 +423,6 @@ /obj/item/clothing/suit/space/hardsuit/syndi/update_icon() icon_state = "hardsuit[on]-[item_color]" -/obj/item/clothing/suit/space/hardsuit/syndi/attack_self(mob/user) - on = !on - if(on) - to_chat(user, "You switch your hardsuit to travel mode. It will allow you to stand in zero pressure environments, at the cost of speed.") - name = "blood-red hardsuit" - desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in travel mode. Property of Gorlex Marauders." - slowdown = 1 - flags = STOPSPRESSUREDMAGE | THICKMATERIAL - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS - else - to_chat(user, "You switch your hardsuit to combat mode. You will take damage in zero pressure environments, but you are more suited for a fight.") - name = "blood-red hardsuit (combat)" - desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in combat mode. Property of Gorlex Marauders." - slowdown = 0 - flags = THICKMATERIAL - flags_inv = null - cold_protection = null - - update_icon() - playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) - user.update_inv_wear_suit() - user.update_inv_w_uniform() - - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() - //Elite Syndie suit /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite name = "elite syndicate hardsuit helmet" diff --git a/code/modules/clothing/suits/storage.dm b/code/modules/clothing/suits/storage.dm index f64ae7ca6c0..0c77183b578 100644 --- a/code/modules/clothing/suits/storage.dm +++ b/code/modules/clothing/suits/storage.dm @@ -28,8 +28,8 @@ pockets.emp_act(severity) ..() -/obj/item/clothing/suit/storage/hear_talk(mob/M, var/msg) - pockets.hear_talk(M, msg) +/obj/item/clothing/suit/storage/hear_talk(mob/M, list/message_pieces) + pockets.hear_talk(M, message_pieces) ..() /obj/item/clothing/suit/storage/hear_message(mob/M, var/msg) diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index ae771a0dffd..3b2e9c75a20 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -40,8 +40,8 @@ hold.emp_act(severity) ..() -/obj/item/clothing/accessory/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking) - hold.hear_talk(M, msg, verb, speaking) +/obj/item/clothing/accessory/storage/hear_talk(mob/M, list/message_pieces, verb) + hold.hear_talk(M, message_pieces, verb) ..() /obj/item/clothing/accessory/storage/hear_message(mob/M, var/msg, verb, datum/language/speaking) diff --git a/code/modules/clothing/under/chameleon.dm b/code/modules/clothing/under/chameleon.dm index 8828f7a4c2e..b320237996e 100644 --- a/code/modules/clothing/under/chameleon.dm +++ b/code/modules/clothing/under/chameleon.dm @@ -12,11 +12,12 @@ New() ..() - for(var/U in subtypesof(/obj/item/clothing/under/color)) + var/blocked = list(/obj/item/clothing/under/color/random, /obj/item/clothing/under/rank/centcom) // Stops random coloured jumpsuit and undefined centcomm suit appearing in the list. + for(var/U in subtypesof(/obj/item/clothing/under/color) - blocked) var/obj/item/clothing/under/V = new U src.clothing_choices += V - for(var/U in subtypesof(/obj/item/clothing/under/rank)) + for(var/U in subtypesof(/obj/item/clothing/under/rank) - blocked) var/obj/item/clothing/under/V = new U src.clothing_choices += V return diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 76bef3e056b..62ced953ae2 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -69,15 +69,17 @@ item_state = "clown" item_color = "clown" flags_size = ONESIZEFITSALL - var/honk_sound = 'sound/items/bikehorn.ogg' + +/obj/item/clothing/under/rank/clown/Initialize() + . = ..() + AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50) /obj/item/clothing/under/rank/clown/hit_reaction() - playsound(loc, honk_sound, 50, 1, -1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc if(H.mind && H.mind.assigned_role == "Clown") score_clownabuse++ - return 0 + return ..() /obj/item/clothing/under/rank/head_of_personnel desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"." diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index e39691d857f..8fd4e55f57e 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -79,11 +79,4 @@ name = "camo pants" desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station." icon_state = "camopants" - item_color = "camopants" - -/obj/item/clothing/under/pants/chaps - name = "black leather assless chaps" - desc = "For those brave enough to weather the breeze." - icon_state = "chaps" - item_color = "chaps" - flags_size = ONESIZEFITSALL \ No newline at end of file + item_color = "camopants" \ No newline at end of file diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index ada24f85259..127656ece55 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -1490,9 +1490,9 @@ icon = 'icons/obj/custom_items.dmi' lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi' righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' + honk_sounds = list('sound/items/teri_horn.ogg' = 1) icon_state = "teri_horn" item_state = "teri_horn" - honk_sound = 'sound/items/teri_horn.ogg' /obj/item/clothing/accessory/medal/fluff/elo //V-Force_Bomber: E.L.O. name = "distinguished medal of loyalty and excellence" diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index f9f147e9bf8..5273bcb768b 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -728,7 +728,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_ people += H if(person) //Basic talk var/image/speech_overlay = image('icons/mob/talk.dmi', person, "h0", layer = ABOVE_MOB_LAYER) - target.hear_say(pick(speak_messages),language = pick(person.languages),speaker = person) + target.hear_say(message_to_multilingual(pick(speak_messages), pick(person.languages)), speaker = person) if(target.client) target.client.images |= speech_overlay sleep(30) @@ -738,7 +738,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_ for(var/mob/living/carbon/human/H in GLOB.living_mob_list) humans += H person = pick(humans) - target.hear_radio(pick(radio_messages),language = pick(person.languages),speaker = person, part_a = "\[[get_frequency_name(PUB_FREQ)]\] ", part_b = " ") + target.hear_radio(message_to_multilingual(pick(radio_messages), pick(person.languages)), speaker = person, part_a = "\[[get_frequency_name(PUB_FREQ)]\] ", part_b = " ") qdel(src) /obj/effect/hallucination/message @@ -754,7 +754,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_ "You feel a tiny prick!", "[target] sneezes.", "You feel faint.", - "You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]", + "You hear a strange, alien voice in your head... [pick("Hiss","Ssss")]", "You can see...everything!") to_chat(target, chosen) qdel(src) diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index c481df1ca42..b72ddea8be1 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -392,4 +392,7 @@ desc = "Contains oil intended for use on cyborgs, robots, and other synthetics." icon = 'icons/goonstation/objects/oil.dmi' icon_state = "oilcan" - volume = 100 \ No newline at end of file + volume = 100 + +/obj/item/reagent_containers/food/drinks/oilcan/full + list_reagents = list("oil" = 100) diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index bd80823addd..c5bcd22a885 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -75,8 +75,7 @@ to_chat(user, "Wait for [occupant.name] to finish being loaded!") return - else - startgibbing(user) + startgibbing(user) /obj/machinery/gibber/attackby(obj/item/P, mob/user, params) if(istype(P, /obj/item/grab)) @@ -113,7 +112,7 @@ move_into_gibber(user,target) -/obj/machinery/gibber/proc/move_into_gibber(var/mob/user,var/mob/living/victim) +/obj/machinery/gibber/proc/move_into_gibber(mob/user, mob/living/victim) if(occupant) to_chat(user, "The [src] is full, empty it first!") return @@ -215,7 +214,7 @@ qdel(holder2) //get rid of holder object locked = 0 //unlock -/obj/machinery/gibber/proc/startgibbing(var/mob/user, var/UserOverride=0) +/obj/machinery/gibber/proc/startgibbing(mob/user, UserOverride=0) if(!istype(user) && !UserOverride) log_debug("Some shit just went down with the gibber at X[x], Y[y], Z[z] with an invalid user. (JMP)") return @@ -249,11 +248,11 @@ for(var/i=1 to slab_count) var/obj/item/reagent_containers/food/snacks/meat/new_meat = new slab_type(src) new_meat.name = "[slab_name] [new_meat.name]" - new_meat.reagents.add_reagent("nutriment",slab_nutrition) + new_meat.reagents.add_reagent("nutriment", slab_nutrition) if(occupant.reagents) - occupant.reagents.trans_to(new_meat, round(occupant.reagents.total_volume/slab_count,1)) + occupant.reagents.trans_to(new_meat, round(occupant.reagents.total_volume/slab_count, 1)) if(ishuman(occupant)) var/mob/living/carbon/human/H = occupant @@ -279,11 +278,10 @@ occupant.death(1) occupant.ghostize() - qdel(occupant) + QDEL_NULL(occupant) spawn(gibtime) playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) - operating = 0 if(stealthmode) for(var/atom/movable/AM in contents) @@ -292,12 +290,12 @@ else for(var/obj/item/thing in contents) //Meat is spawned inside the gibber and thrown out afterwards. thing.loc = get_turf(thing) // Drop it onto the turf for throwing. - thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) // Being pelted with bits of meat and bone would hurt. + thing.throw_at(get_edge_target_turf(src, gib_throw_dir), rand(1, 5), 15) // Being pelted with bits of meat and bone would hurt. sleep(1) for(var/obj/effect/gibs in contents) //throw out the gibs too gibs.loc = get_turf(gibs) //drop onto turf for throwing - gibs.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + gibs.throw_at(get_edge_target_turf(src, gib_throw_dir), rand(1, 5), 15) sleep(1) pixel_x = initial(pixel_x) //return to it's spot after shaking @@ -358,7 +356,7 @@ break victim_targets.Cut() -/obj/machinery/gibber/autogibber/proc/force_move_into_gibber(var/mob/living/carbon/human/victim) +/obj/machinery/gibber/autogibber/proc/force_move_into_gibber(mob/living/carbon/human/victim) if(!istype(victim)) return 0 visible_message("\The [victim.name] gets sucked into \the [src]!") @@ -385,7 +383,7 @@ qdel(O) //they are already dead by now H.unEquip(O) O.loc = loc - O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + O.throw_at(get_edge_target_turf(src, gib_throw_dir), rand(1, 5), 15) sleep(1) for(var/obj/item/clothing/C in H) @@ -393,7 +391,7 @@ qdel(C) H.unEquip(C) C.loc = loc - C.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + C.throw_at(get_edge_target_turf(src, gib_throw_dir), rand(1, 5), 15) sleep(1) visible_message("\The [src] spits out \the [H.name]'s possessions!") @@ -405,7 +403,7 @@ qdel(O) else if(istype(O)) O.loc = loc - O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + O.throw_at(get_edge_target_turf(src, gib_throw_dir), rand(1, 5), 15) spats++ sleep(1) if(spats) diff --git a/code/modules/martial_arts/cqc.dm b/code/modules/martial_arts/cqc.dm new file mode 100644 index 00000000000..54f9ac97cd9 --- /dev/null +++ b/code/modules/martial_arts/cqc.dm @@ -0,0 +1,204 @@ +#define SLAM_COMBO "HG" +#define KICK_COMBO "HH" +#define RESTRAIN_COMBO "GG" +#define PRESSURE_COMBO "DG" +#define CONSECUTIVE_COMBO "DDH" + +/datum/martial_art/cqc + name = "CQC" + help_verb = /mob/living/carbon/human/proc/CQC_help + block_chance = 75 + +/datum/martial_art/cqc/can_use(mob/living/carbon/human/H) + if(istype(H.gloves, /obj/item/clothing/gloves/fingerless/rapid)) + return FALSE + return ..() + +/datum/martial_art/cqc/proc/drop_restraining() + restraining = FALSE + +/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + if(findtext(streak, SLAM_COMBO)) + streak = "" + Slam(A, D) + return TRUE + if(findtext(streak, KICK_COMBO)) + streak = "" + Kick(A, D) + return TRUE + if(findtext(streak, RESTRAIN_COMBO)) + streak = "" + Restrain(A, D) + return TRUE + if(findtext(streak, PRESSURE_COMBO)) + streak = "" + Pressure(A, D) + return TRUE + if(findtext(streak, CONSECUTIVE_COMBO)) + streak = "" + Consecutive(A, D) + return FALSE + +/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + if(!D.stat || !D.weakened) + D.visible_message("[A] slams [D] into the ground!", \ + "[A] slams you into the ground!") + playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) + D.apply_damage(10, BRUTE) + D.Weaken(6) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Slam", ATKLOG_ALL) + else //if target can't be slammed, do a regular grab attack then clear the streak + streak = "" + grab_act(A, D) + streak = "" + return TRUE + +/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + if(!D.stat || !D.weakened) + D.visible_message("[A] kicks [D] back!", \ + "[A] kicks you back!") + playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + var/atom/throw_target = get_edge_target_turf(D, A.dir) + D.throw_at(throw_target, 1, 14, A) + D.apply_damage(10, BRUTE) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Kick", ATKLOG_ALL) + if(D.weakened && !D.stat) + D.visible_message("[A] kicks [D]'s head, knocking [D.p_them()] out!", \ + "[A] kicks your head, knocking you out!") + playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1) + D.SetSleeping(15) + D.adjustBrainLoss(15, 150) + add_attack_logs(A, D, "Knocked out with martial-art [src] : Kick", ATKLOG_ALL) + else //if target can't be kicked, do a regular harm attack then clear the streak + streak = "" + harm_act(A, D) + streak = "" + return TRUE + +/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + D.visible_message("[A] forces their arm on [D]'s neck!") + D.adjustStaminaLoss(60) + playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Pressure", ATKLOG_ALL) + return TRUE + +/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(restraining) + return + if(!can_use(A)) + return FALSE + if(!D.stat) + D.visible_message("[A] locks [D] into a restraining position!", \ + "[A] locks you into a restraining position!") + D.adjustStaminaLoss(20) + D.Stun(5) + restraining = TRUE + addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Restrain", ATKLOG_ALL) + return TRUE + +/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + if(!D.stat) + D.visible_message("[A] strikes [D]'s abdomen, neck and back consecutively", \ + "[A] strikes your abdomen, neck and back consecutively!") + playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) + var/obj/item/I = D.get_active_hand() + if(I && D.drop_item()) + A.put_in_hands(I) + D.adjustStaminaLoss(50) + D.apply_damage(25, BRUTE) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Consecutive", ATKLOG_ALL) + else //if target can't be hit, do a regular harm attack then clear the streak + streak = "" + harm_act(A, D) + streak = "" + return TRUE + +/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + add_to_streak("G", D) + if(check_streak(A, D)) + return TRUE + var/obj/item/grab/G = D.grabbedby(A, 1) + if(G) + G.state = GRAB_AGGRESSIVE //Instant aggressive grab + return TRUE + +/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + add_to_streak("H", D) + if(check_streak(A, D)) + return TRUE + A.do_attack_animation(D) + var/picked_hit_type = pick("CQC'd", "neck chopped", "gut punched") + var/bonus_damage = 13 + if(D.weakened || D.resting || D.lying) + bonus_damage += 5 + picked_hit_type = "stomps on" + D.apply_damage(bonus_damage, BRUTE) + if(picked_hit_type == "kicks" || picked_hit_type == "stomps on") + playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) + else + playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + D.visible_message("[A] [picked_hit_type] [D]!", \ + "[A] [picked_hit_type] you!") + add_attack_logs(A, D, "Melee attacked with martial-art [src]", ATKLOG_ALL) + if(A.resting && !D.stat && !D.weakened) + D.visible_message("[A] leg sweeps [D]!", \ + "[A] leg sweeps you!") + playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) + D.apply_damage(10, BRUTE) + D.Weaken(3) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Leg sweep", ATKLOG_ALL) + return TRUE + +/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!can_use(A)) + return FALSE + add_to_streak("D", D) + if(check_streak(A, D)) + return TRUE + if(!restraining) + D.visible_message("[A] strikes [D]'s jaw with their hand!", \ + "[A] strikes your jaw, disorienting you!") + playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + D.Jitter(2) + D.apply_damage(5, BRUTE) + add_attack_logs(A, D, "Melee attacked with martial-art [src] : Disarm", ATKLOG_ALL) + if(restraining) + D.visible_message("[A] puts [D] into a chokehold!", \ + "[A] puts you into a chokehold!") + D.SetSleeping(20) + restraining = FALSE + add_attack_logs(A, D, "Knocked out with martial-art [src] : Choke hold", ATKLOG_ALL) + else + restraining = FALSE + return FALSE + return TRUE + +/mob/living/carbon/human/proc/CQC_help() + set name = "Remember The Basics" + set desc = "You try to remember some of the basics of CQC." + set category = "CQC" + to_chat(usr, "You try to remember some of the basics of CQC.") + + to_chat(usr, "Slam: Harm Grab. Slam opponent into the ground, knocking them down.") + to_chat(usr, "CQC Kick: Harm Harm. Knocks opponent away. Knocks out stunned or knocked down opponents.") + to_chat(usr, "Restrain: Grab Switch Hand Grab. Locks opponent into a restraining position, stunning them.") + to_chat(usr, "Choke Hold: Restrain Disarm. Knocks out an opponent you have restrained.") + to_chat(usr, "Pressure: Disarm Grab. Decent stamina damage.") + to_chat(usr, "Consecutive CQC: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.") + + to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter melee attacks done to you.") \ No newline at end of file diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 3e3af7963b0..aed823b372b 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -6,6 +6,8 @@ var/temporary = 0 var/datum/martial_art/base = null // The permanent style var/deflection_chance = 0 //Chance to deflect projectiles + var/block_chance = 0 //Chance to block melee attacks using items while on throw mode. + var/restraining = 0 //used in cqc's disarm_act to check if the disarmed is being restrained and so whether they should be put in a chokehold or not var/help_verb = null var/no_guns = FALSE //set to TRUE to prevent users of this style from using guns (sleeping carp, highlander). They can still pick them up, but not fire them. var/no_guns_message = "" //message to tell the style user if they try and use a gun while no_guns = TRUE (DISHONORABRU!) @@ -22,6 +24,9 @@ /datum/martial_art/proc/help_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) return 0 +/datum/martial_art/proc/can_use(mob/living/carbon/human/H) + return TRUE + /datum/martial_art/proc/add_to_streak(var/element,var/mob/living/carbon/human/D) if(D != current_target) current_target = D @@ -143,6 +148,7 @@ /obj/item/plasma_fist_scroll/attack_self(mob/user as mob) if(!ishuman(user)) return + if(!used) var/mob/living/carbon/human/H = user var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null) @@ -162,6 +168,14 @@ /obj/item/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user as mob) if(!istype(user) || !user) return + if(user.mind && (user.mind.changeling || user.mind.vampire)) //Prevents changelings and vampires from being able to learn it + if(user.mind && user.mind.changeling) //Changelings + to_chat(user, "We try multiple times, but we are not able to comprehend the contents of the scroll!") + return + else //Vampires + to_chat(user, "Your blood lust distracts you too much to be able to concentrate on the contents of the scroll!") + return + to_chat(user, "You have learned the ancient martial art of the Sleeping Carp! \ Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles directed toward you. \ However, you are also unable to use any ranged weaponry. \ @@ -175,6 +189,24 @@ new /obj/effect/decal/cleanable/ash(get_turf(src)) qdel(src) +/obj/item/CQC_manual + name = "old manual" + desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat." + icon = 'icons/obj/library.dmi' + icon_state = "cqcmanual" + +/obj/item/CQC_manual/attack_self(mob/living/carbon/human/user) + if(!istype(user) || !user) + return + to_chat(user, "You remember the basics of CQC.") + + var/datum/martial_art/cqc/CQC = new(null) + CQC.teach(user) + user.drop_item() + visible_message("[src] beeps ominously, and a moment later it bursts up in flames.") + new /obj/effect/decal/cleanable/ash(get_turf(src)) + qdel(src) + /obj/item/twohanded/bostaff name = "bo staff" desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." diff --git a/code/modules/mining/coins.dm b/code/modules/mining/coins.dm index 96fc0aa2e7f..70d920cd38f 100644 --- a/code/modules/mining/coins.dm +++ b/code/modules/mining/coins.dm @@ -18,7 +18,7 @@ pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 - icon_state = "coin_[cmineral]_heads" + icon_state = "coin_[cmineral]_[sideslist[1]]" if(cmineral) name = "[cmineral] coin" diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index c6749528908..11bafb24e26 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -335,6 +335,8 @@ var/datum/design/alloy = files.FindDesignByID(alloy_id) if((check_access(inserted_id) || allowed(usr)) && alloy) var/desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num + if(desired < 1) // Stops an exploit that lets you build negative alloys and get free materials + return var/smelt_amount = can_smelt_alloy(alloy) var/amount = round(min(desired,50,smelt_amount)) materials.use_amount(alloy.materials, amount) diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm index 4c748067a5b..78dcbca2cf4 100644 --- a/code/modules/mining/lavaland/loot/colossus_loot.dm +++ b/code/modules/mining/lavaland/loot/colossus_loot.dm @@ -112,9 +112,9 @@ activation_method = pick("touch","laser","bullet","energy","bomb","mob_bump","weapon","speech") // "heat" removed due to lack of is_hot() ..() -/obj/machinery/anomalous_crystal/hear_talk(mob/speaker, message) +/obj/machinery/anomalous_crystal/hear_talk(mob/speaker, list/message_pieces) ..() - if(isliving(speaker) && message) + if(isliving(speaker) && LAZYLEN(message_pieces)) ActivationReaction(speaker, "speech") /obj/machinery/anomalous_crystal/attack_hand(mob/user) diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm new file mode 100644 index 00000000000..922f3181c27 --- /dev/null +++ b/code/modules/mob/dead/dead.dm @@ -0,0 +1,23 @@ +/mob/dead/forceMove(atom/destination) + // Overriden from code/game/atoms_movable.dm#141 to prevent things like mice squeaking when ghosts walk on them. + // Same as parent, except that it does not include Uncrossed or Crossed calls. + var/turf/old_loc = loc + loc = destination + + if(old_loc) + old_loc.Exited(src, destination) + + if(destination) + destination.Entered(src) + + if(isturf(destination) && opacity) + var/turf/new_loc = destination + new_loc.reconsider_lights() + + if(isturf(old_loc) && opacity) + old_loc.reconsider_lights() + + for(var/datum/light_source/L in light_sources) + L.source_atom.update_light() + + return 1 diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index b780ac0d381..ab47a84ee76 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -38,7 +38,7 @@ . = src.emote_dead(message) -/mob/dead/observer/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear) +/mob/dead/observer/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear) return "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])" /mob/dead/observer/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 2593d2eebaf..382eb94b4db 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -1,6 +1,53 @@ // At minimum every mob has a hear_say proc. -/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) +/mob/proc/combine_message(var/list/message_pieces, var/verb, var/mob/speaker, always_stars = FALSE) + var/iteration_count = 0 + var/msg = "" // This is to make sure that the pieces have actually added something + . = "[verb], \"" + for(var/datum/multilingual_say_piece/SP in message_pieces) + iteration_count++ + var/piece = SP.message + if(piece == "") + continue + + if(SP.speaking && SP.speaking.flags & INNATE) // Fucking snowflake noise lang + return SP.speaking.format_message(piece) + + if(iteration_count == 1) + piece = capitalize(piece) + + if(SP.speaking) + if(!say_understands(speaker, SP.speaking)) + if(isanimal(speaker)) + var/mob/living/simple_animal/S = speaker + if(LAZYLEN(S.speak)) + piece = pick(S.speak) + else + piece = stars(piece) + else + piece = SP.speaking.scramble(piece) + if(always_stars) + piece = stars(piece) + piece = SP.speaking.format_message(piece) + else + if(!say_understands(speaker, null)) + piece = stars(piece) + if(isanimal(speaker)) + var/mob/living/simple_animal/S = speaker + if(LAZYLEN(S.speak)) + piece = pick(S.speak) + if(always_stars) + piece = stars(piece) + piece = "[piece]" + msg += (piece + " ") + if(msg == "") + // There is literally no content left in this message, we need to shut this shit down + . = "" // hear_say will suppress it + else + . = trim(. + trim(msg)) + . += "\"" + +/mob/proc/hear_say(var/list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) if(!client) return 0 @@ -23,35 +70,18 @@ sound_vol *= 0.5 if(sleeping || stat == UNCONSCIOUS) - hear_sleep(message) + hear_sleep(message_pieces) return 0 - //non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet. - if(language && (language.flags & NONVERBAL)) - if(!has_vision(information_only = TRUE)) //blind people can't see dumbass - message = stars(message) - - if(!speaker || !(speaker in view(src))) - message = stars(message) - - if(!say_understands(speaker, language)) - if(isanimal(speaker)) - var/mob/living/simple_animal/S = speaker - if(S.speak.len) - message = pick(S.speak) - else - message = stars(message) - else - if(language) - message = language.scramble(message) - else - message = stars(message) - var/speaker_name = speaker.name if(ishuman(speaker)) var/mob/living/carbon/human/H = speaker speaker_name = H.GetVoice() + var/message = combine_message(message_pieces, verb, speaker) + if(message == "") + return + if(italics) message = "[message]" @@ -66,74 +96,47 @@ message = "[message]" if(!can_hear()) - if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set - if(speaker == src) - to_chat(src, "You cannot hear yourself speak!") - else - to_chat(src, "[speaker_name][speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].") - else - if(language) - to_chat(src, "[speaker_name][speaker.GetAltName()] [track][language.format_message(message, verb)]") + // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set + // if(!language || !(language.flags & INNATE)) + if(speaker == src) + to_chat(src, "You cannot hear yourself speak!") else - to_chat(src, "[speaker_name][speaker.GetAltName()] [track][verb], \"[message]\"") + to_chat(src, "[speaker_name][speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].") + else + to_chat(src, "[speaker_name][speaker.GetAltName()] [track][message]") if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z)) var/turf/source = speaker? get_turf(speaker) : get_turf(src) src.playsound_local(source, speech_sound, sound_vol, 1) -/mob/proc/hear_radio(var/message, var/verb = "says", var/datum/language/language = null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname = "", var/atom/follow_target) +/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target) if(!client) return if(sleeping || stat == UNCONSCIOUS) //If unconscious or sleeping - hear_sleep(message) + hear_sleep(multilingual_to_message(message_pieces)) + return + + var/message = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear) + if(message == "") return var/track = null if(!follow_target) follow_target = speaker - //non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet. - if(language && (language.flags & NONVERBAL)) - if(!has_vision(information_only=TRUE)) //blind people can't see dumbass - message = stars(message) - - if(!speaker || !(speaker in view(src))) - message = stars(message) - - if(!say_understands(speaker, language)) - if(isanimal(speaker)) - var/mob/living/simple_animal/S = speaker - if(S.speak && S.speak.len) - message = pick(S.speak) - else - return - else - if(language) - message = language.scramble(message) - else - message = stars(message) - - if(hard_to_hear) - message = stars(message) - var/speaker_name = handle_speaker_name(speaker, vname, hard_to_hear) - track = handle_track(message, verb, language, speaker, speaker_name, follow_target, hard_to_hear) + track = handle_track(message, verb, speaker, speaker_name, follow_target, hard_to_hear) - var/formatted - if(language) - formatted = language.format_message_radio(message, verb) - else - formatted = "[verb], \"[message]\"" if(!can_hear()) if(prob(20)) to_chat(src, "You feel your headset vibrate but can hear nothing from it!") else if(track) - to_chat(src, "[part_a][track][part_b][formatted]") + to_chat(src, "[part_a][track][part_b][message]") else - to_chat(src, "[part_a][speaker_name][part_b][formatted]") + to_chat(src, "[part_a][speaker_name][part_b][message]") -/mob/proc/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear) +/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear) var/speaker_name = "unknown" if(speaker) speaker_name = speaker.name @@ -146,26 +149,10 @@ return speaker_name -/mob/proc/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear) +/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear) return -/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null) - if(!client) - return - - if(say_understands(speaker, language)) - message = "[src] [verb], \"[message]\"" - else - message = "[src] [verb]." - - if(src.status_flags & PASSEMOTES) - for(var/obj/item/holder/H in src.contents) - H.show_message(message) - for(var/mob/living/M in src.contents) - M.show_message(message) - src.show_message(message) - -/mob/proc/hear_sleep(var/message) +/mob/proc/hear_sleep(message) var/heard = "" if(prob(15)) message = strip_html_properly(message) @@ -177,9 +164,19 @@ heardword = copytext(heardword,2) if(copytext(heardword,-1) in punctuation) heardword = copytext(heardword,1,lentext(heardword)) - heard = "...You hear something about...[heardword]" + heard = "...You hear something about... '[heardword]'..." else - heard = "...You almost hear someone talking..." + heard = "...You almost hear someone talking..." to_chat(src, heard) + +/mob/proc/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null) + var/message = combine_message(message_pieces, verb, speaker) + + var/name = speaker.name + if(!say_understands(speaker)) + name = speaker.voice_name + + var/rendered = "[name] [message]" + to_chat(src, rendered) \ No newline at end of file diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 0a1f2d322ce..2d4b555448b 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -11,7 +11,6 @@ var/ask_verb = "asks" // Used when sentence ends in a ? var/exclaim_verb = "exclaims" // Used when sentence ends in a ! var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead. - var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags var/colour = "body" // CSS style to use for strings in this language. var/key = "x" // Character used to speak in language eg. :o for Unathi. var/flags = 0 // Various language flags. @@ -85,11 +84,11 @@ return scrambled_text -/datum/language/proc/format_message(message, verb) - return "[verb], \"[capitalize(message)]\"" +/datum/language/proc/format_message(message) + return "[message]" -/datum/language/proc/format_message_radio(message, verb) - return "[verb], \"[capitalize(message)]\"" +/datum/language/proc/format_message_radio(message) + return "[message]" /datum/language/proc/get_talkinto_msg_range(message) // if you yell, you'll be heard from two tiles over instead of one @@ -103,11 +102,11 @@ if(!speaker_mask) speaker_mask = speaker.name - var/msg = "[name], [speaker_mask] [format_message(message, get_spoken_verb(message))]" + var/msg = "[name], [speaker_mask] [get_spoken_verb(message)], [format_message(message)]" for(var/mob/player in GLOB.player_list) if(istype(player,/mob/dead) && follow) - var/msg_dead = "[name], [speaker_mask] ([ghost_follow_link(speaker, ghost=player)]) [format_message(message, get_spoken_verb(message))]" + var/msg_dead = "[name], [speaker_mask] ([ghost_follow_link(speaker, ghost=player)]) [get_spoken_verb(message)], [format_message(message)]" to_chat(player, msg_dead) continue @@ -135,10 +134,10 @@ key = "" flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER -/datum/language/noise/format_message(message, verb) +/datum/language/noise/format_message(message) return "[message]" -/datum/language/noise/format_message_radio(message, verb) +/datum/language/noise/format_message_radio(message) return "[message]" /datum/language/noise/get_talkinto_msg_range(message) @@ -635,10 +634,9 @@ // Language handling. /mob/proc/add_language(language) - var/datum/language/new_language = GLOB.all_languages[language] - if(!istype(new_language) || new_language in languages) + if(!istype(new_language) || (new_language in languages)) return FALSE languages |= new_language @@ -657,8 +655,7 @@ // Can we speak this language, as opposed to just understanding it? /mob/proc/can_speak_language(datum/language/speaking) - - return (universal_speak || (speaking && speaking.flags & INNATE) || speaking in languages) + return universal_speak || (speaking && speaking.flags & INNATE) || (speaking in languages) //TBD /mob/proc/check_lang_data() diff --git a/code/modules/mob/living/autohiss.dm b/code/modules/mob/living/autohiss.dm index df1bde34306..286901baf5c 100644 --- a/code/modules/mob/living/autohiss.dm +++ b/code/modules/mob/living/autohiss.dm @@ -1,4 +1,4 @@ -/mob/living/proc/handle_autohiss(message, datum/language/L) +/mob/proc/handle_autohiss(message, datum/language/L) return message // no autohiss at this level /mob/living/carbon/human/handle_autohiss(message, datum/language/L) diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm index f2a15119156..eb4750c9780 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -29,7 +29,7 @@ to_chat(usr, "You cannot speak, as your internal speaker is turned off.") . = FALSE -/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios) +/mob/living/carbon/brain/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios) switch(message_mode) if("headset") var/radio_worked = 0 // If any of the radios our brainmob could use functioned, this is set true so that we don't use any others @@ -39,12 +39,12 @@ if(!radio_worked && c.mecha) var/obj/mecha/metalgear = c.mecha if(metalgear.radio) - radio_worked = metalgear.radio.talk_into(src, message, message_mode, verb, speaking) + radio_worked = metalgear.radio.talk_into(src, message_pieces, message_mode, verb) else if(!radio_worked && c.radio) - radio_worked = c.radio.talk_into(src, message, message_mode, verb, speaking) + radio_worked = c.radio.talk_into(src, message_pieces, message_mode, verb) return radio_worked if("whisper") - whisper_say(message, speaking) + whisper_say(message_pieces) return 1 else return 0 diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 9201075bd56..11961dac08f 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -238,7 +238,7 @@ start_tail_wagging(1) else if(dna.species.bodyflags & TAIL_WAGGING) - if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) + if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL)) message = "[src] starts wagging [p_their()] tail." start_tail_wagging(1) else diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b3d4ab3306b..09d0a84f729 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -705,7 +705,8 @@ if(href_list["criminal"]) if(hasHUD(usr,"security")) - + if(usr.incapacitated()) + return var/found_record = 0 var/perpname = "wot" if(wear_id) @@ -752,6 +753,8 @@ if(href_list["secrecord"]) if(hasHUD(usr,"security")) + if(usr.incapacitated()) + return var/perpname = "wot" var/read = 0 @@ -782,6 +785,8 @@ if(href_list["secrecordComment"]) if(hasHUD(usr,"security")) + if(usr.incapacitated()) + return var/perpname = "wot" var/read = 0 @@ -811,6 +816,8 @@ if(href_list["secrecordadd"]) if(hasHUD(usr,"security")) + if(usr.incapacitated()) + return var/perpname = "wot" if(wear_id) if(istype(wear_id,/obj/item/card/id)) @@ -840,6 +847,8 @@ if(href_list["medical"]) if(hasHUD(usr,"medical")) + if(usr.incapacitated()) + return var/perpname = "wot" var/modified = 0 @@ -873,6 +882,8 @@ if(href_list["medrecord"]) if(hasHUD(usr,"medical")) + if(usr.incapacitated()) + return var/perpname = "wot" var/read = 0 @@ -904,6 +915,8 @@ if(href_list["medrecordComment"]) if(hasHUD(usr,"medical")) + if(usr.incapacitated()) + return var/perpname = "wot" var/read = 0 @@ -933,6 +946,8 @@ if(href_list["medrecordadd"]) if(hasHUD(usr,"medical")) + if(usr.incapacitated()) + return var/perpname = "wot" if(wear_id) if(istype(wear_id,/obj/item/card/id)) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index d4c14bda32a..b858cca130a 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -233,7 +233,6 @@ var/obj/item/organ/external/picked = pick(parts) if(picked.receive_damage(brute, burn, sharp, updating_health)) UpdateDamageIcon() - speech_problem_flag = 1 //Heal MANY external organs, in random order @@ -256,7 +255,6 @@ if(updating_health) updatehealth("heal overall damage") - speech_problem_flag = 1 if(update) UpdateDamageIcon() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 98274ea7e1f..a7d04c7f0c4 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -156,6 +156,10 @@ emp_act return 1 return 0 +/mob/living/carbon/human/check_block() + if(martial_art && prob(martial_art.block_chance) && martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE)) + return TRUE + /mob/living/carbon/human/emp_act(severity) for(var/obj/O in src) if(!O) continue diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 96693a0d086..22a9d40f6fd 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -42,8 +42,6 @@ var/global/default_martial_art = new/datum/martial_art var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() - var/speech_problem_flag = 0 - var/datum/personal_crafting/handcrafting var/datum/martial_art/martial_art = null diff --git a/code/modules/mob/living/carbon/human/interactive/interactive.dm b/code/modules/mob/living/carbon/human/interactive/interactive.dm index 3eb2f4e65fd..bb9ae87bdc7 100644 --- a/code/modules/mob/living/carbon/human/interactive/interactive.dm +++ b/code/modules/mob/living/carbon/human/interactive/interactive.dm @@ -580,14 +580,14 @@ return FALSE saveVoice() -/mob/living/carbon/human/interactive/hear_say(message, verb = "says", datum/language/language = null, italics = 0, mob/speaker = null, sound/speech_sound, sound_vol) +/mob/living/carbon/human/interactive/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol) if(!istype(speaker, /mob/living/carbon/human/interactive)) - knownStrings |= html_decode(message) + knownStrings |= html_decode(multilingual_to_message(message_pieces)) ..() -/mob/living/carbon/human/interactive/hear_radio(message, verb = "says", datum/language/language=null, part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target) +/mob/living/carbon/human/interactive/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target) if(!istype(speaker, /mob/living/carbon/human/interactive)) - knownStrings |= html_decode(message) + knownStrings |= html_decode(multilingual_to_message(message_pieces)) ..() /mob/living/carbon/human/interactive/proc/doProcess() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index ce1d9a7f56e..8d0261528ed 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -71,7 +71,6 @@ drop_item() emote("cough") if(disabilities & TOURETTES) - speech_problem_flag = 1 if((prob(10) && paralysis <= 1)) Stun(10) switch(rand(1, 3)) @@ -86,12 +85,10 @@ animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y), time = 1) if(disabilities & NERVOUS) - speech_problem_flag = 1 if(prob(10)) Stuttering(10) if(getBrainLoss() >= 60 && stat != DEAD) - speech_problem_flag = 1 if(prob(3)) var/list/s1 = list("IM A [pick("PONY","LIZARD","taJaran","kitty","Vulpakin","drASK","BIRDIE","voxxie","race car","combat meCH","SPESSSHIP")] [pick("NEEEEEEIIIIIIIIIGH","sKREEEEEE","MEOW","NYA~","rawr","Barkbark","Hissssss","vROOOOOM","pewpew","choo Choo")]!", "without oxigen blob don't evoluate?", @@ -158,7 +155,6 @@ if(!gene.block) continue if(gene.is_active(src)) - speech_problem_flag = 1 gene.OnMobLife(src) if(!ignore_gene_stability && gene_stability < GENETIC_DAMAGE_STAGE_1) var/instability = DEFAULT_GENE_STABILITY - gene_stability @@ -741,7 +737,6 @@ stat = UNCONSCIOUS else if(sleeping) - speech_problem_flag = 1 stat = UNCONSCIOUS @@ -1003,29 +998,6 @@ This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag. */ - -/mob/living/carbon/human/handle_silent() - if(..()) - speech_problem_flag = 1 - return silent - -/mob/living/carbon/human/handle_slurring() - if(..()) - speech_problem_flag = 1 - return slurring - -/mob/living/carbon/human/handle_stunned() - if(..()) - speech_problem_flag = 1 - return stunned - -/mob/living/carbon/human/handle_stuttering() - if(..()) - speech_problem_flag = 1 - return stuttering - - - /mob/living/carbon/human/proc/can_heartattack() if(NO_BLOOD in dna.species.species_traits) return FALSE diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 70cab4751e2..8d9355c1f26 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -107,65 +107,58 @@ /mob/living/carbon/human/proc/GetSpecialVoice() return special_voice -/mob/living/carbon/human/handle_speech_problems(var/message, var/verb) - var/list/returns[3] - var/speech_problem_flag = 0 +/mob/living/carbon/human/handle_speech_problems(list/message_pieces, var/verb) var/span = "" if(mind) span = mind.speech_span - if(silent || (disabilities & MUTE)) - message = "" - speech_problem_flag = 1 + if((COMIC in mutations) \ + || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \ + || istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown)) + span = "sans" + + var/list/parent = ..() + verb = parent["verb"] - if(istype(wear_mask, /obj/item/clothing/mask/horsehead)) - var/obj/item/clothing/mask/horsehead/hoers = wear_mask - if(hoers.voicechange) - message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") - verb = pick("whinnies","neighs", "says") - speech_problem_flag = 1 + for(var/datum/multilingual_say_piece/S in message_pieces) + if(S.speaking && S.speaking.flags & NO_STUTTER) + continue - if(dna) - for(var/datum/dna/gene/gene in dna_genes) - if(!gene.block) - continue - if(gene.is_active(src)) - message = gene.OnSay(src,message) - speech_problem_flag = 1 + if(silent || (disabilities & MUTE)) + S.message = "" - if(message != "") - var/list/parent = ..() - message = parent[1] - verb = parent[2] - if(parent[3]) - speech_problem_flag = 1 + if(istype(wear_mask, /obj/item/clothing/mask/horsehead)) + var/obj/item/clothing/mask/horsehead/hoers = wear_mask + if(hoers.voicechange) + S.message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") + verb = pick("whinnies", "neighs", "says") + + if(dna) + for(var/datum/dna/gene/gene in dna_genes) + if(!gene.block) + continue + if(gene.is_active(src)) + S.message = gene.OnSay(src, S.message) var/braindam = getBrainLoss() if(braindam >= 60) - speech_problem_flag = 1 - if(prob(braindam/4)) - message = stutter(message) + if(prob(braindam / 4)) + S.message = stutter(S.message) verb = "gibbers" if(prob(braindam)) - message = uppertext(message) + S.message = uppertext(S.message) verb = "yells loudly" - if((COMIC in mutations) || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) || istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown)) - span = "sans" + if(span) + S.message = "[S.message]" + return list("verb" = verb) - if(span) - message = "[message]" - returns[1] = message - returns[2] = verb - returns[3] = speech_problem_flag - return returns - -/mob/living/carbon/human/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios) +/mob/living/carbon/human/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios) switch(message_mode) if("intercom") for(var/obj/item/radio/intercom/I in view(1, src)) spawn(0) - I.talk_into(src, message, null, verb, speaking) + I.talk_into(src, message_pieces, null, verb) used_radios += I if("headset") @@ -173,13 +166,13 @@ if(isradio(l_ear)) R = l_ear used_radios += R - if(R.talk_into(src, message, null, verb, speaking)) + if(R.talk_into(src, message_pieces, null, verb)) return if(isradio(r_ear)) R = r_ear used_radios += R - if(R.talk_into(src, message, null, verb, speaking)) + if(R.talk_into(src, message_pieces, null, verb)) return if("right ear") @@ -190,7 +183,7 @@ R = r_hand if(R) used_radios += R - R.talk_into(src, message, null, verb, speaking) + R.talk_into(src, message_pieces, null, verb) if("left ear") var/obj/item/radio/R @@ -200,21 +193,21 @@ R = l_hand if(R) used_radios += R - R.talk_into(src, message, null, verb, speaking) + R.talk_into(src, message_pieces, null, verb) if("whisper") - whisper_say(message, speaking) + whisper_say(message_pieces) return 1 else if(message_mode) if(isradio(l_ear)) used_radios += l_ear - if(l_ear.talk_into(src, message, message_mode, verb, speaking)) + if(l_ear.talk_into(src, message_pieces, message_mode, verb)) return if(isradio(r_ear)) used_radios += r_ear - if(r_ear.talk_into(src, message, message_mode, verb, speaking)) + if(r_ear.talk_into(src, message_pieces, message_mode, verb)) return /mob/living/carbon/human/handle_speech_sound() diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 37b67d40f29..06d45056ac4 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -198,8 +198,9 @@ var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears) if(ears) qdel(ears) - - ears = new mutantears(H) + + if(mutantears) + ears = new mutantears(H) /datum/species/proc/breathe(mob/living/carbon/human/H) if((NO_BREATHE in species_traits) || (BREATHLESS in H.mutations)) @@ -318,6 +319,9 @@ user.do_cpr(target) /datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + if(target.check_block()) //cqc + target.visible_message("[target] blocks [user]'s grab attempt!") + return FALSE if(attacker_style && attacker_style.grab_act(user, target)) return TRUE else @@ -344,6 +348,9 @@ add_attack_logs(user, target, "vampirebit") return //end vampire codes + if(target.check_block()) //cqc + target.visible_message("[target] blocks [user]'s attack!") + return FALSE if(attacker_style && attacker_style.harm_act(user, target)) return TRUE else @@ -382,6 +389,9 @@ target.forcesay(GLOB.hit_appends) /datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + if(target.check_block()) //cqc + target.visible_message("[target] blocks [user]'s disarm attempt!") + return FALSE if(attacker_style && attacker_style.disarm_act(user, target)) return TRUE else @@ -716,3 +726,9 @@ It'll return null if the organ doesn't correspond, so include null checks when u var/picked_species = pick(random_species) var/datum/species/selected_species = GLOB.all_species[picked_species] return species_name ? picked_species : selected_species.type + +/datum/species/proc/can_hear(mob/living/carbon/human/H) + . = FALSE + var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears) && !ears.deaf) + . = TRUE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm index a3c0295243c..88ed0a626cb 100644 --- a/code/modules/mob/living/carbon/human/species/machine.dm +++ b/code/modules/mob/living/carbon/human/species/machine.dm @@ -55,6 +55,7 @@ ) vision_organ = /obj/item/organ/internal/eyes/optical_sensor + mutantears = /obj/item/organ/internal/ears/microphone has_limbs = list( "chest" = list("path" = /obj/item/organ/external/chest/ipc), "groin" = list("path" = /obj/item/organ/external/groin/ipc), diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm index 583835b7358..5631f600afc 100644 --- a/code/modules/mob/living/carbon/human/species/slime.dm +++ b/code/modules/mob/living/carbon/human/species/slime.dm @@ -42,6 +42,7 @@ has_organ = list( "brain" = /obj/item/organ/internal/brain/slime ) + mutantears = null suicide_messages = list( "is melting into a puddle!", @@ -82,6 +83,9 @@ H.update_body() ..() +/datum/species/slime/can_hear() // fucking snowflakes + . = TRUE + /datum/action/innate/slimecolor name = "Toggle Recolor" check_flags = AB_CHECK_CONSCIOUS diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm deleted file mode 100644 index ec8076cf37b..00000000000 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ /dev/null @@ -1,1040 +0,0 @@ -/datum/species/human - name = "Human" - name_plural = "Humans" - icobase = 'icons/mob/human_races/r_human.dmi' - deform = 'icons/mob/human_races/r_def_human.dmi' - primitive_form = /datum/species/monkey - language = "Sol Common" - species_traits = list(LIPS, CAN_BE_FAT) - skinned_type = /obj/item/stack/sheet/animalhide/human - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS - dietflags = DIET_OMNI - blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \ - colonies across a wide swathe of space. They hold a wide range of forms and creeds.

\ - While the central Sol government maintains control of its far-flung people, powerful corporate \ - interests, rampant cyber and bio-augmentation and secretive factions make life on most human \ - worlds tumultous at best." - - reagent_tag = PROCESS_ORG - //Has standard darksight of 2. - -/datum/species/unathi - name = "Unathi" - name_plural = "Unathi" - icobase = 'icons/mob/human_races/r_lizard.dmi' - deform = 'icons/mob/human_races/r_def_lizard.dmi' - language = "Sinta'unathi" - tail = "sogtail" - skinned_type = /obj/item/stack/sheet/animalhide/lizard - unarmed_type = /datum/unarmed_attack/claws - primitive_form = /datum/species/monkey/unathi - - blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ - Uuosa-Eso system, which roughly translates to 'burning mother'.

Coming from a harsh, radioactive \ - desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \ - else, frequently even their own lives. They prefer warmer temperatures than most species and \ - their native tongue is a heavy hissing laungage called Sinta'Unathi." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_BODY_MARKINGS | HAS_HEAD_MARKINGS | HAS_SKIN_COLOR | HAS_ALT_HEADS | TAIL_WAGGING - dietflags = DIET_CARN - - cold_level_1 = 280 //Default 260 - Lower is better - cold_level_2 = 220 //Default 200 - cold_level_3 = 140 //Default 120 - - heat_level_1 = 380 //Default 360 - Higher is better - heat_level_2 = 420 //Default 400 - heat_level_3 = 480 //Default 460 - - flesh_color = "#34AF10" - reagent_tag = PROCESS_ORG - base_color = "#066000" - //Default styles for created mobs. - default_headacc = "Simple" - default_headacc_colour = "#404040" - butt_sprite = "unathi" - brute_mod = 1.05 - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/unathi, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight. - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, - /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - - var/datum/action/innate/tail_lash/lash = new() - - -/datum/species/unathi/handle_post_spawn(var/mob/living/carbon/human/H) - lash.Grant(H) - ..() - -/datum/action/innate/tail_lash - name = "Tail lash" - icon_icon = 'icons/effects/effects.dmi' - button_icon_state = "tail" - -/datum/action/innate/tail_lash/Activate() - var/mob/living/carbon/human/user = owner - if(!user.restrained() || !user.buckled) - to_chat(user, "You need freedom of movement to tail lash!") - return - if(user.getStaminaLoss() >= 50) - to_chat(user, "Rest before tail lashing again!") - return - for(var/mob/living/carbon/human/C in orange(1)) - var/obj/item/organ/external/E = C.get_organ(pick("l_leg", "r_leg", "l_foot", "r_foot", "groin")) - if(E) - user.changeNext_move(CLICK_CD_MELEE) - user.visible_message("[src] smacks [C] in [E] with their tail! ", "You hit [C] in [E] with your tail!") - user.adjustStaminaLoss(15) - C.apply_damage(5, BRUTE, E) - user.spin(20, 1) - playsound(user.loc, 'sound/weapons/slash.ogg', 50, 0) - - - -/datum/species/unathi/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/tajaran - name = "Tajaran" - name_plural = "Tajaran" - icobase = 'icons/mob/human_races/r_tajaran.dmi' - deform = 'icons/mob/human_races/r_def_tajaran.dmi' - language = "Siik'tajr" - tail = "tajtail" - skinned_type = /obj/item/stack/sheet/fur - unarmed_type = /datum/unarmed_attack/claws - - blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \ - S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \ - influenced heavily by their long history of Slavemaster rule. They have a structured, clan-influenced way \ - of family and politics. They prefer colder environments, and speak a variety of languages, mostly Siik'Maas, \ - using unique inflections their mouths form." - - cold_level_1 = 240 - cold_level_2 = 180 - cold_level_3 = 100 - - heat_level_1 = 340 - heat_level_2 = 380 - heat_level_3 = 440 - - primitive_form = /datum/species/monkey/tajaran - - species_traits = list(LIPS, CAN_BE_FAT) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING - dietflags = DIET_OMNI - taste_sensitivity = TASTE_SENSITIVITY_SHARP - reagent_tag = PROCESS_ORG - flesh_color = "#AFA59E" - base_color = "#424242" - butt_sprite = "tajaran" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/tajaran, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) - unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, - /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - -/datum/species/tajaran/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/vulpkanin - name = "Vulpkanin" - name_plural = "Vulpkanin" - icobase = 'icons/mob/human_races/r_vulpkanin.dmi' - deform = 'icons/mob/human_races/r_vulpkanin.dmi' - language = "Canilunzt" - primitive_form = /datum/species/monkey/vulpkanin - tail = "vulptail" - skinned_type = /obj/item/stack/sheet/fur - unarmed_type = /datum/unarmed_attack/claws - - blurb = "Vulpkanin are a species of sharp-witted canine-pideds residing on the planet Altam just barely within the \ - dual-star Vazzend system. Their politically de-centralized society and independent natures have led them to become a species and \ - culture both feared and respected for their scientific breakthroughs. Discovery, loyalty, and utilitarianism dominates their lifestyles \ - to the degree it can cause conflict with more rigorous and strict authorities. They speak a guttural language known as 'Canilunzt' \ - which has a heavy emphasis on utilizing tail positioning and ear twitches to communicate intent." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR - dietflags = DIET_OMNI - hunger_drain = 0.11 - taste_sensitivity = TASTE_SENSITIVITY_SHARP - reagent_tag = PROCESS_ORG - flesh_color = "#966464" - base_color = "#CF4D2F" - butt_sprite = "vulp" - - scream_verb = "yelps" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/vulpkanin, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) - unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, - /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!") - -/datum/species/vulpkanin/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/skrell - name = "Skrell" - name_plural = "Skrell" - icobase = 'icons/mob/human_races/r_skrell.dmi' - deform = 'icons/mob/human_races/r_def_skrell.dmi' - language = "Skrellian" - primitive_form = /datum/species/monkey/skrell - - blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \ - the royals' or 'Light of the Crown'.

Skrell are a highly advanced and logical race who live under the rule \ - of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \ - herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ - the secrets of their empire to their allies." - - species_traits = list(LIPS) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | HAS_BODY_MARKINGS - dietflags = DIET_HERB - taste_sensitivity = TASTE_SENSITIVITY_DULL - flesh_color = "#8CD7A3" - blood_color = "#1D2CBF" - base_color = "#38b661" //RGB: 56, 182, 97. - default_hair_colour = "#38b661" - eyes = "skrell_eyes_s" - //Default styles for created mobs. - default_hair = "Skrell Male Tentacles" - reagent_tag = PROCESS_ORG - butt_sprite = "skrell" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/skrell, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "headpocket" = /obj/item/organ/internal/headpocket - ) - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their thumbs into their eye sockets!", - "is twisting their own neck!", - "makes like a fish and suffocates!", - "is strangling themselves with their own tendrils!") - -/datum/species/vox - name = "Vox" - name_plural = "Vox" - icobase = 'icons/mob/human_races/vox/r_vox.dmi' - deform = 'icons/mob/human_races/vox/r_def_vox.dmi' - language = "Vox-pidgin" - tail = "voxtail" - speech_sounds = list('sound/voice/shriek1.ogg') - speech_chance = 20 - unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too. - - blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \ - scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \ - alive. They are four to five feet tall, reptillian, beaked, tailed and quilled; human crews often \ - refer to them as 'shitbirds' for their violent and offensive nature, as well as their horrible \ - smell.

Most humans will never meet a Vox raider, instead learning of this insular species through \ - dealing with their traders and merchants; those that do rarely enjoy the experience." - - brute_mod = 1.2 //20% more brute damage. Fragile bird bones. - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - breathid = "n2" - - eyes = "vox_eyes_s" - - species_traits = list(NO_SCAN, IS_WHITELISTED, NOTRANSSTING) - clothing_flags = HAS_SOCKS - dietflags = DIET_OMNI - bodyflags = HAS_ICON_SKIN_TONE | HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED | HAS_BODY_MARKINGS | HAS_TAIL_MARKINGS - - blood_color = "#2299FC" - flesh_color = "#808D11" - //Default styles for created mobs. - default_hair = "Short Vox Quills" - default_hair_colour = "#614f19" //R: 97, G: 79, B: 25 - butt_sprite = "vox" - - reagent_tag = PROCESS_ORG - scream_verb = "shrieks" - male_scream_sound = 'sound/voice/shriek1.ogg' - female_scream_sound = 'sound/voice/shriek1.ogg' - male_cough_sounds = list('sound/voice/shriekcough.ogg') - female_cough_sounds = list('sound/voice/shriekcough.ogg') - male_sneeze_sound = 'sound/voice/shrieksneeze.ogg' - female_sneeze_sound = 'sound/voice/shrieksneeze.ogg' - - icon_skin_tones = list( - 1 = "Default Green", - 2 = "Dark Green", - 3 = "Brown", - 4 = "Grey", - 5 = "Emerald", - 6 = "Azure" - ) - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs/vox, - "liver" = /obj/item/organ/internal/liver/vox, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "stack" = /obj/item/organ/internal/stack //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used - ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!", - "is deeply inhaling oxygen!") - -/datum/species/vox/handle_death(var/mob/living/carbon/human/H) - H.stop_tail_wagging(1) - -/datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H) - if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime") - H.unEquip(H.wear_mask) - H.unEquip(H.l_hand) - - H.equip_or_collect(new /obj/item/clothing/mask/breath/vox(H), slot_wear_mask) - var/tank_pref = H.client && H.client.prefs ? H.client.prefs.speciesprefs : null - if(tank_pref)//Diseasel, here you go - H.equip_or_collect(new /obj/item/tank/nitrogen(H), slot_l_hand) - else - H.equip_or_collect(new /obj/item/tank/emergency_oxygen/vox(H), slot_l_hand) - to_chat(H, "You are now running on nitrogen internals from the [H.l_hand] in your hand. Your species finds oxygen toxic, so you must breathe nitrogen only.") - H.internal = H.l_hand - H.update_action_buttons_icon() - -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - updatespeciescolor(H) - H.update_icons() - //H.verbs += /mob/living/carbon/human/proc/leap - ..() - -/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H, var/owner_sensitive = 1) //Handling species-specific skin-tones for the Vox race. - if(H.dna.species.bodyflags & HAS_ICON_SKIN_TONE) //Making sure we don't break Armalis. - var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox. - var/new_deform = 'icons/mob/human_races/vox/r_def_vox.dmi' //Default Green Vox. - switch(H.s_tone) - if(6) //Azure Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' - H.tail = "voxtail_azu" - if(5) //Emerald Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' - H.tail = "voxtail_emrl" - if(4) //Grey Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' - H.tail = "voxtail_gry" - if(3) //Brown Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' - H.tail = "voxtail_brn" - if(2) //Dark Green Vox. - new_icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi' - new_deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi' - H.tail = "voxtail_dgrn" - else //Default Green Vox. - H.tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone. - - H.change_icobase(new_icobase, new_deform, owner_sensitive) //Update the icobase/deform of all our organs, but make sure we don't mess with frankenstein limbs in doing so. - H.update_dna() - -/datum/species/vox/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R) - if(R.id == "oxygen") //Armalis are above such petty things. - H.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER) //Same as plasma. - H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM) - return 0 //Handling reagent removal on our own. - - return ..() - -/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H) - H.verbs += /mob/living/carbon/human/proc/leap - H.verbs += /mob/living/carbon/human/proc/gut - ..() - -/datum/species/vox/armalis - name = "Vox Armalis" - name_plural = "Vox Armalis" - icobase = 'icons/mob/human_races/r_armalis.dmi' - deform = 'icons/mob/human_races/r_armalis.dmi' - unarmed_type = /datum/unarmed_attack/claws/armalis - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - brute_mod = 0.2 - burn_mod = 0.2 - - eyes = "blank_eyes" - - species_traits = list(NO_SCAN, NO_BLOOD, NO_PAIN, IS_WHITELISTED) - bodyflags = HAS_TAIL - dietflags = DIET_OMNI //should inherit this from vox, this is here just in case - - blood_color = "#2299FC" - flesh_color = "#808D11" - - reagent_tag = PROCESS_ORG - - tail = "armalis_tail" - icon_template = 'icons/mob/human_races/r_armalis.dmi' - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs/vox, - "liver" = /obj/item/organ/internal/liver, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "stack" = /obj/item/organ/internal/stack //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used - ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. - - suicide_messages = list( - "is attempting to bite their tongue off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is holding their breath!", - "is huffing oxygen!") - -/datum/species/vox/armalis/handle_reagents() //Skip the Vox oxygen reagent toxicity. Armalis are above such things. - return 1 - -/datum/species/kidan - name = "Kidan" - name_plural = "Kidan" - icobase = 'icons/mob/human_races/r_kidan.dmi' - deform = 'icons/mob/human_races/r_def_kidan.dmi' - language = "Chittin" - unarmed_type = /datum/unarmed_attack/claws - - brute_mod = 0.8 - - species_traits = list(IS_WHITELISTED) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS - eyes = "kidan_eyes_s" - dietflags = DIET_HERB - blood_color = "#FB9800" - reagent_tag = PROCESS_ORG - //Default styles for created mobs. - default_headacc = "Normal Antennae" - butt_sprite = "kidan" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/kidan, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. - "lantern" = /obj/item/organ/internal/lantern - ) - - allowed_consumed_mobs = list(/mob/living/simple_animal/diona) - - suicide_messages = list( - "is attempting to bite their antenna off!", - "is jamming their claws into their eye sockets!", - "is twisting their own neck!", - "is cracking their exoskeleton!", - "is stabbing themselves with their mandibles!", - "is holding their breath!") - -/datum/species/slime - name = "Slime People" - name_plural = "Slime People" - language = "Bubblish" - icobase = 'icons/mob/human_races/r_slime.dmi' - deform = 'icons/mob/human_races/r_slime.dmi' - remains_type = /obj/effect/decal/remains/slime - - // More sensitive to the cold - cold_level_1 = 280 - cold_level_2 = 240 - cold_level_3 = 200 - coldmod = 3 - - oxy_mod = 0 - brain_mod = 2.5 - - male_cough_sounds = list('sound/effects/slime_squish.ogg') - female_cough_sounds = list('sound/effects/slime_squish.ogg') - - species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_INTORGANS, NO_SCAN) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | NO_EYES - dietflags = DIET_CARN - reagent_tag = PROCESS_ORG - - blood_color = "#0064C8" - exotic_blood = "water" - blood_damage_type = TOX - - butt_sprite = "slime" - //Has default darksight of 2. - - has_organ = list( - "brain" = /obj/item/organ/internal/brain/slime - ) - - suicide_messages = list( - "is melting into a puddle!", - "is ripping out their own core!", - "is turning a dull, brown color and melting into a puddle!") - - var/reagent_skin_coloring = FALSE - - var/datum/action/innate/regrow/grow = new() - - species_abilities = list( - /mob/living/carbon/human/verb/toggle_recolor_verb, - /mob/living/carbon/human/proc/regrow_limbs - ) - -/datum/species/slime/handle_post_spawn(var/mob/living/carbon/human/H) - grow.Grant(H) - ..() - -/datum/action/innate/regrow - name = "Regrow limbs" - icon_icon = 'icons/effects/effects.dmi' - button_icon_state = "greenglow" - -/datum/action/innate/regrow/Activate() - var/mob/living/carbon/human/user = owner - user.regrow_limbs() - - -/datum/species/slime/handle_life(var/mob/living/carbon/human/H) -//This is allegedly for code "style". Like a plaid sweater? -#define SLIMEPERSON_COLOR_SHIFT_TRIGGER 0.1 -#define SLIMEPERSON_ICON_UPDATE_PERIOD 200 // 20 seconds -#define SLIMEPERSON_BLOOD_SCALING_FACTOR 5 // Used to adjust how much of an effect the blood has on the rate of color change. Higher is slower. - // Slowly shifting to the color of the reagents - if(reagent_skin_coloring && H.reagents.total_volume > SLIMEPERSON_COLOR_SHIFT_TRIGGER) - var/blood_amount = H.blood_volume - var/r_color = mix_color_from_reagents(H.reagents.reagent_list) - var/new_body_color = BlendRGB(r_color, H.skin_colour, (blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)/((blood_amount*SLIMEPERSON_BLOOD_SCALING_FACTOR)+(H.reagents.total_volume))) - H.skin_colour = new_body_color - if(world.time % SLIMEPERSON_ICON_UPDATE_PERIOD > SLIMEPERSON_ICON_UPDATE_PERIOD - 20) // The 20 is because this gets called every 2 seconds, from the mob controller - for(var/organname in H.bodyparts_by_name) - var/obj/item/organ/external/E = H.bodyparts_by_name[organname] - if(istype(E) && E.dna && istype(E.dna.species, /datum/species/slime)) - E.sync_colour_to_human(H) - H.update_hair(0) - H.update_body() - ..() - -#undef SLIMEPERSON_COLOR_SHIFT_TRIGGER -#undef SLIMEPERSON_ICON_UPDATE_PERIOD -#undef SLIMEPERSON_BLOOD_SCALING_FACTOR - -/mob/living/carbon/human/proc/toggle_recolor(silent = FALSE) - if(!isslimeperson(src)) - if(!silent) - to_chat(src, "You're not a slime person!") - return - - var/datum/species/slime/S = dna.species - if(S.reagent_skin_coloring) - S.reagent_skin_coloring = TRUE - if(!silent) - to_chat(src, "You adjust your internal chemistry to filter out pigments from things you consume.") - else - S.reagent_skin_coloring = TRUE - if(!silent) - to_chat(src, "You adjust your internal chemistry to permit pigments in chemicals you consume to tint you.") - -/mob/living/carbon/human/verb/toggle_recolor_verb() - set category = "IC" - set name = "Toggle Reagent Recoloring" - set desc = "While active, you'll slowly adjust your body's color to that of the reagents inside of you, moderated by how much blood you have." - - toggle_recolor() - - -/mob/living/carbon/human/proc/regrow_limbs() - set category = "IC" - set name = "Regrow Limbs" - set desc = "Regrow one of your missing limbs at the cost of a large amount of hunger" - -#define SLIMEPERSON_HUNGERCOST 50 -#define SLIMEPERSON_MINHUNGER 250 -#define SLIMEPERSON_REGROWTHDELAY 450 // 45 seconds - - if(stat || paralysis || stunned) - to_chat(src, "You cannot regenerate missing limbs in your current state.") - return - - if(nutrition < SLIMEPERSON_MINHUNGER) - to_chat(src, "You're too hungry to regenerate a limb!") - return - - var/list/missing_limbs = list() - for(var/l in bodyparts_by_name) - var/obj/item/organ/external/E = bodyparts_by_name[l] - if(!istype(E)) - var/list/limblist = dna.species.has_limbs[l] - var/obj/item/organ/external/limb = limblist["path"] - var/parent_organ = initial(limb.parent_organ) - var/obj/item/organ/external/parentLimb = bodyparts_by_name[parent_organ] - if(!istype(parentLimb)) - continue - missing_limbs[initial(limb.name)] = l - - if(!missing_limbs.len) - to_chat(src, "You're not missing any limbs!") - return - - var/limb_select = input(src, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs - var/chosen_limb = missing_limbs[limb_select] - - visible_message("[src] begins to hold still and concentrate on [p_their()] missing [limb_select]...", "You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)") - if(do_after(src, SLIMEPERSON_REGROWTHDELAY, needhand=0, target = src)) - if(stat || paralysis || stunned) - to_chat(src, "You cannot regenerate missing limbs in your current state.") - return - - if(nutrition < SLIMEPERSON_MINHUNGER) - to_chat(src, "You're too hungry to regenerate a limb!") - return - - var/obj/item/organ/external/O = bodyparts_by_name[chosen_limb] - - var/stored_brute = 0 - var/stored_burn = 0 - if(istype(O)) - to_chat(src, "You distribute the damaged tissue around your body, out of the way of your new pseudopod!") - var/obj/item/organ/external/doomedStump = O - stored_brute = doomedStump.brute_dam - stored_burn = doomedStump.burn_dam - qdel(O) - - var/limb_list = dna.species.has_limbs[chosen_limb] - var/obj/item/organ/external/limb_path = limb_list["path"] - // Parent check - var/obj/item/organ/external/potential_parent = bodyparts_by_name[initial(limb_path.parent_organ)] - if(!istype(potential_parent)) - to_chat(src, "You've lost the organ that you've been growing your new part on!") - return // No rayman for you - // Grah this line will leave a "not used" warning, in spite of the fact that the new() proc WILL do the thing. - // Bothersome. - var/obj/item/organ/external/new_limb = new limb_path(src) - new_limb.open = 0 // This is just so that the compiler won't think that new_limb is unused, because the compiler is horribly stupid. - adjustBruteLoss(stored_brute) - adjustFireLoss(stored_burn) - update_body() - updatehealth("slime person regrowth") - UpdateDamageIcon() - nutrition -= SLIMEPERSON_HUNGERCOST - visible_message("[src] finishes regrowing [p_their()] missing [new_limb]!", "You finish regrowing your [limb_select]") - else - to_chat(src, "You need to hold still in order to regrow a limb!") - return - -#undef SLIMEPERSON_HUNGERCOST -#undef SLIMEPERSON_MINHUNGER -#undef SLIMEPERSON_REGROWTHDELAY - -/datum/species/slime/handle_pre_change(mob/living/carbon/human/H) - ..() - if(reagent_skin_coloring) - H.toggle_recolor(silent = 1) - -/datum/species/grey - name = "Grey" - name_plural = "Greys" - icobase = 'icons/mob/human_races/r_grey.dmi' - deform = 'icons/mob/human_races/r_def_grey.dmi' - language = "Psionic Communication" - eyes = "grey_eyes_s" - butt_sprite = "grey" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart, - "lungs" = /obj/item/organ/internal/lungs, - "liver" = /obj/item/organ/internal/liver/grey, - "kidneys" = /obj/item/organ/internal/kidneys, - "brain" = /obj/item/organ/internal/brain/grey, - "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/grey //5 darksight. - ) - - brute_mod = 1.25 //greys are fragile - - default_genes = list(REMOTE_TALK) - - - species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_BODY_MARKINGS - dietflags = DIET_HERB - reagent_tag = PROCESS_ORG - blood_color = "#A200FF" - -/datum/species/grey/handle_dna(var/mob/living/carbon/C, var/remove) - if(!remove) - C.dna.SetSEState(REMOTETALKBLOCK,1,1) - genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) - else - C.dna.SetSEState(REMOTETALKBLOCK,0,1) - genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) - ..() - -/datum/species/grey/water_act(var/mob/living/carbon/C, volume, temperature, source) - ..() - C.take_organ_damage(5,min(volume,20)) - C.emote("scream") - -/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) - var/speech_pref = H.client.prefs.speciesprefs - if(speech_pref) - H.mind.speech_span = "wingdings" - -/datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) - if(R.id == "sacid") - H.reagents.del_reagent(R.id) - return 0 - return ..() - -/datum/species/diona - name = "Diona" - name_plural = "Dionaea" - icobase = 'icons/mob/human_races/r_diona.dmi' - deform = 'icons/mob/human_races/r_def_plant.dmi' - language = "Rootspeak" - speech_sounds = list('sound/voice/dionatalk1.ogg') //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16] - speech_chance = 20 - unarmed_type = /datum/unarmed_attack/diona - //primitive_form = "Nymph" - slowdown = 5 - remains_type = /obj/effect/decal/cleanable/ash - - - warning_low_pressure = 50 - hazard_low_pressure = -1 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 300 - heat_level_2 = 340 - heat_level_3 = 400 - - blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \ - species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \ - there is no effective upper limit to the number that can fuse in gestalt, and reports exist of the Epsilon Ursae \ - Minoris primary being ringed with a cloud of singing space-station-sized entities.

The Dionaea coexist peacefully with \ - all known species, especially the Skrell. Their communal mind makes them slow to react, and they have difficulty understanding \ - even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \ - water and other radiation." - - species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN) - clothing_flags = HAS_SOCKS - default_hair_colour = "#000000" - dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary - taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE - skinned_type = /obj/item/stack/sheet/wood - - oxy_mod = 0 - - body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not - blood_color = "#004400" - flesh_color = "#907E4A" - butt_sprite = "diona" - - reagent_tag = PROCESS_ORG - - has_organ = list( - "nutrient channel" = /obj/item/organ/internal/liver/diona, - "neural strata" = /obj/item/organ/internal/heart/diona, - "receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2. - "gas bladder" = /obj/item/organ/internal/brain/diona, - "polyp segment" = /obj/item/organ/internal/kidneys/diona, - "anchoring ligament" = /obj/item/organ/internal/appendix/diona - ) - - vision_organ = /obj/item/organ/internal/eyes/diona - has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/chest/diona), - "groin" = list("path" = /obj/item/organ/external/groin/diona), - "head" = list("path" = /obj/item/organ/external/head/diona), - "l_arm" = list("path" = /obj/item/organ/external/arm/diona), - "r_arm" = list("path" = /obj/item/organ/external/arm/right/diona), - "l_leg" = list("path" = /obj/item/organ/external/leg/diona), - "r_leg" = list("path" = /obj/item/organ/external/leg/right/diona), - "l_hand" = list("path" = /obj/item/organ/external/hand/diona), - "r_hand" = list("path" = /obj/item/organ/external/hand/right/diona), - "l_foot" = list("path" = /obj/item/organ/external/foot/diona), - "r_foot" = list("path" = /obj/item/organ/external/foot/right/diona) - ) - - suicide_messages = list( - "is losing branches!", - "pulls out a secret stash of herbicide and takes a hearty swig!", - "is pulling themselves apart!") - -/datum/species/diona/can_understand(var/mob/other) - if(istype(other, /mob/living/simple_animal/diona)) - return 1 - return 0 - -/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER - - return ..() - -/datum/species/diona/handle_life(var/mob/living/carbon/human/H) - H.radiation = Clamp(H.radiation, 0, 100) //We have to clamp this first, then decrease it, or there's a few edge cases of massive heals if we clamp and decrease at the same time. - var/rads = H.radiation / 25 - H.radiation = max(H.radiation-rads, 0) - H.nutrition = min(H.nutrition+rads, NUTRITION_LEVEL_WELL_FED+10) - H.adjustBruteLoss(-(rads)) - H.adjustToxLoss(-(rads)) - - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(H.loc)) //else, there's considered to be no light - var/turf/T = H.loc - light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights - H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10) - - if(light_amount > 0) - H.clear_alert("nolight") - else - H.throw_alert("nolight", /obj/screen/alert/nolight) - - if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal - - H.adjustBruteLoss(-(light_amount/2)) - H.adjustFireLoss(-(light_amount/4)) - if(H.nutrition < NUTRITION_LEVEL_STARVING+50) - H.take_overall_damage(10,0) - ..() - -/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." - - icobase = 'icons/mob/human_races/r_machine.dmi' - deform = 'icons/mob/human_races/r_machine.dmi' - language = "Trinary" - remains_type = /obj/effect/decal/remains/robot - skinned_type = /obj/item/stack/sheet/metal // Let's grind up IPCs for station resources! - - 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. - tox_mod = 0 - clone_mod = 0 - oxy_mod = 0 - death_message = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off..." - - species_traits = list(IS_WHITELISTED, NO_BREATHE, NO_SCAN, NO_BLOOD, NO_PAIN, NO_DNA, RADIMMUNE, VIRUSIMMUNE, NOTRANSSTING) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS - dietflags = 0 //IPCs can't eat, so no diet - taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE - blood_color = "#1F181F" - flesh_color = "#AAAAAA" - //Default styles for created mobs. - default_hair = "Blue IPC Screen" - can_revive_by_healing = 1 - has_gender = FALSE - reagent_tag = PROCESS_SYN - male_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' - female_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' - male_cough_sounds = list('sound/effects/mob_effects/m_machine_cougha.ogg','sound/effects/mob_effects/m_machine_coughb.ogg', 'sound/effects/mob_effects/m_machine_coughc.ogg') - female_cough_sounds = list('sound/effects/mob_effects/f_machine_cougha.ogg','sound/effects/mob_effects/f_machine_coughb.ogg') - male_sneeze_sound = 'sound/effects/mob_effects/machine_sneeze.ogg' - female_sneeze_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg' - butt_sprite = "machine" - - has_organ = list( - "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, - "cell" = /obj/item/organ/internal/cell, - "optics" = /obj/item/organ/internal/eyes/optical_sensor, //Default darksight of 2. - "charger" = /obj/item/organ/internal/cyberimp/arm/power_cord - ) - - vision_organ = /obj/item/organ/internal/eyes/optical_sensor - has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/chest/ipc), - "groin" = list("path" = /obj/item/organ/external/groin/ipc), - "head" = list("path" = /obj/item/organ/external/head/ipc), - "l_arm" = list("path" = /obj/item/organ/external/arm/ipc), - "r_arm" = list("path" = /obj/item/organ/external/arm/right/ipc), - "l_leg" = list("path" = /obj/item/organ/external/leg/ipc), - "r_leg" = list("path" = /obj/item/organ/external/leg/right/ipc), - "l_hand" = list("path" = /obj/item/organ/external/hand/ipc), - "r_hand" = list("path" = /obj/item/organ/external/hand/right/ipc), - "l_foot" = list("path" = /obj/item/organ/external/foot/ipc), - "r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc) - ) - - suicide_messages = list( - "is powering down!", - "is smashing their own monitor!", - "is twisting their own neck!", - "is downloading extra RAM!", - "is frying their own circuits!", - "is blocking their ventilation port!") - - species_abilities = list( - /mob/living/carbon/human/proc/change_monitor - ) - -/datum/species/machine/handle_death(var/mob/living/carbon/human/H) - var/obj/item/organ/external/head/head_organ = H.get_organ("head") - if(!head_organ) - return - head_organ.h_style = "Bald" - head_organ.f_style = "Shaved" - spawn(100) - if(H) - H.update_hair() - H.update_fhair() - -/datum/species/drask - name = "Drask" - name_plural = "Drask" - icobase = 'icons/mob/human_races/r_drask.dmi' - deform = 'icons/mob/human_races/r_drask.dmi' - language = "Orluum" - eyes = "drask_eyes_s" - - speech_sounds = list('sound/voice/DraskTalk.ogg') - speech_chance = 20 - male_scream_sound = 'sound/voice/DraskTalk2.ogg' - female_scream_sound = 'sound/voice/DraskTalk2.ogg' - male_cough_sounds = 'sound/voice/DraskCough.ogg' - female_cough_sounds = 'sound/voice/DraskCough.ogg' - male_sneeze_sound = 'sound/voice/DraskSneeze.ogg' - female_sneeze_sound = 'sound/voice/DraskSneeze.ogg' - - burn_mod = 2 - //exotic_blood = "cryoxadone" - body_temperature = 273 - - blurb = "Hailing from Hoorlm, planet outside what is usually considered a habitable \ - orbit, the Drask evolved to live in extreme cold. Their strange bodies seem \ - to operate better the colder their surroundings are, and can regenerate rapidly \ - when breathing supercooled gas.

On their homeworld, the Drask live long lives \ - in their labyrinthine settlements, carved out beneath Hoorlm's icy surface, where the air \ - is of breathable density." - - suicide_messages = list( - "is self-warming with friction!", - "is jamming fingers through their big eyes!", - "is sucking in warm air!", - "is holding their breath!") - - species_traits = list(LIPS, IS_WHITELISTED) - clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT - bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS - dietflags = DIET_OMNI - - cold_level_1 = -1 //Default 260 - Lower is better - cold_level_2 = -1 //Default 200 - cold_level_3 = -1 //Default 120 - coldmod = -1 - - heat_level_1 = 300 //Default 360 - Higher is better - heat_level_2 = 340 //Default 400 - heat_level_3 = 400 //Default 460 - heatmod = 2 - - flesh_color = "#a3d4eb" - reagent_tag = PROCESS_ORG - base_color = "#a3d4eb" - blood_color = "#a3d4eb" - butt_sprite = "drask" - - has_organ = list( - "heart" = /obj/item/organ/internal/heart/drask, - "lungs" = /obj/item/organ/internal/lungs/drask, - "metabolic strainer" = /obj/item/organ/internal/liver/drask, - "eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight. - "brain" = /obj/item/organ/internal/brain/drask - ) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 4357584a18e..12efa71860a 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1082,7 +1082,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[TAIL_LAYER] = tail else if(tail && dna.species.bodyflags & HAS_TAIL) //no tailless tajaran - if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) + if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL)) var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]_s") if(dna.species.bodyflags & HAS_SKIN_COLOR) tail_s.Blend(skin_colour, ICON_ADD) diff --git a/code/modules/mob/living/carbon/human/update_stat.dm b/code/modules/mob/living/carbon/human/update_stat.dm index e079328206e..d8c26a91964 100644 --- a/code/modules/mob/living/carbon/human/update_stat.dm +++ b/code/modules/mob/living/carbon/human/update_stat.dm @@ -24,4 +24,10 @@ if((disabilities & NEARSIGHTED) && (!istype(G) || !G.prescription)) overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) else - clear_fullscreen("nearsighted") \ No newline at end of file + clear_fullscreen("nearsighted") + + +/mob/living/carbon/human/can_hear() + . = TRUE // Fallback if we don't have a species + if(dna.species) + . = dna.species.can_hear(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm deleted file mode 100644 index 4e74688e10f..00000000000 --- a/code/modules/mob/living/carbon/human/whisper.dm +++ /dev/null @@ -1,21 +0,0 @@ -//Lallander was here -/mob/living/carbon/human/whisper(message as text) - message = trim_strip_html_properly(message) //bit of duplicate code, acceptable because the workaround would be annoying - - //parse the language code and consume it - var/datum/language/speaking = parse_language(message) - if(speaking) - message = copytext(message, 2 + length(speaking.key)) - else - speaking = get_default_language() - - // This is broadcast to all mobs with the language, - // irrespective of distance or anything else. - if(speaking && (speaking.flags & HIVEMIND)) - speaking.broadcast(src,trim(message)) - return 1 - - message = trim_left(message) - message = handle_autohiss(message, speaking) - - whisper_say(message, speaking) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/slime/say.dm b/code/modules/mob/living/carbon/slime/say.dm index 04416e945ee..2096da01360 100644 --- a/code/modules/mob/living/carbon/slime/say.dm +++ b/code/modules/mob/living/carbon/slime/say.dm @@ -14,16 +14,16 @@ return 1 return ..() -/mob/living/carbon/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) +/mob/living/carbon/slime/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) if(speaker in Friends) speech_buffer = list() speech_buffer.Add(speaker) - speech_buffer.Add(lowertext(html_decode(message))) + speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces)))) ..() -/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target) +/mob/living/carbon/slime/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target) if(speaker in Friends) speech_buffer = list() speech_buffer.Add(speaker) - speech_buffer.Add(lowertext(html_decode(message))) + speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces)))) ..() diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 92a9a6b7b47..f766a1f53ce 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -337,3 +337,7 @@ if(INTENT_DISARM) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) return TRUE + +//defined here, overridden for humans in human_defense. By default, living mobs don't get to block anything +/mob/living/proc/check_block() + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index cb08ebff021..b32925badb4 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -54,51 +54,48 @@ proc/get_radio_key_from_channel(var/channel) /mob/living/proc/binarycheck() return FALSE -/mob/living/proc/get_default_language() +/mob/proc/get_default_language() + return null + +/mob/living/get_default_language() return default_language -/mob/living/proc/handle_speech_problems(var/message, var/verb) - var/list/returns[3] - var/speech_problem_flag = 0 +/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb) var/robot = isSynthetic() + for(var/datum/multilingual_say_piece/S in message_pieces) + if(S.speaking && S.speaking.flags & NO_STUTTER) + continue + if((HULK in mutations) && health >= 25) + S.message = "[uppertext(S.message)]!!!" + verb = pick("yells", "roars", "hollers") - if((HULK in mutations) && health >= 25 && length(message)) - message = "[uppertext(message)]!!!" - verb = pick("yells","roars","hollers") - speech_problem_flag = 1 + if(slurring) + if(robot) + S.message = slur(S.message, list("@", "!", "#", "$", "%", "&", "?")) + else + S.message = slur(S.message) + verb = "slurs" - if(slurring) - if(robot) - message = slur(message, list("@", "!", "#", "$", "%", "&", "?")) - else - message = slur(message) - verb = "slurs" - speech_problem_flag = 1 - if(stuttering) - if(robot) - message = robostutter(message) - else - message = stutter(message) - verb = "stammers" - speech_problem_flag = 1 - if(cultslurring) - message = cultslur(message) - verb = "slurs" - speech_problem_flag = 1 - if(!IsVocal()) - message = "" - speech_problem_flag = 1 + if(stuttering) + if(robot) + S.message = robostutter(S.message) + else + S.message = stutter(S.message) + verb = "stammers" - returns[1] = message - returns[2] = verb - returns[3] = speech_problem_flag - return returns + if(cultslurring) + S.message = cultslur(S.message) + verb = "slurs" -/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios) + if(!IsVocal()) + S.message = "" + return list("verb" = verb) + +/mob/living/proc/handle_message_mode(message_mode, list/message_pieces, verb, used_radios) switch(message_mode) if("whisper") //all mobs can whisper by default - whisper_say(message, speaking) + whisper_say(message_pieces) return 1 return 0 @@ -109,7 +106,7 @@ proc/get_radio_key_from_channel(var/channel) return returns -/mob/living/say(var/message, var/datum/language/speaking = null, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE) +/mob/living/say(var/message, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE) if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (Muted).") @@ -138,19 +135,17 @@ proc/get_radio_key_from_channel(var/channel) message = trim_left(message) //parse the language code and consume it - if(!speaking) - speaking = parse_language(message) - if(speaking) - message = copytext(message, 2 + length(speaking.key)) - else - speaking = get_default_language() - - // This is broadcast to all mobs with the language, - // irrespective of distance or anything else. - if(speaking && (speaking.flags & HIVEMIND)) - speaking.broadcast(src,trim(message)) + var/list/message_pieces = parse_languages(message) + if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages + var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting + S.speaking.broadcast(src, S.message) return 1 + + if(!LAZYLEN(message_pieces)) + log_runtime(EXCEPTION("Message failed to generate pieces. [message] - [json_encode(message_pieces)]")) + return 0 + if(message_mode == "cords") if(iscarbon(src)) var/mob/living/carbon/C = src @@ -160,7 +155,8 @@ proc/get_radio_key_from_channel(var/channel) V.speak_with(message) //words come before actions return 1 - verb = say_quote(message, speaking) + var/datum/multilingual_say_piece/first_piece = message_pieces[1] + verb = say_quote(message, first_piece.speaking) if(is_muzzled()) var/obj/item/clothing/mask/muzzle/G = wear_mask @@ -168,25 +164,19 @@ proc/get_radio_key_from_channel(var/channel) to_chat(src, "You're muzzled and cannot speak!") return else if(G.mute == MUZZLE_MUTE_MUFFLE) - message = muffledspeech(message) + muffledspeech_all(message_pieces) verb = "mumbles" - message = trim_left(message) + if(!ignore_speech_problems) + var/list/hsp = handle_speech_problems(message_pieces, verb) + verb = hsp["verb"] - message = handle_autohiss(message, speaking) - - if(!ignore_speech_problems && (speaking && !(speaking.flags & NO_STUTTER))) - var/list/handle_s = handle_speech_problems(message, verb) - message = handle_s[1] - verb = handle_s[2] - - if(!message || message == "") - return 0 var/list/used_radios = list() - if(handle_message_mode(message_mode, message, verb, speaking, used_radios)) + if(handle_message_mode(message_mode, message_pieces, verb, used_radios)) return 1 + var/list/handle_v = handle_speech_sound() var/sound/speech_sound = handle_v[1] var/sound_vol = handle_v[2] @@ -198,11 +188,12 @@ proc/get_radio_key_from_channel(var/channel) if(used_radios.len) italics = 1 message_range = 1 - if(speaking) - message_range = speaking.get_talkinto_msg_range(message) + if(first_piece.speaking) + message_range = first_piece.speaking.get_talkinto_msg_range(message) + var/msg - if(!speaking || !(speaking.flags & NO_TALK_MSG)) - msg = "\The [src] talks into \the [used_radios[1]]" + if(!first_piece.speaking || !(first_piece.speaking.flags & NO_TALK_MSG)) + msg = "[src] talks into [used_radios[1]]" if(msg) for(var/mob/living/M in hearers(5, src) - src) @@ -213,16 +204,6 @@ proc/get_radio_key_from_channel(var/channel) var/turf/T = get_turf(src) - - //handle nonverbal and sign languages here - if(speaking) - if(speaking.flags & NONVERBAL) - if(prob(30)) - custom_emote(1, "[pick(speaking.signlang_verb)].") - - if(speaking.flags & SIGNLANG) - return say_signlang(message, pick(speaking.signlang_verb), speaking) - var/list/listening = list() var/list/listening_obj = list() @@ -268,7 +249,7 @@ proc/get_radio_key_from_channel(var/channel) var/speech_bubble_test = say_test(message) for(var/mob/M in listening) - M.hear_say(message, verb, speaking, italics, src, speech_sound, sound_vol) + M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol) if(M.client) speech_bubble_recipients.Add(M.client) spawn(0) @@ -281,19 +262,13 @@ proc/get_radio_key_from_channel(var/channel) for(var/obj/O in listening_obj) spawn(0) if(O) //It's possible that it could be deleted in the meantime. - O.hear_talk(src, message, verb, speaking) + O.hear_talk(src, message_pieces, verb) //Log of what we've said, plain message, no spans or junk say_log += message - log_say(message, src) return 1 -/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) - for(var/mob/O in viewers(src, null)) - O.hear_signlang(message, verb, language, src) - return 1 - /obj/effect/speech_bubble var/mob/parent @@ -338,28 +313,19 @@ proc/get_radio_key_from_channel(var/channel) message = trim_strip_html_properly(message) //parse the language code and consume it - var/datum/language/speaking = parse_language(message) - if(speaking) - message = copytext(message, 2 + length(speaking.key)) - else - speaking = get_default_language() - - // This is broadcast to all mobs with the language, - // irrespective of distance or anything else. - if(speaking && (speaking.flags & HIVEMIND)) - speaking.broadcast(src,trim(message)) + var/list/message_pieces = parse_languages(message) + if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages + var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting + S.speaking.broadcast(src, S.message) return 1 - message = trim_left(message) - message = handle_autohiss(message, speaking) - - whisper_say(message, speaking) + whisper_say(message_pieces) // for weird circumstances where you're inside an atom that is also you, like pai's /mob/living/proc/get_whisper_loc() return src -/mob/living/proc/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers") +/mob/living/proc/whisper_say(list/message_pieces, verb = "whispers") if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (Muted).") @@ -367,7 +333,7 @@ proc/get_radio_key_from_channel(var/channel) if(stat) if(stat == DEAD) - return say_dead(message) + return say_dead(message_pieces) return if(is_muzzled()) @@ -382,37 +348,29 @@ proc/get_radio_key_from_channel(var/channel) var/watching_range = 5 var/italics = 1 var/adverb_added = FALSE - var/not_heard //the message displayed to people who could not hear the whispering - if(speaking) - if(speaking.whisper_verb) - verb = speaking.whisper_verb + + var/datum/multilingual_say_piece/first_piece = message_pieces[1] + if(first_piece.speaking) + if(first_piece.speaking.whisper_verb) + verb = first_piece.speaking.whisper_verb not_heard = "[verb] something" else var/adverb = pick("quietly", "softly") adverb_added = TRUE - verb = "[speaking.speech_verb] [adverb]" - not_heard = "[speaking.speech_verb] something [adverb]" + verb = "[first_piece.speaking.speech_verb] [adverb]" + not_heard = "[first_piece.speaking.speech_verb] something [adverb]" else not_heard = "[verb] something" - message = trim(message) - - var/speech_problem_flag = 0 - var/list/handle_s = handle_speech_problems(message, verb) - message = handle_s[1] - verb = handle_s[2] - speech_problem_flag = handle_s[3] + var/list/hsp = handle_speech_problems(message_pieces, verb) + verb = hsp["verb"] if(verb == "yells loudly") verb = "slurs emphatically" - - else if(speech_problem_flag && !adverb_added) + else if(!adverb_added) var/adverb = pick("quietly", "softly") verb = "[verb] [adverb]" - if(!message) - return - var/atom/whisper_loc = get_whisper_loc() var/list/listening = hear(message_range, whisper_loc) listening |= src @@ -450,7 +408,7 @@ proc/get_radio_key_from_channel(var/channel) for(var/obj/O in view(message_range, whisper_loc)) spawn(0) if(O) - O.hear_talk(src, message, verb, speaking) + O.hear_talk(src, message_pieces, verb) var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc) eavesdropping -= src @@ -463,17 +421,17 @@ proc/get_radio_key_from_channel(var/channel) //now mobs var/list/speech_bubble_recipients = list() - var/speech_bubble_test = say_test(message) + var/speech_bubble_test = say_test(multilingual_to_message(message_pieces)) for(var/mob/M in listening) - M.hear_say(message, verb, speaking, italics, src) + M.hear_say(message_pieces, verb, italics, src) if(M.client) speech_bubble_recipients.Add(M.client) if(eavesdropping.len) - var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less. + stars_all(message_pieces) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less. for(var/mob/M in eavesdropping) - M.hear_say(new_message, verb, speaking, italics, src) + M.hear_say(message_pieces, verb, italics, src) if(M.client) speech_bubble_recipients.Add(M.client) @@ -487,7 +445,7 @@ proc/get_radio_key_from_channel(var/channel) for(var/mob/M in watching) M.show_message(rendered, 2) - log_whisper(message, src) + log_whisper(multilingual_to_message(message_pieces), src) return 1 /mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list()) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 67bbc6c5388..a6400142086 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1184,19 +1184,11 @@ var/list/ai_verbs_default = list( var/list/viewscale = getviewsize(client.view) return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5) -/mob/living/silicon/ai/proc/relay_speech(mob/living/M, text, verb, datum/language/speaking) - if(!say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. - if(speaking) - text = speaking.scramble(text) - else - text = stars(text) +/mob/living/silicon/ai/proc/relay_speech(mob/living/M, list/message_pieces, verb) + var/message = combine_message(message_pieces, verb, M) var/name_used = M.GetVoice() //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. - var/rendered - if(speaking) - rendered = "Relayed Speech: [name_used] [speaking.format_message(text, verb)]" - else - rendered = "Relayed Speech: [name_used] [verb], \"[text]\"" + var/rendered = "Relayed Speech: [name_used] [message]" show_message(rendered, 2) /mob/living/silicon/ai/proc/malfhacked(obj/machinery/power/apc/apc) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 1037ec7fe61..98d010b878c 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -141,6 +141,10 @@ acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") -/mob/camera/aiEye/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) +/mob/camera/aiEye/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol) if(relay_speech) - ai.relay_speech(speaker, message, verb, language) + if(istype(ai)) + ai.relay_speech(speaker, message_pieces, verb) + else + var/mob/M = ai + M.hear_say(message_pieces, verb, italics, speaker, speech_sound, sound_vol) diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 431cf44a331..6b1306f94d1 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -3,7 +3,7 @@ */ -/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear) +/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear) if(hard_to_hear) return diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 76ac7ab9886..2ec1505741b 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -17,7 +17,6 @@ ventcrawler = 2 magpulse = 1 mob_size = MOB_SIZE_SMALL - default_language = "Drone" // We need to keep track of a few module items so we don't need to do list operations // every time we need them. These get set in New() after the module is chosen. @@ -38,7 +37,6 @@ /mob/living/silicon/robot/drone/New() - ..() remove_language("Robot Talk") diff --git a/code/modules/mob/living/silicon/robot/drone/drone_say.dm b/code/modules/mob/living/silicon/robot/drone/drone_say.dm index 741207d6f2d..7b51952a685 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_say.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_say.dm @@ -1,15 +1,14 @@ -/mob/living/silicon/robot/drone/say(var/message, var/datum/language/speaking = null) +/mob/living/silicon/robot/drone/say(var/message) if(copytext(message, 1, 2) == "*") return emote(copytext(message, 2)) - if(!speaking) - speaking = parse_language(message) - if(!speaking) - speaking = istype(get_default_language(), /datum/language) ? get_default_language() : GLOB.all_languages[get_default_language()] - message = speaking.key + " " + message; // Prepend key to prevent the message from getting trimmed - if(speaking) - return ..() + return ..() -/mob/living/silicon/robot/drone/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers") - say(message) //drones do not get to whisper, only speak normally - return 1 \ No newline at end of file +/mob/living/silicon/robot/drone/whisper_say(list/message_pieces) + say(multilingual_to_message(message_pieces)) //drones do not get to whisper, only speak normally + return 1 + +/mob/living/silicon/robot/drone/get_default_language() + if(default_language) + return default_language + return GLOB.all_languages["Drone"] \ No newline at end of file diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 48297dbb401..17a7e67adf7 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,9 +1,9 @@ -/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios) - log_say(message, src) +/mob/living/silicon/handle_message_mode(message_mode, list/message_pieces, verb, used_radios) + log_say(multilingual_to_message(message_pieces), src) if(..()) return 1 -/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios) +/mob/living/silicon/robot/handle_message_mode(message_mode, list/message_pieces, verb, used_radios) if(..()) return 1 if(message_mode) @@ -13,14 +13,14 @@ return 0 if(message_mode == "general") message_mode = null - return radio.talk_into(src,message,message_mode,verb,speaking) + return radio.talk_into(src,message_pieces,message_mode,verb) -/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios) +/mob/living/silicon/ai/handle_message_mode(message_mode, list/message_pieces, verb, used_radios) if(..()) return 1 if(message_mode == "department") used_radios += aiRadio - return holopad_talk(message, verb, speaking) + return holopad_talk(message_pieces, verb) else if(message_mode) used_radios += aiRadio if(aiRadio.disabledAi || aiRestorePowerRoutine || stat) @@ -28,19 +28,19 @@ return 0 if(message_mode == "general") message_mode = null - return aiRadio.talk_into(src,message,message_mode,verb,speaking) + return aiRadio.talk_into(src, message_pieces, message_mode, verb) -/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios) +/mob/living/silicon/pai/handle_message_mode(message_mode, list/message_pieces, verb, used_radios) if(..()) return 1 else if(message_mode == "whisper") - whisper_say(message, speaking) + whisper_say(message_pieces) return 1 else if(message_mode) if(message_mode == "general") message_mode = null used_radios += radio - return radio.talk_into(src,message,message_mode,verb,speaking) + return radio.talk_into(src, message_pieces, message_mode, verb) /mob/living/silicon/say_quote(var/text) var/ending = copytext(text, length(text)) @@ -70,41 +70,14 @@ return ..() //For holopads only. Usable by AI. -/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking) - log_say("(HPAD) [message]", src) - - message = trim(message) - - if(!message) - return +/mob/living/silicon/ai/proc/holopad_talk(list/message_pieces, verb) + log_say("(HPAD) [multilingual_to_message(message_pieces)]", src) var/obj/machinery/hologram/holopad/T = current if(istype(T) && T.masters[src]) - - //Human-like, sorta, heard by those who understand humans. - var/rendered_a - //Speach distorted, heard by those who do not understand AIs. - var/message_stars = stars(message) - var/rendered_b - - if(speaking) - rendered_a = "[name] [speaking.format_message(message, verb)]" - rendered_b = "[voice_name] [speaking.format_message(message_stars, verb)]" - to_chat(src, "Holopad transmitted, [real_name] [speaking.format_message(message, verb)]")//The AI can "hear" its own message. - - else - rendered_a = "[name] [verb], \"[message]\"" - rendered_b = "[voice_name] [verb], \"[message_stars]\"" - to_chat(src, "Holopad transmitted, [real_name] [verb], \"[message]\"")//The AI can "hear" its own message. - - for(var/mob/M in hearers(T.loc))//The location is the object, default distance. - if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to. - M.show_message(rendered_a, 2) - else//If they do not. - M.show_message(rendered_b, 2) - /*Radios "filter out" this conversation channel so we don't need to account for them. - This is another way of saying that we won't bother dealing with them.*/ + M.hear_holopad_talk(message_pieces, verb, src) + to_chat(src, "Holopad transmitted, [real_name] [combine_message(message_pieces, verb, src)]") else to_chat(src, "No holopad connected.") return diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 070a7d60e84..1c7cb902be3 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -65,6 +65,9 @@ /mob/living/simple_animal/bot/medbot/fish skin = "fish" +/mob/living/simple_animal/bot/medbot/machine + skin = "machine" + /mob/living/simple_animal/bot/medbot/mysterious name = "\improper Mysterious Medibot" desc = "International Medibot of mystery." @@ -578,6 +581,8 @@ T.syndicate_aligned = syndicate_aligned //This is a special case since Syndicate medibots and the mysterious medibot look the same; we also dont' want crew building Syndicate medibots if the mysterious medibot blows up. if("fish") new /obj/item/storage/firstaid/aquatic_kit(Tsec) + if("machine") + new /obj/item/storage/firstaid/machine/empty(Tsec) else new /obj/item/storage/firstaid(Tsec) diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 3ed45508b87..5ebaf47afb2 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -33,6 +33,9 @@ can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY +/mob/living/simple_animal/mouse/Initialize() + . = ..() + /mob/living/simple_animal/mouse/handle_automated_speech() ..() if(prob(speak_chance)) @@ -81,39 +84,16 @@ get_scooped(M) ..() -//make mice fit under tables etc? this was hacky, and not working -/* -/mob/living/simple_animal/mouse/Move(var/dir) - - var/turf/target_turf = get_step(src,dir) - //CanReachThrough(src.loc, target_turf, src) - var/can_fit_under = 0 - if(target_turf.ZCanPass(get_turf(src),1)) - can_fit_under = 1 - - ..(dir) - if(can_fit_under) - src.loc = target_turf - for(var/d in cardinal) - var/turf/O = get_step(T,d) - //Simple pass check. - if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles) - open += O - */ - -///mob/living/simple_animal/mouse/restrained() //Hotfix to stop mice from doing things with MouseDrop -// return 1 - /mob/living/simple_animal/mouse/start_pulling(var/atom/movable/AM)//Prevents mouse from pulling things to_chat(src, "You are too small to pull anything.") return /mob/living/simple_animal/mouse/Crossed(AM as mob|obj) - if( ishuman(AM) ) - if(!stat) + if(ishuman(AM)) + if(stat == CONSCIOUS) var/mob/M = AM to_chat(M, "[bicon(src)] Squeek!") - M << 'sound/effects/mousesqueek.ogg' + SEND_SOUND(M, 'sound/effects/mousesqueek.ogg') ..() /mob/living/simple_animal/mouse/death(gibbed) diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index 2bb792fbb81..1e8d5eeb609 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -60,4 +60,18 @@ if(istype(L)) if(prob(15)) L.Stun(1) - L.visible_message("\the [src] scares \the [L]!") \ No newline at end of file + L.visible_message("\the [src] scares \the [L]!") + + +/mob/living/simple_animal/hostile/scarybat/batswarm + name = "bat swarm" + desc = "A swarm of vicious, angry-looking space bats." + speed = 1 + harm_intent_damage = 25 + maxHealth = 300 + melee_damage_lower = 10 + melee_damage_upper = 30 + a_intent = INTENT_HARM + pass_flags = PASSTABLE + universal_speak = 1 + universal_understand = 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm new file mode 100644 index 00000000000..65a2391acb1 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm @@ -0,0 +1,131 @@ +// Hellhound +/mob/living/simple_animal/hostile/hellhound + // Sprites by FoS: http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 + name = "Lesser Hellhound" + desc = "A horrifying, black canine monster, with glowing red eyes and vicious-looking teeth. A firey, lava-like substance drips from it." + icon_state = "hellhound" + icon_living = "hellhound" + icon_dead = "hellhound_dead" + icon_resting = "hellhound_rest" + mutations = list(BREATHLESS) + gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + maxbodytemp = INFINITY + melee_damage_lower = 10 // slightly higher than araneus + melee_damage_upper = 30 + a_intent = INTENT_HARM + environment_smash = 1 + speak_chance = 0 + speed = 0 + maxHealth = 250 // same as sgt araneus + health = 250 + obj_damage = 50 + robust_searching = 1 + stat_attack = 1 + attacktext = "savages" + attack_sound = 'sound/effects/bite.ogg' + speak_emote = list("growls") + see_in_dark = 9 + universal_understand = 1 + wander = 0 + var/life_regen_cycles = 0 + var/life_regen_cycle_trigger = 10 // heal once for every X number of cycles spent resting + var/life_regen_amount = -10 // negative, because negative = healing + var/smoke_lastuse = 0 + var/smoke_freq = 300 // 30 seconds + var/datum/action/innate/demon/whisper/whisper_action + +/mob/living/simple_animal/hostile/hellhound/New() + . = ..() + whisper_action = new() + whisper_action.Grant(src) + +/mob/living/simple_animal/hostile/hellhound/handle_automated_action() + . = ..() + if(resting) + if(!wants_to_rest()) + custom_emote(1, "growls, and gets up.") + playsound(get_turf(src), 'sound/hallucinations/growl2.ogg', 50, 1) + icon_state = "[icon_living]" + resting = 0 + update_canmove() + else if(wants_to_rest()) + custom_emote(1, "lays down, and starts to lick their wounds.") + icon_state = "[icon_resting]" + resting = 1 + update_canmove() + +/mob/living/simple_animal/hostile/hellhound/examine(mob/user) + . = ..() + if(stat != DEAD) + var/list/msgs = list() + if(key) + msgs += "Its eyes have the spark of intelligence." + if(health > (maxHealth*0.95)) + msgs += "It appears to be in excellent health." + else if(health > (maxHealth*0.75)) + msgs += "It has a few injuries." + else if(health > (maxHealth*0.55)) + msgs += "It has many injuries." + else if(health > (maxHealth*0.25)) + msgs += "It is covered in wounds!" + if(resting) + if(bruteloss > 0 || fireloss > 0) + msgs += "It is currently licking its wounds, regenerating the damage to its body!" + else + msgs += "It is currently resting." + to_chat(usr,msgs.Join("
")) + +/mob/living/simple_animal/hostile/hellhound/Life(seconds, times_fired) + . = ..() + if(stat != DEAD && resting && (bruteloss > 0) || (fireloss > 0)) + if(life_regen_cycles >= life_regen_cycle_trigger) + life_regen_cycles = 0 + to_chat(src, "You lick your wounds, helping them close.") + adjustBruteLoss(life_regen_amount) + adjustFireLoss(life_regen_amount) + else + life_regen_cycles++ + +/mob/living/simple_animal/hostile/hellhound/proc/wants_to_rest() + if(target) + return FALSE + if(bruteloss > 0 || fireloss > 0) + return TRUE + return FALSE + +/mob/living/simple_animal/hostile/hellhound/AttackingTarget() + . = ..() + if(ishuman(target)) + special_aoe() + +/mob/living/simple_animal/hostile/hellhound/attackby(obj/item/C, mob/user, params) + . = ..() + if(target && isliving(target)) + var/mob/living/L = target + if(L.stat != CONSCIOUS) + target = user + +/mob/living/simple_animal/hostile/hellhound/proc/special_aoe() + if(world.time < (smoke_lastuse + smoke_freq)) + return + smoke_lastuse = world.time + var/datum/effect_system/smoke_spread/sleeping/smoke = new + smoke.set_up(10, 0, loc) + smoke.start() + +/mob/living/simple_animal/hostile/hellhound/greater + name = "Greater Hellhound" + icon_state = "hellhoundgreater" + icon_living = "hellhoundgreater" + icon_resting = "hellhoundgreater_sit" + maxHealth = 400 + health = 400 + force_threshold = 5 // no punching + smoke_freq = 200 + life_regen_cycle_trigger = 5 + melee_damage_lower = 20 + melee_damage_upper = 30 + environment_smash = 2 + gold_core_spawnable = CHEM_MOB_SPAWN_INVALID diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index a60ae1d323e..c8e43a936d2 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -704,21 +704,21 @@ available_channels = list(":e") ..() -/mob/living/simple_animal/parrot/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios) +/mob/living/simple_animal/parrot/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios) if(message_mode && istype(ears)) - ears.talk_into(src, message, message_mode, verb, speaking) + ears.talk_into(src, message_pieces, message_mode, verb) used_radios += ears -/mob/living/simple_animal/parrot/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null) +/mob/living/simple_animal/parrot/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null) if(speaker != src && prob(50)) - parrot_hear(html_decode(message)) + parrot_hear(html_decode(multilingual_to_message(message_pieces))) ..() -/mob/living/simple_animal/parrot/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/atom/follow_target) +/mob/living/simple_animal/parrot/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/atom/follow_target) if(speaker != src && prob(50)) - parrot_hear(html_decode(message)) + parrot_hear(html_decode(multilingual_to_message(message_pieces))) ..() diff --git a/code/modules/mob/living/update_status.dm b/code/modules/mob/living/update_status.dm index 94769baf94b..daf058bb41b 100644 --- a/code/modules/mob/living/update_status.dm +++ b/code/modules/mob/living/update_status.dm @@ -44,7 +44,7 @@ . = !(disabilities & DEAF) // Whether the mob is able to see -// `information_only` is for stuff that's purely informational - like understanding nonverbal languages, or blindness overlays +// `information_only` is for stuff that's purely informational - like blindness overlays // This flag exists because certain things like angel statues expect this to be false for dead people /mob/living/has_vision(information_only = FALSE) return (information_only && stat == DEAD) || !(eye_blind || (disabilities & BLIND) || stat) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 659a50880a0..46b7d1141b8 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -177,6 +177,10 @@ p++ return t +/proc/stars_all(list/message_pieces, pr) + for(var/datum/multilingual_say_piece/S in message_pieces) + S.message = stars(S.message, pr) + /proc/slur(phrase, var/list/slurletters = ("'"))//use a different list as an input if you want to make robots slur with $#@%! characters phrase = html_decode(phrase) var/leng=lentext(phrase) @@ -266,6 +270,11 @@ return returntext +/proc/Gibberish_all(list/message_pieces, p) + for(var/datum/multilingual_say_piece/S in message_pieces) + S.message = Gibberish(S.message, p) + + proc/muffledspeech(phrase) phrase = html_decode(phrase) var/leng=lentext(phrase) @@ -284,6 +293,10 @@ proc/muffledspeech(phrase) counter-=1 return newphrase +/proc/muffledspeech_all(list/message_pieces) + for(var/datum/multilingual_say_piece/S in message_pieces) + S.message = muffledspeech(S.message) + /proc/shake_camera(mob/M, duration, strength=1) if(!M || !M.client || M.shakecamera) diff --git a/code/modules/mob/new_player/sprite_accessories/unathi/unathi_head_markings.dm b/code/modules/mob/new_player/sprite_accessories/unathi/unathi_head_markings.dm index 25d74d605e2..b410148b0c9 100644 --- a/code/modules/mob/new_player/sprite_accessories/unathi/unathi_head_markings.dm +++ b/code/modules/mob/new_player/sprite_accessories/unathi/unathi_head_markings.dm @@ -32,6 +32,7 @@ /datum/sprite_accessory/body_markings/head/unathi/points_una //Companion marking for Unathi Points. name = "Unathi Points Head" icon_state = "pointsface" + heads_allowed = list("All") /datum/sprite_accessory/body_markings/head/unathi/sharp heads_allowed = list("Unathi Sharp Snout") @@ -47,7 +48,3 @@ /datum/sprite_accessory/body_markings/head/unathi/sharp/snout_narrow_una_sharp //Companion marking for Unathi Narrow Belly. name = "Unathi Sharp Snout 2" icon_state = "facesharp" - -/datum/sprite_accessory/body_markings/head/unathi/sharp/points_una_sharp //Companion marking for Unathi Points. - name = "Unathi Sharp Points Head" - icon_state = "pointsface" \ No newline at end of file diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index a1236e9c719..aeb6d8f14bf 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -132,17 +132,77 @@ return null -//parses the language code (e.g. :j) from text, such as that supplied to say. -//returns the language object only if the code corresponds to a language that src can speak, otherwise null. -/mob/proc/parse_language(var/message) - var/prefix = copytext(message, 1, 2) - if(length(message) >= 1 && prefix == "!") - return GLOB.all_languages["Noise"] +/datum/multilingual_say_piece + var/datum/language/speaking = null + var/message = "" - if(length(message) >= 2) - var/language_prefix = trim_right(lowertext(copytext(message, 1 ,4))) - var/datum/language/L = GLOB.language_keys[language_prefix] - if(can_speak_language(L)) - return L +/datum/multilingual_say_piece/New(datum/language/new_speaking, new_message) + . = ..() + speaking = new_speaking + if(new_message) + message = new_message - return null +/mob/proc/find_valid_prefixes(message) + var/list/prefixes = list() // [["Common", start, end], ["Gutter", start, end]] + for(var/i in 1 to length(message)) + var/selection = trim_right(lowertext(copytext(message, i, i + 3))) + var/datum/language/L = GLOB.language_keys[selection] + if(L != null && can_speak_language(L)) // What the fuck... remove the L != null check if you ever find out what the fuck is adding `null` to the languages list on absolutely random mobs... seriously what the hell... + prefixes[++prefixes.len] = list(L, i, i + length(selection)) + else if(!L && i == 1) + prefixes[++prefixes.len] = list(get_default_language(), i, i) + else + return prefixes + +/proc/strip_prefixes(message) + . = "" + var/last_index = 1 + for(var/i in 1 to length(message)) + var/selection = trim_right(lowertext(copytext(message, i, i + 3))) + var/datum/language/L = GLOB.language_keys[selection] + if(L) + . += copytext(message, last_index, i) + last_index = i + 3 + if(i + 1 > length(message)) + . += copytext(message, last_index) + +// this returns a structured message with language sections +// list(/datum/multilingual_say_piece(common, "hi"), /datum/multilingual_say_piece(farwa, "squik"), /datum/multilingual_say_piece(common, "meow!")) +/mob/proc/parse_languages(message) + . = list() + + // Noise language is a snowflake + if(copytext(message, 1, 2) == "!" && length(message) > 1) + return list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], trim(strip_prefixes(copytext(message, 2))))) + + // Scan the message for prefixes + var/list/prefix_locations = find_valid_prefixes(message) + if(!LAZYLEN(prefix_locations)) // There are no prefixes... or at least, no _valid_ prefixes. + . += new /datum/multilingual_say_piece(get_default_language(), trim(strip_prefixes(message))) // So we'll just strip those pesky things and still make the message. + + for(var/i in 1 to length(prefix_locations)) + var/current = prefix_locations[i] // ["Common", keypos] + + // There are a few things that will make us want to ignore all other languages in - namely, HIVEMIND languages. + var/datum/language/L = current[1] + if(L && L.flags & HIVEMIND) + . = new /datum/multilingual_say_piece(L, trim(strip_prefixes(message))) + break + + if(i + 1 > length(prefix_locations)) // We are out of lookaheads, that means the rest of the message is in cur lang + var/spoke_message = handle_autohiss(trim(copytext(message, current[3])), L) + . += new /datum/multilingual_say_piece(current[1], spoke_message) + else + var/next = prefix_locations[i + 1] // We look ahead at the next message to see where we need to stop. + var/spoke_message = handle_autohiss(trim(copytext(message, current[3], next[2])), L) + . += new /datum/multilingual_say_piece(current[1], spoke_message) + +/* These are here purely because it would be hell to try to convert everything over to using the multi-lingual system at once */ +/proc/message_to_multilingual(message, datum/language/speaking = null) + . = list(new /datum/multilingual_say_piece(speaking, message)) + +/proc/multilingual_to_message(list/message_pieces) + . = "" + for(var/datum/multilingual_say_piece/S in message_pieces) + . += S.message + " " + . = trim_right(.) \ No newline at end of file diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index cd0832bd714..47e98b8e1b9 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -2,6 +2,7 @@ var/list/obj/machinery/photocopier/faxmachine/allfaxes = list() var/list/admin_departments = list("Central Command") var/list/hidden_admin_departments = list("Syndicate") var/list/alldepartments = list() +var/global/list/fax_blacklist = list() /obj/machinery/photocopier/faxmachine name = "fax machine" @@ -160,7 +161,9 @@ var/list/alldepartments = list() if(href_list["auth"]) if(!is_authenticated && scan) - if(check_access(scan)) + if(scan.registered_name in fax_blacklist) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + else if(check_access(scan)) authenticated = 1 else if(is_authenticated) authenticated = 0 @@ -322,3 +325,9 @@ var/list/alldepartments = list() to_chat(C, msg) if(C.prefs.sound & SOUND_ADMINHELP) C << 'sound/effects/adminhelp.ogg' + +/obj/machinery/photocopier/faxmachine/proc/become_mimic() + if(scan) + scan.forceMove(get_turf(src)) + var/mob/living/simple_animal/hostile/mimic/copy/M = new(loc, src, null, 1) // it will delete src on creation and override any machine checks + M.name = "angry fax machine" \ No newline at end of file diff --git a/code/modules/paperwork/frames.dm b/code/modules/paperwork/frames.dm index 4203b5abfff..cbffb1cd117 100644 --- a/code/modules/paperwork/frames.dm +++ b/code/modules/paperwork/frames.dm @@ -297,10 +297,10 @@ toggle_tilt(usr) -/obj/structure/sign/picture_frame/hear_talk(mob/living/M as mob, msg) +/obj/structure/sign/picture_frame/hear_talk(mob/living/M as mob, list/message_pieces) ..() for(var/obj/O in contents) - O.hear_talk(M, msg) + O.hear_talk(M, message_pieces) /obj/structure/sign/picture_frame/hear_message(mob/living/M as mob, msg) ..() diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 06921bce252..40cc2bcc534 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -596,6 +596,7 @@ var/used = 0 var/countdown = 60 var/activate_on_timeout = 0 + var/faxmachineid = null /obj/item/paper/evilfax/show_content(var/mob/user, var/forceshow = 0, var/forcestars = 0, var/infolinks = 0, var/view = 1) if(user == mytarget) @@ -642,7 +643,8 @@ /obj/item/paper/evilfax/proc/evilpaper_specialaction(var/mob/living/carbon/target) spawn(30) - if(istype(target,/mob/living/carbon)) + if(istype(target, /mob/living/carbon)) + var/obj/machinery/photocopier/faxmachine/fax = locateUID(faxmachineid) if(myeffect == "Borgification") to_chat(target,"You seem to comprehend the AI a little better. Why are your muscles so stiff?") target.ForceContractDisease(new /datum/disease/transformation/robot(0)) @@ -668,8 +670,25 @@ var/mob/living/carbon/human/H = target to_chat(H, "You feel surrounded by sadness. Sadness... and HONKS!") H.makeCluwne() - else if(myeffect == "Demotion Notice") - event_announcement.Announce("[mytarget] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + else if(myeffect == "Demote") + event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + else if(myeffect == "Demote with Bot") + event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + for(var/datum/data/record/R in sortRecord(data_core.security)) + if(R.fields["name"] == target.real_name) + R.fields["criminal"] = "*Arrest*" + update_all_mob_security_hud() + if(fax) + var/turf/T = get_turf(fax) + new /obj/effect/portal(T) + new /mob/living/simple_animal/bot/secbot(T) + else if(myeffect == "Revoke Fax Access") + fax_blacklist += target.real_name + if(fax) + fax.authenticated = 0 + else if(myeffect == "Angry Fax Machine") + if(fax) + fax.become_mimic() else message_admins("Evil paper [src] was activated without a proper effect set! This is a bug.") used = 1 diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 3b37e551e0f..688bffa8ebc 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -541,7 +541,8 @@ var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","s if(..(user, 1)) to_chat(user, "This video camera can send live feeds to the entertainment network. It's [camera ? "" : "in"]active.") -/obj/item/videocam/hear_talk(mob/M as mob, msg) +/obj/item/videocam/hear_talk(mob/M as mob, list/message_pieces) + var/msg = multilingual_to_message(message_pieces) if(camera && on) if(get_dist(src, M) <= canhear_range) talk_into(M, msg) diff --git a/code/modules/pda/utilities.dm b/code/modules/pda/utilities.dm index a03a36e005a..4b2d02c33d4 100644 --- a/code/modules/pda/utilities.dm +++ b/code/modules/pda/utilities.dm @@ -109,8 +109,12 @@ if(A.reagents.reagent_list.len > 0) var/reagents_length = A.reagents.reagent_list.len to_chat(user, "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.") - for(var/re in A.reagents.reagent_list) - to_chat(user, "\t [re]") + for(var/datum/reagent/R in A.reagents.reagent_list) + if(R.id != "blood") + to_chat(user, "\t [R]") + else + var/blood_type = R.data["blood_type"] + to_chat(user, "\t [R] [blood_type]") else to_chat(user, "No active chemical agents found in [A].") else diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index 43112467f33..c525ef92ee1 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -29,6 +29,12 @@ icon_state = "r-casing" projectile_type = /obj/item/projectile/bullet/weakbullet2 +/obj/item/ammo_casing/c38/invisible + projectile_type = /obj/item/projectile/bullet/weakbullet2/invisible + +/obj/item/ammo_casing/c38/invisible/fake + projectile_type = /obj/item/projectile/bullet/weakbullet2/invisible/fake + /obj/item/ammo_casing/c10mm desc = "A 10mm bullet casing." caliber = "10mm" diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index e621b1906b4..6d6e28092c1 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -61,6 +61,14 @@ caliber = "38" max_ammo = 6 +/obj/item/ammo_box/magazine/internal/cylinder/rev38/invisible + name = "finger gun cylinder" + desc = "Wait, what?" + ammo_type = /obj/item/ammo_casing/c38/invisible + +/obj/item/ammo_box/magazine/internal/cylinder/rev38/invisible/fake + ammo_type = /obj/item/ammo_casing/c38/invisible/fake + /obj/item/ammo_box/magazine/internal/cylinder/rev762 name = "nagant revolver cylinder" ammo_type = /obj/item/ammo_casing/n762 diff --git a/code/modules/projectiles/gun_attachments.dm b/code/modules/projectiles/gun_attachments.dm new file mode 100644 index 00000000000..9a5156b4546 --- /dev/null +++ b/code/modules/projectiles/gun_attachments.dm @@ -0,0 +1,19 @@ +//Put all your tacticool gun gadgets here. So far it's pretty empty + + +/obj/item/suppressor + name = "suppressor" + desc = "A universal syndicate small-arms suppressor for maximum espionage." + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "suppressor" + item_state = "suppressor" + w_class = WEIGHT_CLASS_SMALL + var/oldsound = null + var/initial_w_class = null + origin_tech = "combat=2;engineering=2" + +/obj/item/suppressor/specialoffer + name = "cheap suppressor" + desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits all weapons." + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "suppressor" diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 0ff5e57e7c5..39654c96a2b 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -183,20 +183,4 @@ for(var/obj/item/ammo_casing/AC in magazine.stored_ammo) if(AC.BB) process_fire(user, user,0) - . = 1 - -/obj/item/suppressor - name = "suppressor" - desc = "A universal syndicate small-arms suppressor for maximum espionage." - icon = 'icons/obj/guns/projectile.dmi' - icon_state = "suppressor" - item_state = "suppressor" - w_class = WEIGHT_CLASS_SMALL - var/oldsound = null - var/initial_w_class = null - -/obj/item/suppressor/specialoffer - name = "cheap suppressor" - desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits all weapons." - icon = 'icons/obj/guns/projectile.dmi' - icon_state = "suppressor" + . = 1 \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index c4c6f76a963..2f7a7fc1cd9 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -142,6 +142,48 @@ desc = initial(desc) to_chat(user, "You remove the modifications on [src]. Now it will fire .38 rounds.") +/obj/item/gun/projectile/revolver/fingergun //Summoned by the Finger Gun spell, from advanced mimery traitor item + name = "\improper finger gun" + desc = "Bang bang bang!" + icon_state = "fingergun" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38/invisible + origin_tech = "" + flags = ABSTRACT | NODROP | DROPDEL + slot_flags = null + fire_sound = null + fire_sound_text = null + lefthand_file = null + righthand_file = null + clumsy_check = 0 //Stole your uplink! Honk! + needs_permit = 0 //go away beepsky + +/obj/item/gun/projectile/revolver/fingergun/fake + desc = "Pew pew pew!" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38/invisible/fake + +/obj/item/gun/projectile/revolver/fingergun/New() + ..() + verbs -= /obj/item/gun/projectile/revolver/verb/spin + +/obj/item/gun/projectile/revolver/fingergun/shoot_with_empty_chamber(/*mob/living/user as mob|obj*/) + to_chat(usr, "You are out of ammo! You holster your fingers.") + qdel(src) + return + +/obj/item/gun/projectile/revolver/fingergun/afterattack(atom/target, mob/living/user, flag, params) + if(!user.mind.miming) + to_chat(usr, "You must dedicate yourself to silence first. Use your fingers if you wish to holster them.") + return + ..() + +/obj/item/gun/projectile/revolver/fingergun/attackby(obj/item/A, mob/user, params) + return + +/obj/item/gun/projectile/revolver/fingergun/attack_self(mob/living/user) + to_chat(usr, "You holster your fingers. Another time.") + qdel(src) + return + /obj/item/gun/projectile/revolver/mateba name = "\improper Unica 6 auto-revolver" desc = "A retro high-powered autorevolver typically used by officers of the New Russia military. Uses .357 ammo." //>10mm hole >.357 diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 39f25c5ef89..949983d45ba 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -30,7 +30,9 @@ var/spread = 0 //amount (in degrees) of projectile spread var/legacy = FALSE //legacy projectile system animate_movement = 0 - + + var/ignore_source_check = FALSE + var/damage = 10 var/tile_dropoff = 0 //how much damage should be decremented as the bullet moves var/tile_dropoff_s = 0 //same as above but for stamina @@ -54,6 +56,9 @@ var/jitter = 0 var/forcedodge = 0 //to pass through everything var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all. + var/ricochets = 0 + var/ricochets_max = 2 + var/ricochet_chance = 0 var/log_override = FALSE //whether print to admin attack logs or just keep it in the diary @@ -62,15 +67,15 @@ return ..() /obj/item/projectile/proc/Range() - range-- - if(damage && tile_dropoff) - damage = max(0, damage - tile_dropoff) // decrement projectile damage based on dropoff value for each tile it moves - if(stamina && tile_dropoff_s) - stamina = max(0, stamina - tile_dropoff_s) // as above, but with stamina - if(range <= 0 && loc) - on_range() - if(!damage && !stamina && !nodamage) - on_range() + range-- + if(damage && tile_dropoff) + damage = max(0, damage - tile_dropoff) // decrement projectile damage based on dropoff value for each tile it moves + if(stamina && tile_dropoff_s) + stamina = max(0, stamina - tile_dropoff_s) // as above, but with stamina + if(range <= 0 && loc) + on_range() + if(!damage && !stamina && (tile_dropoff || tile_dropoff_s)) + on_range() /obj/item/projectile/proc/on_range() //if we want there to be effects when they reach the end of their range qdel(src) @@ -157,6 +162,14 @@ /obj/item/projectile/Bump(atom/A, yes) if(!yes) //prevents double bumps. return + + if(check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max) + ricochets++ + if(A.handle_ricochet(src)) + on_ricochet(A) + ignore_source_check = TRUE + range = initial(range) + return TRUE if(firer) if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech loc = A.loc @@ -280,3 +293,21 @@ obj/item/projectile/Crossed(atom/movable/AM) //A mob moving on a tile with a pro /obj/item/projectile/proc/dumbfire(var/dir) current = get_ranged_target_turf(src, dir, world.maxx) //world.maxx is the range. Not sure how to handle this better. fire() + + +/obj/item/projectile/proc/on_ricochet(atom/A) + return + +/obj/item/projectile/proc/check_ricochet() + if(prob(ricochet_chance)) + return TRUE + return FALSE + +/obj/item/projectile/proc/check_ricochet_flag(atom/A) + if(A.flags_2 & CHECK_RICOCHET_1) + return TRUE + return FALSE + +/obj/item/projectile/proc/setAngle(new_angle) //wrapper for overrides. + Angle = new_angle + return TRUE diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index b7854d90e13..b34364c4c93 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -79,7 +79,7 @@ name = "laser tag beam" icon_state = "omnilaser" hitsound = 'sound/weapons/tap.ogg' - damage = 0 + nodamage = 1 damage_type = STAMINA flag = "laser" var/suit_types = list(/obj/item/clothing/suit/redtag, /obj/item/clothing/suit/bluetag) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index c4d9fe2c39f..c55f367d8c3 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -37,6 +37,18 @@ stamina = 60 icon_state = "bullet-r" +/obj/item/projectile/bullet/weakbullet2/invisible //finger gun bullets + name = "invisible bullet" + damage = 0 + icon_state = null + hitsound_wall = null + +/obj/item/projectile/bullet/weakbullet2/invisible/fake + weaken = 0 + stamina = 0 + nodamage = 1 + log_override = TRUE + /obj/item/projectile/bullet/weakbullet3 damage = 20 diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 88d7318e962..c838c5469c7 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -64,7 +64,7 @@ options[/obj/item/stock_parts/manipulator/pico] = "Upgrade to a pico manipulator to fix it." options[/obj/item/stock_parts/matter_bin/super] = "Give it a super matter bin to fix it." options[/obj/item/stock_parts/cell/super] = "Replace the reagent synthesizer with a super capacity cell to fix it." - options[/obj/item/mass_spectrometer/adv] = "Replace the reagent scanner with an advanced mass spectrometer to fix it" + options[/obj/item/reagent_scanner/adv] = "Replace the reagent scanner with an advanced reagent scanner to fix it" options[/obj/item/stock_parts/micro_laser/high] = "Repair the reagent synthesizer with an high-power micro-laser to fix it" options[/obj/item/reagent_scanner/adv] = "Replace the reagent scanner with an advanced reagent scanner to fix it" options[/obj/item/stack/nanopaste] = "Apply some nanopaste to the broken nozzles to fix it." diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm index e82dbda249d..db70bf255e6 100644 --- a/code/modules/reagents/reagent_containers/glass_containers.dm +++ b/code/modules/reagents/reagent_containers/glass_containers.dm @@ -245,9 +245,9 @@ if(assembly) assembly.on_found(finder) -/obj/item/reagent_containers/glass/beaker/hear_talk(mob/living/M, msg) +/obj/item/reagent_containers/glass/beaker/hear_talk(mob/living/M, list/message_pieces) if(assembly) - assembly.hear_talk(M, msg) + assembly.hear_talk(M, message_pieces) /obj/item/reagent_containers/glass/beaker/hear_message(mob/living/M, msg) if(assembly) diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index edbc32f36a1..4f4277980e0 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -181,9 +181,9 @@ if(rig) rig.Crossed(AM) -/obj/structure/reagent_dispensers/fueltank/hear_talk(mob/living/M, msg) +/obj/structure/reagent_dispensers/fueltank/hear_talk(mob/living/M, list/message_pieces) if(rig) - rig.hear_talk(M, msg) + rig.hear_talk(M, message_pieces) /obj/structure/reagent_dispensers/fueltank/hear_message(mob/living/M, msg) if(rig) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index f6474c4a16b..d0007ab7266 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -538,6 +538,7 @@ // note AM since can contain mobs or objs for(var/atom/movable/AM in D) AM.loc = src + SEND_SIGNAL(AM, COMSIG_MOVABLE_DISPOSING, src, D) if(istype(AM, /mob/living/carbon/human)) var/mob/living/carbon/human/H = AM if(FAT in H.mutations) // is a human and fat? diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 0253bb32055..315a2e70aa0 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -657,6 +657,7 @@ name = "Exosuit Medical Equipment (Rescue Jaw)" id = "mech_medical_jaw" build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/medical/rescue_jaw req_tech = list("materials" = 4, "engineering" = 6, "magnets" = 6) //now same as jaws of life materials = list(MAT_METAL=5000,MAT_SILVER=2000,MAT_TITANIUM=1500) construction_time = 200 @@ -1165,6 +1166,15 @@ construction_time = 200 category = list("Misc") +/datum/design/ipc_microphone + name = "IPC Microphone" + id = "ipc_microphone" + build_type = MECHFAB + build_path = /obj/item/organ/internal/ears/microphone + materials = list(MAT_METAL = 1000, MAT_GLASS = 2500) + construction_time = 200 + category = list("Misc") + /datum/design/synthetic_flash name = "Synthetic Flash" desc = "A synthetic flash used mostly in borg construction." diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index b5840d82265..ce98cdd4c1e 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -1,15 +1,6 @@ ///////////////////////////////////////// ////////////Medical Tools//////////////// ///////////////////////////////////////// -/datum/design/adv_mass_spectrometer - name = "Advanced Mass-Spectrometer" - desc = "A device for analyzing chemicals in the blood and their quantities." - id = "adv_mass_spectrometer" - req_tech = list("biotech" = 3, "magnets" = 4, "plasmatech" = 3) - build_type = PROTOLATHE - materials = list(MAT_METAL = 500, MAT_GLASS = 200) - build_path = "/obj/item/mass_spectrometer/adv" - category = list("Medical") /datum/design/adv_reagent_scanner name = "Advanced Reagent Scanner" @@ -93,16 +84,6 @@ build_path = /obj/item/mmi category = list("Misc","Medical") -/datum/design/mass_spectrometer - name = "Mass-Spectrometer" - desc = "A device for analyzing chemicals in the blood." - id = "mass_spectrometer" - req_tech = list("magnets" = 2, "plasmatech" = 2) - build_type = PROTOLATHE - materials = list(MAT_METAL = 300, MAT_GLASS = 100) - build_path = /obj/item/mass_spectrometer - category = list("Medical") - /datum/design/robotic_brain name = "Robotic Brain" desc = "The latest in non-sentient Artificial Intelligences." diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 9e72a12c98e..2ae4e3ac828 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -619,7 +619,7 @@ /obj/item/relic/New() icon_state = pick("shock_kit","armor-igniter-analyzer","infra-igniter0","infra-igniter1","radio-multitool","prox-radio1","radio-radio","timer-multitool0","radio-igniter-tank") - realName = "[pick("broken","twisted","spun","improved","silly","regular","badly made")] [pick("device","object","toy","illegal tech","weapon")]" + realName = "[pick("broken","twisted","spun","improved","silly","regular","badly made")] [pick("device","object","toy","suspicious tech","gear")]" floof = pick(/mob/living/simple_animal/pet/corgi, /mob/living/simple_animal/pet/cat, /mob/living/simple_animal/pet/fox, /mob/living/simple_animal/mouse, /mob/living/simple_animal/pet/pug, /mob/living/simple_animal/lizard, /mob/living/simple_animal/diona, /mob/living/simple_animal/butterfly, /mob/living/carbon/human/monkey) diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 0c2688cc3f1..e8c91920cb8 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -279,6 +279,7 @@ var/ert_request_answered = FALSE paranormal_slots -= 1 M.equipOutfit(paranormal_outfit) M.job = "ERT Paranormal" + M.mind.isholy = TRUE if("Commander") command_slots = 0 diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm index be0a6808c39..8948fd80dbb 100644 --- a/code/modules/response_team/ert_outfits.dm +++ b/code/modules/response_team/ert_outfits.dm @@ -146,7 +146,7 @@ /obj/item/organ/internal/cyberimp/chest/nutriment, /obj/item/organ/internal/cyberimp/eyes/hud/security ) - + backpack_contents = list( /obj/item/clothing/head/helmet/space/hardsuit/ert/security = 1, /obj/item/clothing/mask/gas/sechailer = 1, @@ -379,8 +379,7 @@ pda = /obj/item/pda/centcom backpack_contents = list( /obj/item/clothing/mask/gas/sechailer/swat = 1, - /obj/item/storage/box/zipties = 1, - /obj/item/flashlight/seclite = 1 + /obj/item/storage/box/zipties = 1 ) /datum/outfit/job/centcom/response_team/paranormal/amber @@ -395,7 +394,7 @@ suit = /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor head = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor suit_store = /obj/item/gun/energy/gun - r_pocket = /obj/item/nullrod + r_pocket = /obj/item/nullrod/ert glasses = /obj/item/clothing/glasses/sunglasses cybernetic_implants = list( @@ -411,7 +410,7 @@ l_pocket = /obj/item/grenade/clusterbuster/holy shoes = /obj/item/clothing/shoes/magboots/advance glasses = /obj/item/clothing/glasses/night - r_pocket = /obj/item/nullrod + r_pocket = /obj/item/nullrod/ert cybernetic_implants = list( /obj/item/organ/internal/cyberimp/chest/nutriment/plus, diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index bb9c2d41fa1..715adb668ab 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -522,8 +522,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, v to_chat(user, "You need an open hand to do that.") -/obj/spacepod/hear_talk/hear_talk(mob/M, var/msg) - cargo_hold.hear_talk(M, msg) +/obj/spacepod/hear_talk/hear_talk(mob/M, list/message_pieces) + cargo_hold.hear_talk(M, message_pieces) ..() /obj/spacepod/hear_message(mob/M, var/msg) diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 2616c6c6c7e..d9a572c1a0e 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -238,6 +238,14 @@ var/obj/item/flash/armimplant/F = locate(/obj/item/flash/armimplant) in items_list F.I = src +/obj/item/organ/internal/cyberimp/arm/combat/centcom + name = "NT specops cybernetics implant" + desc = "An extremely powerful cybernetic implant that contains combat and utility modules used by NT special forces." + contents = newlist(/obj/item/gun/energy/pulse/pistol/m1911, /obj/item/door_remote/omni, /obj/item/melee/energy/blade/hardlight, /obj/item/reagent_containers/hypospray/combat/nanites, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/implanter/mindshield, /obj/item/flash/armimplant) + icon = 'icons/obj/guns/energy.dmi' + icon_state = "m1911" + emp_proof = 1 + /obj/item/organ/internal/cyberimp/arm/surgery name = "surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm" diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index d04e5a95279..4f23bf18243 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -47,6 +47,9 @@ /obj/item/organ/internal/ears/proc/MinimumDeafTicks(value) deaf = max(deaf, value) +/obj/item/organ/internal/ears/surgeryize() + RestoreEars() + // Mob procs /mob/living/carbon/RestoreEars() var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) @@ -61,4 +64,5 @@ /mob/living/carbon/MinimumDeafTicks(value) var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) if(ears) - ears.MinimumDeafTicks(value) \ No newline at end of file + ears.MinimumDeafTicks(value) + diff --git a/code/modules/surgery/organs/subtypes/machine.dm b/code/modules/surgery/organs/subtypes/machine.dm index b66d13612a3..837e9b5ffb7 100644 --- a/code/modules/surgery/organs/subtypes/machine.dm +++ b/code/modules/surgery/organs/subtypes/machine.dm @@ -133,4 +133,16 @@ stored_mmi.icon_state = "posibrain-occupied" if(!stored_mmi.brainmob.dna) stored_mmi.brainmob.dna = dna.Clone() + . = ..() + +/obj/item/organ/internal/ears/microphone + name = "microphone" + icon = 'icons/obj/device.dmi' + icon_state = "taperecorder_idle" + status = ORGAN_ROBOT + dead_icon = "taperecorder_empty" + +/obj/item/organ/internal/ears/microphone/remove(mob/living/user, special = FALSE) + if(!special) + to_chat(owner, "BZZZZZZZZZZZZZZT! Microphone error!") . = ..() \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/skrell.dm b/code/modules/surgery/organs/subtypes/skrell.dm index fd8a02f18d3..20eae88139c 100644 --- a/code/modules/surgery/organs/subtypes/skrell.dm +++ b/code/modules/surgery/organs/subtypes/skrell.dm @@ -52,8 +52,8 @@ pocket.emp_act(severity) ..() -/obj/item/organ/internal/headpocket/hear_talk(mob/living/M as mob, msg) - pocket.hear_talk(M, msg) +/obj/item/organ/internal/headpocket/hear_talk(mob/living/M as mob, list/message_pieces) + pocket.hear_talk(M, message_pieces) ..() /obj/item/organ/internal/headpocket/hear_message(mob/living/M as mob, msg) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index eedcb52be00..6e630fe7438 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -136,8 +136,8 @@ var/static/regex/multispin_words = regex("like a record baby") var/power_multiplier = base_multiplier if(owner.mind) - //Chaplains are very good at speaking with the voice of god - if(owner.mind.assigned_role == "Chaplain") + //Holy characters are very good at speaking with the voice of god + if(owner.mind.isholy) power_multiplier *= 2 //Command staff has authority if(owner.mind.assigned_role in command_positions) diff --git a/html/changelog.html b/html/changelog.html index 8ace5ded9d0..99337b40878 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,282 @@ -->
+

06 December 2018

+

Shadow-Quill updated:

+
    +
  • Fixed protocol spelling in the Photon Projector description.
  • +
+

TDSSS updated:

+
    +
  • Reverted holopad sorting to make holopads work again.
  • +
+ +

01 December 2018

+

Kyep updated:

+
    +
  • Fixed a couple of bugs with the special event pets triggered by admin bless command.
  • +
+

TDSSS updated:

+
    +
  • Ancient Station asteroids now contain minerals and can be mined.
  • +
+

datlo updated:

+
    +
  • Added 3 carrot seed packets to perma.
  • +
+ +

30 November 2018

+

Azule Utama updated:

+
    +
  • Fixed an ORM exploit which would let you smelt invalid stacks of alloys.
  • +
+

TDSSS updated:

+
    +
  • Removed ballgag and assless chaps
  • +
+ +

29 November 2018

+

Kyep updated:

+
    +
  • Updated chaplains. They now spawn with their nullrod in their hand, and their soulstone in their locker. They now have the ability to bless other players. The more players they bless, the more likely admins are to answer their prayers. There are no longer any atheist chaplains. The chaplain items that reference atheism have been tweaked accordingly, e.g the atheist fedora is now the binary fedora. A few other items have also been tweaked. Paranormal ERT members now count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful version of the nullrod, so they have a reason to use a weapon other than their gun.
  • +
+

TDSSS updated:

+
    +
  • No more making infinite meat and crashing the server with gibbers
  • +
+ +

28 November 2018

+

Kyep and FoS updated:

+
    +
  • Updated hellhound with new sprites by FoS, slightly better AI, and more fixes/tweaks.
  • +
+

MrKicker updated:

+
    +
  • Sort callable holopads by name
  • +
+

tigercat2000 updated:

+
    +
  • You can now speak in multiple languages in the same message! This works for all forms of speech, including radios. Minus megaphones because fuck em.
  • +
  • Some mild formatting errors and inconsistencies that have historically been present within mob speech.
  • +
  • Holopads behaving a bit weirdly with how they interact with the typical say system
  • +
+ +

27 November 2018

+

Azule Utama updated:

+
    +
  • Power beacon made purchasable again in Nuke Ops uplinks.
  • +
+

Dovydas12345 updated:

+
    +
  • Fixes being able to attach IV drips when incapacitated
  • +
+

Farie82 updated:

+
    +
  • You can now actually make the rescue jaws
  • +
+ +

26 November 2018

+

Citinited updated:

+
    +
  • Adds the rubbish bin in front of the kitchen again
  • +
+

TDSSS updated:

+
    +
  • Medbay secondary storage is now accessible to everyone with medbay access, hardsuits were put behind a windoor with CMO access to keep them at the same level of accessability.
  • +
  • Added and removed some items from medbay secondary storage.
  • +
  • Medical storage and secondary storage were renamed to be more accurate.
  • +
+

datlo updated:

+
    +
  • Updated description of finger gun to point out you can holster the gun manually by using it in hand.
  • +
  • Fixed a bug where you couldn't learn finger gun if you already knew fake finger gun.
  • +
  • Power beacon cost reduced to 10 TC, and is now hijack-exclusive.
  • +
  • Guillotines can now be deconstructed with a welder.
  • +
+ +

25 November 2018

+

Azule Utama updated:

+
    +
  • Job-specific gear can no longer be discounted.
  • +
  • Discounted items now get an alternate log entry stating the item's new price.
  • +
+

KasparoVy updated:

+
    +
  • Fixes Unathi Snout 2 not using the correct sprite.
  • +
  • Fixes Unathi Points Head not using the correct sprite.
  • +
  • Fixes Unathi Sharp Tiger Head and Face not using the correct sprite.
  • +
  • Fixes Unathi Tiger Head and Face not using the correct sprite.
  • +
  • Removes Unathi Sharp Points Head and enables Unathi Points Head marking for use on all Unathi head types.
  • +
+

MarsM0nd updated:

+
    +
  • Coins will now always show a side on being spawned.
  • +
+

Reagent Scanner Changes updated:

+
    +
  • Removed Mass Spectrometer and Advanced Mass Spectrometer
  • +
  • Reagent Scanner and Advanced Reagent Scanners can now identify blood types
  • +
+

datlo updated:

+
    +
  • Added the Advanced Mimery Series to Syndicate Mime uplink.
  • +
  • Added a fake Finger Gun manual to the arcade prize machine.
  • +
  • Changed the look of the teleporter hallway from maintenance to dirty hallway.
  • +
+ +

24 November 2018

+

Azule Utama updated:

+
    +
  • Added uplink discounts. Traitor and Nuclear Operative uplinks now have a discounted gear section! 3 random items will be chosen to be 50% off (rounded down), 25% if they usually cost 20 or more TC. You can only buy a discounted item once per uplink. Ported from TG.
  • +
+

Eschess updated:

+
    +
  • hardsuit helmets now unlink from the hardsuits upon being detached
  • +
  • syndicate hardsuit helmet combat mode can no longer be toggled on hand
  • +
  • fixes non-syndicate hardsuit helmet attaching/detaching runtimes
  • +
+

TDSSS updated:

+
    +
  • Space ruin/gateway hardsuits now should all come with helmets
  • +
  • Telecom setup in wizard gateway can now be completed with the present stock parts.
  • +
+

Ty-Omaha updated:

+
    +
  • Added reflective blobs, these blobs have a high chance to deflect energy projectiles while being vulnerable to ballistics and brute damage. Reflective blobs can be obtained by upgrading a shield blob.
  • +
+

tigercat2000 updated:

+
    +
  • Fancier Transpara-corner Nano take 2.
  • +
  • Nano's build-watching works on 512 again.
  • +
  • Nano scrolling issues with the power monitor (they existed before I touched this goddamnit I swear!!!)
  • +
  • Rewrote Nano's buildscripts and upgraded all the dependencies (again)
  • +
+ +

23 November 2018

+

Azule Utama updated:

+
    +
  • Additional check added to damage falloff code, will only delete bullets that reach 0 damage if they actually have a falloff value.
  • +
+

Kyep updated:

+
    +
  • Dead mice no longer squeak.
  • +
  • Ghosts walking over living mice no longer makes them squeak.
  • +
+

TDSSS updated:

+
    +
  • no more runtime spam each time a simple mob is attacked
  • +
+

datlo updated:

+
    +
  • Replaced "illegal" and "weapon" in strange objects name
  • +
+ +

22 November 2018

+

AlAtEX updated:

+
    +
  • re-adds sprites for boxes that disappeared
  • +
+

AlAtEx updated:

+
    +
  • Added a new medkit for IPCs
  • +
  • added a purple medkit
  • +
  • Added a repair kit box to start with for IPC's
  • +
  • Re-added the crowbar and extended tank to miner's boxes
  • +
  • added three new box images
  • +
+

Azule Utama updated:

+
    +
  • Made laser tag guns work again.
  • +
  • Syndicate Cigarettes added to maintenance loot.
  • +
+

Eschess updated:

+
    +
  • Adds ui button to toggle hardsuit helmet
  • +
  • syndicate hardsuit combat mode is activated only by the helmet button
  • +
+

Kyep updated:

+
    +
  • Added hellhound, a dangerous new monster.
  • +
+

datlo updated:

+
    +
  • Added the CQC manual to nuke ops and traitor uplinks, letting them remember some of the basics of CQC.
  • +
+ +

21 November 2018

+

MrKicker updated:

+
    +
  • Added generated sound files to sound/vox_fem , then added references to them in vox_sounds.dm
  • +
+ +

20 November 2018

+

AffectedArc07 updated:

+
    +
  • NTTC now has multiple job tag styles
  • +
  • NTTC now has option to make job tags colored
  • +
  • NTTC now has option to make nametags colored
  • +
  • NTTC now has options to make command members louder (bold)
  • +
  • The NTTC window title is no longer NTSL.
  • +
+

Azule Utama updated:

+
    +
  • Fixed chameleon suit having two invalid options.
  • +
+

TDSSS updated:

+
    +
  • Silencers now have a tech origin, give research levels when deconstructed
  • +
  • Moved gun attachments to their own folder, code-wise.
  • +
+

name here updated:

+
    +
  • Fixed a runtime in a syndieteam radio.
  • +
+

tigercat2000 updated:

+
    +
  • Nano scrolling is 95% less buggy
  • +
  • NanoUI's Fancy Mode now less broken as hell remove: 512 support for Nano dev tools
  • +
+ +

19 November 2018

+

Birdtalon updated:

+
    +
  • Fixes a runtime in safe.dm
  • +
+

Citinited updated:

+
    +
  • Alt-clicking a jumpsuit removes accessories from it
  • +
  • Removing an accessory now shows a small message
  • +
+

KasparoVy updated:

+
    +
  • Brings the logging of plasma statue ignition up to the same spec at as welder tank explosions.
  • +
  • You can no longer ignite plasma statues with disablers.
  • +
+

Kyep updated:

+
    +
  • Tweaked many of the special admin outfits. This means centcom officers are less likely to be seen wielding illegal syndicate gear, and subtle flaws with many other outfits (such as pirates lacking radio, singulo knights lacking a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) have been addressed.
  • +
  • Added several new admin options for fax responses, blessings, and smiting.
  • +
+

Quantum-M updated:

+
    +
  • Sleeping carp uplink description now points out that it is unable to be learned by vampires or changelings.
  • +
  • Holoparasite kit uplink description now points out that it doesn't work on vampires or changelings.
  • +
  • Attempting to learn sleeping carp as a changeling or vampire gives you a red warning message.
  • +
  • You can now refund the sleeping carp scroll to the uplink.
  • +
+

TDSSS updated:

+
    +
  • A warning if slings are very close to ascension, so the crew can potentially still stop them
  • +
+

craftxbox updated:

+
    +
  • add observer/incapacitated check for all sec/medhud actions
  • +
+

datlo updated:

+
    +
  • Added antag alert sounds that play at roundstart for most major antagonists, ported from TG.
  • +
+

17 November 2018

uc_guy updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index b540fc52b55..10fddd7d8e9 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -8094,3 +8094,201 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2018-11-17: uc_guy: - bugfix: Syndicate borgs are no longer pseudonymous on syndie radio. +2018-11-19: + Birdtalon: + - bugfix: Fixes a runtime in safe.dm + Citinited: + - tweak: Alt-clicking a jumpsuit removes accessories from it + - tweak: Removing an accessory now shows a small message + KasparoVy: + - tweak: Brings the logging of plasma statue ignition up to the same spec at as + welder tank explosions. + - bugfix: You can no longer ignite plasma statues with disablers. + Kyep: + - tweak: Tweaked many of the special admin outfits. This means centcom officers + are less likely to be seen wielding illegal syndicate gear, and subtle flaws + with many other outfits (such as pirates lacking radio, singulo knights lacking + a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) + have been addressed. + - rscadd: Added several new admin options for fax responses, blessings, and smiting. + Quantum-M: + - tweak: Sleeping carp uplink description now points out that it is unable to be + learned by vampires or changelings. + - tweak: Holoparasite kit uplink description now points out that it doesn't work + on vampires or changelings. + - tweak: Attempting to learn sleeping carp as a changeling or vampire gives you + a red warning message. + - tweak: You can now refund the sleeping carp scroll to the uplink. + TDSSS: + - rscadd: A warning if slings are very close to ascension, so the crew can potentially + still stop them + craftxbox: + - bugfix: add observer/incapacitated check for all sec/medhud actions + datlo: + - rscadd: Added antag alert sounds that play at roundstart for most major antagonists, + ported from TG. +2018-11-20: + AffectedArc07: + - rscadd: NTTC now has multiple job tag styles + - rscadd: NTTC now has option to make job tags colored + - rscadd: NTTC now has option to make nametags colored + - rscadd: NTTC now has options to make command members louder (bold) + - spellcheck: The NTTC window title is no longer NTSL. + Azule Utama: + - bugfix: Fixed chameleon suit having two invalid options. + TDSSS: + - tweak: Silencers now have a tech origin, give research levels when deconstructed + - tweak: Moved gun attachments to their own folder, code-wise. + name here: + - bugfix: Fixed a runtime in a syndieteam radio. + tigercat2000: + - bugfix: Nano scrolling is 95% less buggy + - bugfix: 'NanoUI''s Fancy Mode now less broken as hell remove: 512 support for + Nano dev tools' +2018-11-21: + MrKicker: + - soundadd: Added generated sound files to sound/vox_fem , then added references + to them in vox_sounds.dm +2018-11-22: + AlAtEX: + - bugfix: re-adds sprites for boxes that disappeared + AlAtEx: + - rscadd: Added a new medkit for IPCs + - imageadd: added a purple medkit + - rscadd: Added a repair kit box to start with for IPC's + - rscadd: Re-added the crowbar and extended tank to miner's boxes + - imageadd: added three new box images + Azule Utama: + - bugfix: Made laser tag guns work again. + - rscadd: Syndicate Cigarettes added to maintenance loot. + Eschess: + - rscadd: Adds ui button to toggle hardsuit helmet + - tweak: syndicate hardsuit combat mode is activated only by the helmet button + Kyep: + - rscadd: Added hellhound, a dangerous new monster. + datlo: + - rscadd: Added the CQC manual to nuke ops and traitor uplinks, letting them remember + some of the basics of CQC. +2018-11-23: + Azule Utama: + - bugfix: Additional check added to damage falloff code, will only delete bullets + that reach 0 damage if they actually have a falloff value. + Kyep: + - bugfix: Dead mice no longer squeak. + - bugfix: Ghosts walking over living mice no longer makes them squeak. + TDSSS: + - bugfix: no more runtime spam each time a simple mob is attacked + datlo: + - tweak: Replaced "illegal" and "weapon" in strange objects name +2018-11-24: + Azule Utama: + - rscadd: Added uplink discounts. Traitor and Nuclear Operative uplinks now have + a discounted gear section! 3 random items will be chosen to be 50% off (rounded + down), 25% if they usually cost 20 or more TC. You can only buy a discounted + item once per uplink. Ported from TG. + Eschess: + - bugfix: hardsuit helmets now unlink from the hardsuits upon being detached + - bugfix: syndicate hardsuit helmet combat mode can no longer be toggled on hand + - bugfix: fixes non-syndicate hardsuit helmet attaching/detaching runtimes + TDSSS: + - tweak: Space ruin/gateway hardsuits now should all come with helmets + - tweak: Telecom setup in wizard gateway can now be completed with the present stock + parts. + Ty-Omaha: + - rscadd: Added reflective blobs, these blobs have a high chance to deflect energy + projectiles while being vulnerable to ballistics and brute damage. Reflective + blobs can be obtained by upgrading a shield blob. + tigercat2000: + - rscadd: Fancier Transpara-corner Nano take 2. + - rscadd: Nano's build-watching works on 512 again. + - bugfix: Nano scrolling issues with the power monitor (they existed before I touched + this goddamnit I swear!!!) + - tweak: Rewrote Nano's buildscripts and upgraded all the dependencies (again) +2018-11-25: + Azule Utama: + - tweak: Job-specific gear can no longer be discounted. + - tweak: Discounted items now get an alternate log entry stating the item's new + price. + KasparoVy: + - bugfix: Fixes Unathi Snout 2 not using the correct sprite. + - bugfix: Fixes Unathi Points Head not using the correct sprite. + - bugfix: Fixes Unathi Sharp Tiger Head and Face not using the correct sprite. + - bugfix: Fixes Unathi Tiger Head and Face not using the correct sprite. + - tweak: Removes Unathi Sharp Points Head and enables Unathi Points Head marking + for use on all Unathi head types. + MarsM0nd: + - bugfix: Coins will now always show a side on being spawned. + Reagent Scanner Changes: + - rscdel: Removed Mass Spectrometer and Advanced Mass Spectrometer + - tweak: Reagent Scanner and Advanced Reagent Scanners can now identify blood types + datlo: + - rscadd: Added the Advanced Mimery Series to Syndicate Mime uplink. + - rscadd: Added a fake Finger Gun manual to the arcade prize machine. + - tweak: Changed the look of the teleporter hallway from maintenance to dirty hallway. +2018-11-26: + Citinited: + - rscadd: Adds the rubbish bin in front of the kitchen again + TDSSS: + - tweak: Medbay secondary storage is now accessible to everyone with medbay access, + hardsuits were put behind a windoor with CMO access to keep them at the same + level of accessability. + - tweak: Added and removed some items from medbay secondary storage. + - tweak: Medical storage and secondary storage were renamed to be more accurate. + datlo: + - tweak: Updated description of finger gun to point out you can holster the gun + manually by using it in hand. + - bugfix: Fixed a bug where you couldn't learn finger gun if you already knew fake + finger gun. + - tweak: Power beacon cost reduced to 10 TC, and is now hijack-exclusive. + - rscadd: Guillotines can now be deconstructed with a welder. +2018-11-27: + Azule Utama: + - bugfix: Power beacon made purchasable again in Nuke Ops uplinks. + Dovydas12345: + - bugfix: Fixes being able to attach IV drips when incapacitated + Farie82: + - bugfix: You can now actually make the rescue jaws +2018-11-28: + Kyep and FoS: + - rscadd: Updated hellhound with new sprites by FoS, slightly better AI, and more + fixes/tweaks. + MrKicker: + - rscadd: Sort callable holopads by name + tigercat2000: + - rscadd: You can now speak in multiple languages in the same message! This works + for all forms of speech, including radios. Minus megaphones because fuck em. + - bugfix: Some mild formatting errors and inconsistencies that have historically + been present within mob speech. + - bugfix: Holopads behaving a bit weirdly with how they interact with the typical + say system +2018-11-29: + Kyep: + - rscadd: Updated chaplains. They now spawn with their nullrod in their hand, and + their soulstone in their locker. They now have the ability to bless other players. + The more players they bless, the more likely admins are to answer their prayers. + There are no longer any atheist chaplains. The chaplain items that reference + atheism have been tweaked accordingly, e.g the atheist fedora is now the binary + fedora. A few other items have also been tweaked. Paranormal ERT members now + count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful + version of the nullrod, so they have a reason to use a weapon other than their + gun. + TDSSS: + - bugfix: No more making infinite meat and crashing the server with gibbers +2018-11-30: + Azule Utama: + - bugfix: Fixed an ORM exploit which would let you smelt invalid stacks of alloys. + TDSSS: + - rscdel: Removed ballgag and assless chaps +2018-12-01: + Kyep: + - bugfix: Fixed a couple of bugs with the special event pets triggered by admin + bless command. + TDSSS: + - rscadd: Ancient Station asteroids now contain minerals and can be mined. + datlo: + - rscadd: Added 3 carrot seed packets to perma. +2018-12-06: + Shadow-Quill: + - spellcheck: Fixed protocol spelling in the Photon Projector description. + TDSSS: + - rscdel: Reverted holopad sorting to make holopads work again. diff --git a/html/nttc/dist/index.html b/html/nttc/dist/index.html index 80e7a40ac81..a8a7a17f1e3 100644 --- a/html/nttc/dist/index.html +++ b/html/nttc/dist/index.html @@ -3,7 +3,7 @@ - NTSL + NTTC @@ -12,7 +12,7 @@