diff --git a/.travis.yml b/.travis.yml index 27dae76378e..af2cfc45cc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ git: env: global: - BYOND_MAJOR="510" - - BYOND_MINOR="1336" + - BYOND_MINOR="1346" matrix: - DM_MAPFILE="cyberiad" - DM_MAPFILE="metastation" diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 7e221cf1131..6a8fb071c95 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -796,7 +796,7 @@ "app" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f6"; dir = 2},/area/shuttle/pod_1) "apq" = (/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1379; master_tag = "security_airlock"; name = "exterior access button"; pixel_x = -20; pixel_y = -20; req_access_txt = "13"},/turf/simulated/floor/plating/airless,/area/space) "apr" = (/obj/effect/decal/warning_stripes/east,/turf/simulated/floor/engine/vacuum,/area/escapepodbay) -"aps" = (/turf/space,/area/shuttle/syndicate_elite/station) +"aps" = (/turf/space,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite) "apt" = (/obj/machinery/door/airlock/shuttle{id_tag = "s_docking_airlock"; name = "Labor Shuttle Airlock"; req_access_txt = "2"},/obj/docking_port/mobile{dir = 8; dwidth = 2; height = 5; id = "laborcamp"; name = "labor camp shuttle"; rebuildable = 1; width = 9},/obj/docking_port/stationary{dir = 8; dwidth = 2; height = 5; id = "laborcamp_home"; name = "fore bay 1"; width = 9},/turf/simulated/shuttle/floor,/area/shuttle/siberia) "apu" = (/obj/machinery/light,/turf/simulated/floor/plating,/area/security/prisonershuttle) "apv" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/prisonershuttle) @@ -3461,7 +3461,7 @@ "boC" = (/obj/machinery/conveyor{dir = 1; id = "packageSort1"},/turf/simulated/floor/plating,/area/quartermaster/office) "boD" = (/obj/structure/stool,/turf/simulated/floor/plasteel{dir = 9; icon_state = "warning"},/area/quartermaster/office) "boE" = (/obj/machinery/atmospherics/unary/vent_pump/on,/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/quartermaster/office) -"boF" = (/obj/machinery/conveyor_switch/oneway{id = "packageSort2"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/quartermaster/office) +"boF" = (/obj/structure/disposalpipe/junction{dir = 8; icon_state = "pipe-j2"; tag = "icon-pipe-j1 (WEST)"},/turf/simulated/wall,/area/storage/tools) "boG" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/hallway/primary/central/west) "boH" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor/plasteel,/area/hallway/primary/central/west) "boI" = (/turf/simulated/floor/plasteel{icon_state = "bluecorner"},/area/hallway/primary/central/west) @@ -3790,7 +3790,7 @@ "buT" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/quartermaster/storage) "buU" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/wall,/area/quartermaster/storage) "buV" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/wall,/area/quartermaster/office) -"buW" = (/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{dir = 8; icon_state = "brown"},/area/quartermaster/office) +"buW" = (/obj/structure/disposalpipe/segment,/turf/simulated/wall,/area/quartermaster/office) "buX" = (/obj/structure/stool/bed/chair{dir = 4},/obj/effect/landmark/start{name = "Cargo Technician"},/turf/simulated/floor/plasteel,/area/quartermaster/office) "buY" = (/obj/structure/table/reinforced,/turf/simulated/floor/plasteel{icon_state = "arrival"; dir = 4},/area/quartermaster/office) "buZ" = (/obj/machinery/door/firedoor{dir = 8; name = "Firelock West"},/obj/machinery/door/window{base_state = "right"; dir = 8; icon_state = "right"; name = "Mailing Room"; req_access_txt = "50"},/turf/simulated/floor/plasteel{icon_state = "bot"},/area/quartermaster/office) @@ -5037,7 +5037,7 @@ "bSS" = (/obj/machinery/light/small{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/toxins/storage) "bST" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/yellow,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/toxins/storage) "bSU" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor/plasteel{dir = 5; icon_state = "whitehall"},/area/medical/research{name = "Research Division"}) -"bSV" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/wrapsortjunction{dir = 1},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) +"bSV" = (/obj/machinery/conveyor_switch/oneway{id = "packageSort2"},/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/quartermaster/office) "bSW" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plasteel{dir = 9; icon_state = "whitehall"},/area/medical/research{name = "Research Division"}) "bSX" = (/obj/machinery/door/airlock/glass_command{name = "Research Director"; req_access_txt = "30"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bSY" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) @@ -5094,7 +5094,7 @@ "bTX" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "cmooffice"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/medical/cmo) "bTY" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/medbay2) "bTZ" = (/obj/item/device/radio/intercom{frequency = 1459; name = "station intercom (General)"; pixel_x = 28},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (EAST)"; icon_state = "whiteblue"; dir = 4},/area/medical/medbay2) -"bUa" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/medical/cryo) +"bUa" = (/obj/effect/spawner/window/reinforced,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "staffroom"; name = "Staff Room Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/medical/cryo) "bUb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/wall,/area/medical/genetics) "bUc" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/wall,/area/medical/genetics) "bUd" = (/obj/machinery/computer/scan_consolenew,/obj/structure/window/reinforced,/turf/simulated/floor/plasteel{tag = "icon-whitepurple (WEST)"; icon_state = "whitepurple"; dir = 8},/area/medical/genetics) @@ -8771,6 +8771,31 @@ "dmI" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f9"; dir = 2},/area/shuttle/trade/sol) "dmJ" = (/obj/docking_port/stationary{dir = 8; dwidth = 2; height = 11; id = "trade_dock"; name = "port bay 4 at Cyberiad"; width = 5},/turf/space,/area/space) "dmK" = (/obj/machinery/door/airlock/external{id_tag = "trade_dock"},/turf/simulated/floor/plating,/area/hallway/secondary/entry) +"dmL" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion (NORTH)"; icon_state = "propulsion"; dir = 1},/turf/space,/area/shuttle/syndicate_elite) +"dmM" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_r (NORTH)"; icon_state = "propulsion_r"; dir = 1},/turf/space,/area/shuttle/syndicate_elite) +"dmN" = (/turf/space,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite) +"dmO" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_l (NORTH)"; icon_state = "propulsion_l"; dir = 1},/turf/space,/area/shuttle/syndicate_elite) +"dmP" = (/turf/simulated/shuttle/wall{dir = 4; icon_state = "wall3"},/area/shuttle/syndicate_elite) +"dmQ" = (/obj/structure/window/reinforced,/obj/structure/shuttle/engine/heater{tag = "icon-heater (NORTH)"; icon_state = "heater"; dir = 1},/turf/simulated/floor/plating/airless,/area/shuttle/syndicate_elite) +"dmR" = (/obj/effect/landmark{name = "Syndicate-Commando-Bomb"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmS" = (/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmT" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmU" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmV" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmW" = (/obj/machinery/door/airlock/external{id_tag = "s_docking_airlock"; name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "syndicate_elite"; name = "Side Hull Door"; opacity = 0},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmX" = (/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmY" = (/obj/machinery/door/airlock/external{id_tag = "s_docking_airlock"; name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "syndicate_elite"; name = "Side Hull Door"; opacity = 0; req_access_txt = "150"},/obj/docking_port/mobile{dir = 8; dwidth = 3; height = 5; id = "sst"; name = "SST shuttle"; roundstart_move = "sst_away"; width = 11},/obj/docking_port/stationary{dir = 8; dwidth = 3; height = 5; id = "sst_home"; name = "northwest of station"; width = 11},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dmZ" = (/obj/machinery/computer/pod{id_tags = list("syndicate_elite"); name = "Hull Door Control"; req_access_txt = "150"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dna" = (/obj/machinery/computer/shuttle/sst,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite) +"dnb" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite) +"dnc" = (/obj/machinery/door/airlock/external{id_tag = "s_docking_airlock"; name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{icon_state = "pdoor1"; id_tag = "syndicate_elite"; name = "Front Hull Door"; opacity = 1},/turf/simulated/shuttle/plating,/area/shuttle/syndicate_elite) +"dnd" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/syndicate_elite) +"dne" = (/turf/space,/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite) +"dnf" = (/turf/simulated/floor/plating/airless,/area/shuttle/syndicate_elite) +"dng" = (/obj/structure/disposalpipe/sortjunction{dir = 4; icon_state = "pipe-j2s"; sortType = 0},/turf/simulated/wall,/area/quartermaster/office) +"dnh" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/quartermaster/office) +"dni" = (/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 8; icon_state = "brown"},/area/quartermaster/office) +"dnj" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/sortjunction{dir = 1; icon_state = "pipe-j1s"; sortType = 13},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"}) (1,1,1) = {" bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8855,17 +8880,17 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGaabamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikamOamNamQamPamOamRamSamSamTamUamVamWamXamYamZanaanbancajuajuandaneajuajuajuajuajuanfanganhanianfajGajBajCanjajEajFajGankanlanmannahUahUahUahUannanoanpanmahUahAayjahAanrantansansanubikbikbikbikbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikaabbikbikbikaEEanwanzanyanBanAanDanCanAanGanGanHanIanJanKanLanManNanOanPanQanRanSanTanSanSanUanVanWanXanYanSanZaoaaobaocaodaoeaofaogaohanSaoiaojaokaolaomaonaooaopaoqaoraosaplaotaovaEHaouaoyaoxbikbikbikbikbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOanEaoAanFamOamRamSamSamSaoBaoHaoIaoJaoKaoLaoMaoNaoOaoPaoQaoRaoSaoTaoUaoVaoWaoXaoYaoWaoZapaaoTapbapcapdaoTaoTapdaoXapcapeaoTaoTapbapcaoVapfapgaphapiapjapkaplapmapnaovaozansansapobikaacapqaacbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikaabaabajkajPajmaabaabagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikajjbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamOaoCaoCaoDamObikbikbikapwapwapxapyapzapAapAapAapBapBapBapBapCapDapEapEapEapFapGapHapFapEapEapEapIapJapKapLapMapKapNapJapOapOapOapPapQapOapRapSapTapUapVapWapXapmapnapYapYamKapZapZapZamKaqaamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmaabaabbikaabaiIaabbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGaqbamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikaEEaoEaoCaoFamOamRamSamSamSaqgaqhaqiaqjaqkaqlaqmapBaqnaqoaqpaqqaqraqsaqtaquaqvaqwaqxaqyaqzaqAaqsaqBaqCaqDaqEaqFaqGaqHaqCapOaqIaqJaqKaqLapOaqMaqNaqOaqPaqQaqRapXapmaqSaqTaqUaqVaqWaqWaqXamKaqYamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikaabaloaabbikbikaqZbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikacGbikbikbikamOaoGaoCaoCaptanAapuanCanAapvanLarharianGanGarjapBarkarlarmarnaroarparqarrarsartaruarvarrarwarxaryarzarAarBarCarDarEarFarGarHarIarJarKapOarLarMarMarNarMarOapXapmaovaovaovaovarPaovarQarRarSamKakBarTakEbikbikaiIaabaabaabaabaiIaabaabaabaabaiIaabaabaabaabarUarVakEaabbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOaqcaqcaqcamOamRamSamSamSarXarYaoMarZasaanGasbapBascasdaseasfasgashasiasjaskaslasmasnasoaspashasqarFasrassastasrarEasuapOarGaswasxasyapOaszasAarMarNarMasBapXasCasDasEasFasEasGasHamKamKapnamKaloasIasJakCakCarTakCakCakCakCarTakCakCakCakCarTakCakCakCasKasLasIaloaabbikagQaabbikbikbikbikbikbikbikbikbikbikaabbikaabbikasMasMasNasNasNasNasNasNasMasMaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikaqeaqdaqdaqdaqfbikbikbikapwapwapwapwapwasSanGasTasUapBatRapBasVasWapEapEatSapEasXasYapEatSapEasZataatbatcatdateatfatgathapOatiatjatkatlatmatnatoatpatqarMatrapXatsattatuatvatwatxatyatzatAatBamKatCarTatDaabaabbikaabbikbikbikbikbikbikbikbikaabaabaabaabaabatEatFatDaabaabaabaabaabbikbikbikbikbikbikbikbikbikaabbikaabasMasMatGatHatIatJatKatLatMatIasMasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikaabatNamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwatOanGasTasUatPatUatTauyatVaqsatQauJauEavxauTavEavBatWaqsatXatYatZauaaubaubaucaudapOaueaufaugauhapOauiaujaukarNarMaulapXatsarPattattattaumaovaunauoaupamKbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikaabaabaabaabauqaabaabbikbikaabaabaabbikbikbikbikbikbikbikbikasMasMasMasMauratJausatJausautatJatJatJauuasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikbikaabbikaabbikbikauvbikbikaabbikaabbikbikacGbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikapwauwanGauxasUarkavJauzauAauBauCauDdlLauFauGauHauIdlMauKauLauMauNauNauOauNauNauPauQauRauSdlNapOauUapOauVauWauXauYauZavaapXatsavbavcavcavcavdaveavfavgavhamKbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabbikbikbikaabaabaabaviaabaabbikbikaabbikaabaabbikbikbikbikbikbikbikasMavjavkavlavmavnavoavpatJatJavqavratJavsasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGacGacGaabaabaabaabavtavuavtaabaabaabaabacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwavvanGavwasUdlPdlQavyavzavAashdlRdlSashavCavDashdlTdlUashavFavGavHavGavGavHavGavIapOatidlVapOavKapOavLavMavNavOavPavQavRavSavTavUavUavUavVavWavXavYavYavYbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikaabaabavZawaavZaabaabbikaabbikbikaabaabbikbikbikbikbikbikasMawbawcawdaweawfawgatJatJatJawhawiatJawjasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikaahbikbikbikbikaabbikaabbikbikaabbikavtawkawlbikbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmapwapwawnapwasUasUasUawoawpawqawrawrawsawrawsawrawrawtasZasZasvawvawwawuawvawwawuawyawzawzawzawzawzapOawAawBawCawCawDawCawEawFavUawGawHawIavVawJawKawLawMavWbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikaabbikavZawNavZbikaabbikaabbikbikbikaabaabbikbikbikbikbikasMawOawPavlawQawRawSawTatJawUawVawWawXasMawYaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikaabbikaabbikbikaabavtavtawZaxaavtbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxbaxcaxdaxeaxfaxgaxhaxiaxhaxjaxhaxhaxkaxlaxlaxlaxlaxlaxmaxnaxoaxlaxlaxlaxlaxpaxlaxlaxlaxlaxqaxraxsaxtaxuaxvaxwaxxapWaxyaxzaxAaxBaxCaxDaxEaxFavUaxGaxHaxIavVaxKaxLaxJaAZavWbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikaabavZavZaxMavZavZaabbikaabbikbikbikbikaabaabbikbikbikbikasMaxNaxOavlasMavlavlaxPaxQasMasMasMasMasMasMaabaabbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsbikbikbikbikbikbikaabaabbikaabbikbikaabaxRaxSaxTaxUaxRaxVaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxWaxXaxYaxZayaaybaycaydayeayfaxqaxqaygaxqaxqaxqaxqaxqayhaxqaxqaxqaxqaxqaxqayiaxqaxqaxqaxqaSWaxqaykaxqaylaxqaymaynapWayoaypayqayraysaytaxEayuavUayvaywayxayyayzayAayBawMavWbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikaabayCayDayEayFayCaabbikaabbikbikaabbikbikaabaabbikbikayGasMavlasMavlayHayIayHayJayHayHayHayKayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsdmMdmLdmOdmNbikbikbikbikbikbikajjbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamOaoCaoCaoDamObikbikbikapwapwapxapyapzapAapAapAapBapBapBapBapCapDapEapEapEapFapGapHapFapEapEapEapIapJapKapLapMapKapNapJapOapOapOapPapQapOapRapSapTapUapVapWapXapmapnapYapYamKapZapZapZamKaqaamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmaabaabbikaabaiIaabbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmQdmQdmQdmPbikbikbikbikbikbikacGaqbamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikaEEaoEaoCaoFamOamRamSamSamSaqgaqhaqiaqjaqkaqlaqmapBaqnaqoaqpaqqaqraqsaqtaquaqvaqwaqxaqyaqzaqAaqsaqBaqCaqDaqEaqFaqGaqHaqCapOaqIaqJaqKaqLapOaqMaqNaqOaqPaqQaqRapXapmaqSaqTaqUaqVaqWaqWaqXamKaqYamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikaabaloaabbikbikaqZbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmRdmRdmRdmPbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikacGbikbikbikamOaoGaoCaoCaptanAapuanCanAapvanLarharianGanGarjapBarkarlarmarnaroarparqarrarsartaruarvarrarwarxaryarzarAarBarCarDarEarFarGarHarIarJarKapOarLarMarMarNarMarOapXapmaovaovaovaovarPaovarQarRarSamKakBarTakEbikbikaiIaabaabaabaabaiIaabaabaabaabaiIaabaabaabaabarUarVakEaabbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmTdmSdmUdmPbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOaqcaqcaqcamOamRamSamSamSarXarYaoMarZasaanGasbapBascasdaseasfasgashasiasjaskaslasmasnasoaspashasqarFasrassastasrarEasuapOarGaswasxasyapOaszasAarMarNarMasBapXasCasDasEasFasEasGasHamKamKapnamKaloasIasJakCakCarTakCakCakCakCarTakCakCakCakCarTakCakCakCasKasLasIaloaabbikagQaabbikbikbikbikbikbikbikbikbikbikaabbikaabbikasMasMasNasNasNasNasNasNasMasMaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmVdmSdmUdmPbikbikbikbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikaqeaqdaqdaqdaqfbikbikbikapwapwapwapwapwasSanGasTasUapBatRapBasVasWapEapEatSapEasXasYapEatSapEasZataatbatcatdateatfatgathapOatiatjatkatlatmatnatoatpatqarMatrapXatsattatuatvatwatxatyatzatAatBamKatCarTatDaabaabbikaabbikbikbikbikbikbikbikbikaabaabaabaabaabatEatFatDaabaabaabaabaabbikbikbikbikbikbikbikbikbikaabbikaabasMasMatGatHatIatJatKatLatMatIasMasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmVdmSdmUdmPbikbikbikbikbikbikaabatNamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwatOanGasTasUatPatUatTauyatVaqsatQauJauEavxauTavEavBatWaqsatXatYatZauaaubaubaucaudapOaueaufaugauhapOauiaujaukarNarMaulapXatsarPattattattaumaovaunauoaupamKbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikaabaabaabaabauqaabaabbikbikaabaabaabbikbikbikbikbikbikbikbikasMasMasMasMauratJausatJausautatJatJatJauuasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmSdmSdmSdmWbikbikbikbikbikbikacGbikbikaabbikaabbikbikauvbikbikaabbikaabbikbikacGbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikapwauwanGauxasUarkavJauzauAauBauCauDdlLauFauGauHauIdlMauKauLauMauNauNauOauNauNauPauQauRauSdlNapOauUapOauVauWauXauYauZavaapXatsavbavcavcavcavdaveavfavgavhamKbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabbikbikbikaabaabaabaviaabaabbikbikaabbikaabaabbikbikbikbikbikbikbikasMavjavkavlavmavnavoavpatJatJavqavratJavsasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmXdmSdmSdmYbikbikbikbikbikbikacGacGacGaabaabaabaabavtavuavtaabaabaabaabacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwavvanGavwasUdlPdlQavyavzavAashdlRdlSashavCavDashdlTdlUashavFavGavHavGavGavHavGavIapOatidlVapOavKapOavLavMavNavOavPavQavRavSavTavUavUavUavVavWavXavYavYavYbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikaabaabavZawaavZaabaabbikaabbikbikaabaabbikbikbikbikbikbikasMawbawcawdaweawfawgatJatJatJawhawiatJawjasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmZdmSdnadmPbikaahbikbikbikbikaabbikaabbikbikaabbikavtawkawlbikbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmapwapwawnapwasUasUasUawoawpawqawrawrawsawrawsawrawrawtasZasZasvawvawwawuawvawwawuawyawzawzawzawzawzapOawAawBawCawCawDawCawEawFavUawGawHawIavVawJawKawLawMavWbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikaabbikavZawNavZbikaabbikaabbikbikbikaabaabbikbikbikbikbikasMawOawPavlawQawRawSawTatJawUawVawWawXasMawYaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdnbdnddncdnddnebikbikbikbikbikbikaabbikaabbikbikaabavtavtawZaxaavtbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxbaxcaxdaxeaxfaxgaxhaxiaxhaxjaxhaxhaxkaxlaxlaxlaxlaxlaxmaxnaxoaxlaxlaxlaxlaxpaxlaxlaxlaxlaxqaxraxsaxtaxuaxvaxwaxxapWaxyaxzaxAaxBaxCaxDaxEaxFavUaxGaxHaxIavVaxKaxLaxJaAZavWbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikaabavZavZaxMavZavZaabbikaabbikbikbikbikaabaabbikbikbikbikasMaxNaxOavlasMavlavlaxPaxQasMasMasMasMasMasMaabaabbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdnbdnfdnebikbikbikbikbikbikaabaabbikaabbikbikaabaxRaxSaxTaxUaxRaxVaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxWaxXaxYaxZayaaybaycaydayeayfaxqaxqaygaxqaxqaxqaxqaxqayhaxqaxqaxqaxqaxqaxqayiaxqaxqaxqaxqaSWaxqaykaxqaylaxqaymaynapWayoaypayqayraysaytaxEayuavUayvaywayxayyayzayAayBawMavWbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikaabayCayDayEayFayCaabbikaabbikbikaabbikbikaabaabbikbikayGasMavlasMavlayHayIayHayJayHayHayHayKayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaxVaxVaxVaxVaxVaabaabaxRazsayMayNaxRayOaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmayPayQayRaySayTawmayUayVayWayXayYayZazaazbazcayXayXayXazdayXayXayXayXayXayXazeazfazgazgazgazhaziazjaziazkazlazmaznapWazoazoazoazoazoazoaxEaxFavUazpaxHazqavVcscazraxJcvYavWbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikaabayCaFCaztazuayCaabbikaabbikbikaabbikbikayGazvayGazvayGayKayHayHayHayHayHayHayHayHayHazwazxayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikazyazzazybikbikbikaxVaxVaxVaxVazAazBazCaxVbikbikaxRazDazEazFazGazHaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmawmazIazIazJazKazKazLazMazNazOazPazPazOazQazOazRazRazRazRazRazRazSazRazRazTazUazVazWazIazXazIazYazIazIaqVazZaovaovaovaovaAaaxFavUaAbaxHaAcavVaAdayAayBawMavWbikbikbikbikbikbikbikbikaabaabbikbikbikbikazyaAeazybikaabayCaAfaAgaAhayCaAiaAiaAiaAiaAiazvazvazvayGaAjayHazwazxayJayHayJayJayJayGaAkayGayGayGayGayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikaAlaAmaAlbikbikaabaxVaAnaAoaApazHaAqazHaxVaAlaAlaxRaxRaAraAsazGazHaxVaxVaAlaAlaAlaxVaxVbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikazJaAtaAuaAvazMaAwazOaAxaAyaAzaAAaABaACaADbfTaAFaAGaAHaAIaAJaAKaALaxqaxraAMaANaAOaAPaAQaAPaAPaAPaARaAPaAPaAPaAPaASaATaAUaAVaAWaAXaAYcNsaBaaUadcuavWaabaBbaBcaBcaBcaBcaBcaBdaabaabbikbikbikbikazvaBeazvbikaAiayCayCaBfaBgayCaBhayHayHayHayJaBiayHaBjayGayHayHayHaBkayJayHayGaBlaBmayGayHaBnayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8895,14 +8920,14 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaCuaCuaInaInaInaInaInaInaInaInaInaCuaDEbgLbgMbgNbgNbgNbgNbgNbgNbgObgNbgNbgNaDEbdVbejbgPbcobgQbecbecdhUbgSbgTbgUdhUbecbecbecbgVbcobejbekbctbgWbgXbgYbcvbgZbhabhbbcvbhcbhdbhebhfbhgbesbhhbhiaXObcDbcDbhjbcEbcEbcEbhkbhlbhmbhnbhobhobhpbhqbhobhrbhobhsbhtbhubhvbhwbhxbcEbcEbcEbhjbcKbcKbeGaYiaYiaMebhybhzbgkbhAbmwbhBbhCbmwbhDbhEbglbmwbnMbeMbeMbhFbcSbhHbhIbhJbhKbhLbeMbhMbgubhNdlHbeYbeYbhObhPbhQaVbaVhayHaRDbhRbhSbhTbbPbbQbhUaTvaTvbhVaTvbhWbhXaQbbhYbhZbiabfgbfgbibbiabicaQbbidbgHbatbatbatbavbatbatbKnbIzbPfbNjbiibPfddJbmKbmKbmKbmKbmKbmKbmKbmKbmKbmKbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikblsbltbltblubltbltbltblvbltbltbmPaabaInaLAaJtbilbgNbimbinbiobipbiqbirbisbitbgNbiubivbiwbixbcobiybecbecdhUbgTbizbiAdhUbecbecbiBbiCbcobejbekbctbctbiDbctbcvbiEbiFbiGbcvbiHbhfbiIbhfbiJbesbeubiKaXOaXPaXPbiLbiMbiNbcEbiObfRbiPbhobhobiQbiRbiSakybiSbiUbiVbiWbiXbiYbiZbjabcEbjbbiMbjcbjdbjebeGaYiaYibjfbmwbjgbmwbmwbmwbjhbjibmwbhDbjjbglbmwbeLbeMbeMbjkbBDbjmbjnbjobjpbhLbjqaVbdlJdlIdlKbeYbeYbeXbhPbjsaVbbjtbjuaRDbjvaRDaRDbjwbbQbjxbjyaTvbjzbjAaWSbjBbdvbjCbjDbjEbjFbjFbjGbjHbjIbdvbjJbjKbatbjLbatbavbatbatddAbaAbaAbaAbaAbgKbqUddBbmKbutbwmbtmbmKbutbwmbtmbmKddCbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikblsbohbptbojbpwbpwbqWbpwbpwbpwbqWblubjNaInaKzaKBbfqbgNbimbjObjPbimbjQbjRbjSbjTbgNbjUaFmbjWbcsbcobjXbjYbjZbkabkbbkcbkdbkebkebkebkfbkgbcobejbivbkhbkibkjbkkbcvbcvbcvbcvbcvbklbkmbknbkobkpbesbeubiKaXJaXJaXJbkqbkrbksbktbkubkvbhobkwbkxbkybkzbkAbkBbkCbkDbkEbkFbkGbkubkHbkIbkJbkKbkMbkLbkObkObkPaYibkQaMebmwbkRbkSbglbmwbkTbkUbmwbkVbkWbglbmwbnMbeMbeMbeMbeNbeMbkXbeMbjpbhLbkYaVbdlObhNbeXbeYbeYbeXbhPblaaVbblbblcbldbleblfblgblhblibljbljbljbljbljbljblkbllblmbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbatbatbavbatbatddDbgKblrblrblrbaAbwmbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbwmbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbqYbqXbqXbqXbqXbqXbqXbqXbqXbqXbqXbqZbraaGdbraaJrbfqbgNblwbimblxblxblxblybimblzbgNblAblBbjWblCblCblCblCblDblCblEbecblFblGblHblHblIblJbcoblKblLblMblNblOblPblQblRblSblRblTblTblTblTblTblUberbeublVblWblXblYblZbmabmbbmcbmdbkBbmebmfbmgbmgbmgbmgbmhbmgbmibmjbmkbmlbmebmmbmnbcEbmobmpbmqbkNbmsbmtaYiaYibjfbmwbnCbmwbmwbmwaRebmwbmwbmvbmvbmwbmwbmxbeMbeMbmybmzbeMbeMbeMbmAbmBbmCaVbbgxbhNbeXbeXbeXbeXbhPbmDaVbbmEbmFbmFbmGbmFbmHbbPbbPbbPbbPbmIbbPbbPbbPbmJblobfgbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbfjbfjbfkbfjbatddEbaAbmLbmMbmNbaAbBQbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbBQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbrbbrebrdbrfbrfbrgbrfbrfbrfbrgbluaInaInaKzbrVbcjbmQbimbmRblxblxblxblybmRbimbgNbmSbmTbjWblCbmUbmVbmWbmXblCbmYbmZbnabcobnbbncbndbnebcobejbnfbngbngbnhbngbngbngbngbnibnjbnjbnjbnkbnjbnlbnmbnnbnobnpbnqbnqbnqbnqbnqbnqbnrbnsbnrbmgbmgbntbnubnvbnwbnxbnybntbnzbmgbnAbnBbnAbnAbnAbnAbnAbnAbnAbmtaYiaYiaMebnEbnDcakbnGbmwbnFbmwbnJdmhdmgbmwbpjaUTbnKbnLaUTaUTczObnNddybnNaUTaUTaVbbnObnPbnQbnQbnQbnQbnPbnRaVbbnSbmFbmFbmGbnTaRDbnUbnVbnWbnXbnYbnZboabobbocaQbbodaRSboebfgbfgboeaRSbofaQbbogbgHbatbgIbgIbgJbgIbatddDbgKblrblrblrbaAbGVbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbGVbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbltbltblubltbltbltblvbltbltbtnaabaInboibdFbokbgNbjObjObjObimbolbombonboobgNbopboqbjWblCborblCbosbotblCboubovbowbcobnbbncbndbiCbcobejbnfbngboxboybozboAboBbngboCboDboEboFbnmbnmbnmbnmboGboHboIbnqboJboKboLboMboNboOboPboQbmgboRbnvboSboTboUboTboSbnvboVbmgboWboXboYboZbpabpbbpcbpdbnAbpebpfbpfbpgaMeaMeaMeaMebphbjfbphbpiaMeaURaMeaMeaUTaUTaUTaUTbplbpkbpkbpkbpkbpmbpJaVbbakbpnbakbpobpobakbpnbakaVbbnSbmFbmFbppbnTaRDaRDaRDaRDaRDbjvaRDaRDaRDaRDaQbbpqaQcaQcaQcaQcaQcaQcaQbaQbbprbpsbatbatbatbavbatbatddAbaAbaAbaAbaAbgKbqUddFbmKbmKbmKbmKbmKbmKbmKbmKbmKddGbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaKzaDEaDEaDEaDEaDEaDEbtobpubgNbgNbgNbgNbgNbgNbpvbgNbgNbgNbejbejbpxblCbpybpzbosbpAblCdlEbpCbpBbcobnbbncbndbecbcobejbnfbngbpDbpEbpFboAbpFbngboCbpGbpHbpIbmubpKbpLbnmbpMbpNboIbpObpPbpQbpRbpSbpSbpRbpTbpUbmgbpVbnvbnvbpWbpXboTboSbnvbpYbmkbpZbqabqbbqcbqdbqebqbbqfbnAbqgbqhbqibqjbqkbqlbqmbqnbqnbqnbqnbqnbqnbqobqpbqqbqnbqnbqsbqnbqnbqnbqnbqnbqnbqnbqndcZbqubqvbqvbqvbqvbqvbqvbqwbqlbqxbqybqyaHkbqAbqBbqAbqCbqAbqDbqEbqFbqAbqGbqHbqIbqJbqKbqKbqKbqKbqKbqKbqKbqLbqMbqNbqNbqNbqNbqObqNbqPbKnddHbPfddIbiibPfdlbbmKbmKbmKbmKddKbmKddKbmKbmKbmKddGbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbtpbtqbtqbtqbtqbwpbwpbtqbtqbxZbikaabaInaLAaJtbzPbzObzRbzQbzQbzQbzQbzSbzUbzTbcsbdVbBFbrhblCblCblCbribotblCbcobcobcobcobnbbrjbrkbrlbcobrmbrnbngbrobrpboAbpFbrqbngboCbrrbpHbpIbpIbrsbrtbnmbrubpNboIbpObrvbrwbrxbrybrzbrAbpTbrBbmgbrCbpWbnvbrDbrEbrDbnvbpWbrFbnzbrGbqbbqbbqcbrHbqebqbbrIbnAbrJbqibqibqjbqkbqlbqnbqnbqnbqnbqnbqnbqnbrKbqnbqnbqnbqnbqnbqnbrLbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrNbrObrPbqKbqKbrQbmFbmFbmFbmFbmFbmGbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbrRbmFbrSbrTbatbatbatbatbatbatbatddLbaAbgKbaAbaAbaAbqUddMddOddNbdBddPbdBddPbdBddQddMddObqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCbBHdjhbDDdjidjidjkdjjbtqbxZbjNaInaInaKBbrWbrXbrYbrXbrXbrXbrXbrZbsabsbbcsbcsbscbsdblCbmUbsebsfbpAblCbsgbshbsgbcobcobcobcobsibcobsjbskbngbslbsmbpFbsnbsobngboCbnmbspbpIbpIbpIbsqbnmbsrbpNboIbpObWDbrwbrxbstbsubrAbpTbsvbmgbswbsxbnvbsybszbsAboSbsBbsCbsDbsEbsFbsGbsHbsIbsJbqbbsKbnAbsLbsMbqibqjbqkbqlbqnbsNbqnbqnbqnbqnbsObsPbsPbsPbsPbsQbqnbqnbqnbqnbsRbqnbsNbsSbqnbsTbsUbsVbqnbsWbsXbsXbsYbsZbtabtbbmFbmFbmFbmFbmFbmFbmFbtcbtdbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbtebtfbtfbtgddSddRddUddTddTddTddTddVddWbaAaabbikbikaabbqUddXddZddYdeabqUbikbqUdecdebdecdecbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjldjidjidjidjidjidjidjideHdjnaGddjnaJrbtrbrXbtsbttbtubtvbtwbrZbtxbtybtzbtzbtAbtBblCblCblCbosbtCborbcsbcsbcsbcsbtDbejbejbskbejbsjbskbngbtEbtFbtGbtHboAbngbtIbnmbtJbpIbpIbpIbtKbtLbtMbpNbtNbnqbtObtPbpRbpRbpRbpRbpTbtQbmgbtRbtSbmgbmgbmgbmgbmgbmgbmgbnzbnAbqrbtUbtVbtWbtXbtYbtZbnAbvubuabuabucbucbucbucbucbucbucbudbudbuebufbugbugbufbuebudbudbuhbuhbuhbuhbuhbuhbuibuibujbuibuibuibuibuibukafkbumbunbmFbmFbuobuobupbupbupbupbupbuqbtfbtfbtebtfbmFbtfbtfbtfbtfburbusbusbusbusdedbuubuubuubuubuubuubuubuubuubikbikbikbikbdBddYddYddYdeebqUbikbqUdefdebdebdegbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjodjpdjpdjidjpdjpdjpbtqdjqaInaInaInaKBbuvbrXbuwbuxbuxbuxbuybrZbejbuzbuAbuBbuCbuDblCbmUbuEbosbuFborbuGbuHbuIbuJbuKbuLbuLbuMbuLbuNbuObngbuPbuQbuRbuSbuTbuUbuVbnmbuWbpIbpIbuXbuYbuZbtMbpNbvabnqbvbbvcbvdbvebvfbvgbvhbnqbnqbvibvjbvkbvlbvmbvlbvnbvjbikbvobnAbvpbvqbvrccIbtXbqbbvtbnAbxebvwbxfbucbzcbvybvzbvAbvBbvCbvDbvEbvFbvGbvHbvHbvGbvIbvJbvKbuhbvLbvMbvNbvObuhbvPbvQbvRbvSbvTbvUbvUbvVbukafNbvXbvYbvZbvYbwabwabupbwbbwcbwdbupbwebwfbwebupbwgbtfburbusbwhbwibwhbusbwjbwkbusdeicngbxXbwobikbikbikbikbikbikbikbikbikbikbqUddXddZddYdejbqUbikbqUdekdekdekdekbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbqYbqXbqXbqXbqXbqXbqXbqXbqXbqXbqXbqZbraaGdbraaJrbfqbgNblwbimblxblxblxblybimblzbgNblAblBbjWblCblCblCblCblDblCblEbecblFblGblHblHblIblJbcoblKblLblMblNblOblPblQblRblSblRblTblTblTblTblTboFblUbeublVblWblXblYblZbmabmbbmcbmdbkBbmebmfbmgbmgbmgbmgbmhbmgbmibmjbmkbmlbmebmmbmnbcEbmobmpbmqbkNbmsbmtaYiaYibjfbmwbnCbmwbmwbmwaRebmwbmwbmvbmvbmwbmwbmxbeMbeMbmybmzbeMbeMbeMbmAbmBbmCaVbbgxbhNbeXbeXbeXbeXbhPbmDaVbbmEbmFbmFbmGbmFbmHbbPbbPbbPbbPbmIbbPbbPbbPbmJblobfgbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbfjbfjbfkbfjbatddEbaAbmLbmMbmNbaAbBQbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbBQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbrbbrebrdbrfbrfbrgbrfbrfbrfbrgbluaInaInaKzbrVbcjbmQbimbmRblxblxblxblybmRbimbgNbmSbmTbjWblCbmUbmVbmWbmXblCbmYbmZbnabcobnbbncbndbnebcobejbnfbngbngbnhbngbngbngbngbnibnjbnjbnjbnkbnjbnlbuWbnnbnobnpbnqbnqbnqbnqbnqbnqbnrbnsbnrbmgbmgbntbnubnvbnwbnxbnybntbnzbmgbnAbnBbnAbnAbnAbnAbnAbnAbnAbmtaYiaYiaMebnEbnDcakbnGbmwbnFbmwbnJdmhdmgbmwbpjaUTbnKbnLaUTaUTczObnNddybnNaUTaUTaVbbnObnPbnQbnQbnQbnQbnPbnRaVbbnSbmFbmFbmGbnTaRDbnUbnVbnWbnXbnYbnZboabobbocaQbbodaRSboebfgbfgboeaRSbofaQbbogbgHbatbgIbgIbgJbgIbatddDbgKblrblrblrbaAbGVbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbGVbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbltbltblubltbltbltblvbltbltbtnaabaInboibdFbokbgNbjObjObjObimbolbombonboobgNbopboqbjWblCborblCbosbotblCboubovbowbcobnbbncbndbiCbcobejbnfbngboxboybozboAboBbngboCboDboEbSVbyzbyzbyzbuVboGboHboIbnqboJboKboLboMboNboOboPboQbmgboRbnvboSboTboUboTboSbnvboVbmgboWboXboYboZbpabpbbpcbpdbnAbpebpfbpfbpgaMeaMeaMeaMebphbjfbphbpiaMeaURaMeaMeaUTaUTaUTaUTbplbpkbpkbpkbpkbpmbpJaVbbakbpnbakbpobpobakbpnbakaVbbnSbmFbmFbppbnTaRDaRDaRDaRDaRDbjvaRDaRDaRDaRDaQbbpqaQcaQcaQcaQcaQcaQcaQbaQbbprbpsbatbatbatbavbatbatddAbaAbaAbaAbaAbgKbqUddFbmKbmKbmKbmKbmKbmKbmKbmKbmKddGbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaKzaDEaDEaDEaDEaDEaDEbtobpubgNbgNbgNbgNbgNbgNbpvbgNbgNbgNbejbejbpxblCbpybpzbosbpAblCdlEbpCbpBbcobnbbncbndbecbcobejbnfbngbpDbpEbpFboAbpFbngboCbpGbpHbAibmubpKbpLbnmbpMbpNboIbpObpPbpQbpRbpSbpSbpRbpTbpUbmgbpVbnvbnvbpWbpXboTboSbnvbpYbmkbpZbqabqbbqcbqdbqebqbbqfbnAbqgbqhbqibqjbqkbqlbqmbqnbqnbqnbqnbqnbqnbqobqpbqqbqnbqnbqsbqnbqnbqnbqnbqnbqnbqnbqndcZbqubqvbqvbqvbqvbqvbqvbqwbqlbqxbqybqyaHkbqAbqBbqAbqCbqAbqDbqEbqFbqAbqGbqHbqIbqJbqKbqKbqKbqKbqKbqKbqKbqLbqMbqNbqNbqNbqNbqObqNbqPbKnddHbPfddIbiibPfdlbbmKbmKbmKbmKddKbmKddKbmKbmKbmKddGbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbtpbtqbtqbtqbtqbwpbwpbtqbtqbxZbikaabaInaLAaJtbzPbzObzRbzQbzQbzQbzQbzSbzUbzTbcsbdVbBFbrhblCblCblCbribotblCbcobcobcobcobnbbrjbrkbrlbcobrmbrnbngbrobrpboAbpFbrqbngboCbrrbpHbAibpIbrsbrtbnmbrubpNboIbpObrvbrwbrxbrybrzbrAbpTbrBbmgbrCbpWbnvbrDbrEbrDbnvbpWbrFbnzbrGbqbbqbbqcbrHbqebqbbrIbnAbrJbqibqibqjbqkbqlbqnbqnbqnbqnbqnbqnbqnbrKbqnbqnbqnbqnbqnbqnbrLbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrNbrObrPbqKbqKbrQbmFbmFbmFbmFbmFbmGbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbrRbmFbrSbrTbatbatbatbatbatbatbatddLbaAbgKbaAbaAbaAbqUddMddOddNbdBddPbdBddPbdBddQddMddObqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCbBHdjhbDDdjidjidjkdjjbtqbxZbjNaInaInaKBbrWbrXbrYbrXbrXbrXbrXbrZbsabsbbcsbcsbscbsdblCbmUbsebsfbpAblCbsgbshbsgbcobcobcobcobsibcobsjbskbngbslbsmbpFbsnbsobngboCbnmbspbAibpIbpIbsqbnmbsrbpNboIbpObWDbrwbrxbstbsubrAbpTbsvbmgbswbsxbnvbsybszbsAboSbsBbsCbsDbsEbsFbsGbsHbsIbsJbqbbsKbnAbsLbsMbqibqjbqkbqlbqnbsNbqnbqnbqnbqnbsObsPbsPbsPbsPbsQbqnbqnbqnbqnbsRbqnbsNbsSbqnbsTbsUbsVbqnbsWbsXbsXbsYbsZbtabtbbmFbmFbmFbmFbmFbmFbmFbtcbtdbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbtebtfbtfbtgddSddRddUddTddTddTddTddVddWbaAaabbikbikaabbqUddXddZddYdeabqUbikbqUdecdebdecdecbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjldjidjidjidjidjidjidjideHdjnaGddjnaJrbtrbrXbtsbttbtubtvbtwbrZbtxbtybtzbtzbtAbtBblCblCblCbosbtCborbcsbcsbcsbcsbtDbejbejbskbejbsjbskbngbtEbtFbtGbtHboAbngbtIbnmbtJbAibpIbpIbtKbtLbtMbpNbtNbnqbtObtPbpRbpRbpRbpRbpTbtQbmgbtRbtSbmgbmgbmgbmgbmgbmgbmgbnzbnAbqrbtUbtVbtWbtXbtYbtZbnAbvubuabuabucbucbucbucbucbucbucbudbudbuebufbugbugbufbuebudbudbuhbuhbuhbuhbuhbuhbuibuibujbuibuibuibuibuibukafkbumbunbmFbmFbuobuobupbupbupbupbupbuqbtfbtfbtebtfbmFbtfbtfbtfbtfburbusbusbusbusdedbuubuubuubuubuubuubuubuubuubikbikbikbikbdBddYddYddYdeebqUbikbqUdefdebdebdegbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjodjpdjpdjidjpdjpdjpbtqdjqaInaInaInaKBbuvbrXbuwbuxbuxbuxbuybrZbejbuzbuAbuBbuCbuDblCbmUbuEbosbuFborbuGbuHbuIbuJbuKbuLbuLbuMbuLbuNbuObngbuPbuQbuRbuSbuTbuUdngbyzdnidnhbpIbuXbuYbuZbtMbpNbvabnqbvbbvcbvdbvebvfbvgbvhbnqbnqbvibvjbvkbvlbvmbvlbvnbvjbikbvobnAbvpbvqbvrccIbtXbqbbvtbnAbxebvwbxfbucbzcbvybvzbvAbvBbvCbvDbvEbvFbvGbvHbvHbvGbvIbvJbvKbuhbvLbvMbvNbvObuhbvPbvQbvRbvSbvTbvUbvUbvVbukafNbvXbvYbvZbvYbwabwabupbwbbwcbwdbupbwebwfbwebupbwgbtfburbusbwhbwibwhbusbwjbwkbusdeicngbxXbwobikbikbikbikbikbikbikbikbikbikbqUddXddZddYdejbqUbikbqUdekdekdekdekbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjrbtqbtqbtqbtqbtqbtqbtqbtqdjqbikbikaInbwqbdFbwrbrXbwsbrXbwtbuxbwubwvbrZbwwbwxbwybwzbuDblCblCblCblCblCblCbwAbwBbwCbwDbwEbngbngbngbngbngbngbngbwFbngbngbngbwGbngbwHbwIbwJbpIbpIbpIbwKbtLbwLbpNbwMbnqbIDbvcbnrbnrbnrbnqbwObnqbwPbwQbwRbwSbwTbwUbwVbwWbwXbwYbwZbnAbxabqbbxbbxcbtXbxdbqbbnAbzbbxgbANbucbxhbxibxjbxkbxlbxmbxnbvHbvHbvHbvHbvHbvHbvHbvHbxobxpbxqbxrbxsbxtbuhbxubxvbxwbxxbxybxzbxvbxAbukbDdbvXbxCbxDbxEbxFbxFbxGbxHbxIbxJbxKbxLbxMbxNbupbxObxPbxQbusbxRbxSbxTbLSbxUbxVbusbxWbxXbxYbwobikbikbikbikbikbikbikbikbikbikbDybtldemdemdemdenbikdeodepdepdepbtlbDzbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaInaInaInaInaInaInaInaKBaJrbyabrXbybbycbydbyebyebyfbygbyhbyibyibyjbykbtzbtzbtzbtzbtzbtzbylbymbymbynbyobngbypbyqbyrbysbytbyubyvbywbngbyxbyybyzbuVbtLbwJbpIbpIbyAbnmbnmbyBbyCbyDbyEbyFbyGbyHbyIbyJbyKbyLbyMbyNbyObwXbyPbyQbyPbyQbyRbwXbwYbySbyTbyUbyVbyWbyXbyYbyZbzabyTbAObvwbvwbucbzebzdcSCbzfbzgbucbxnbvHbvHbvHbvHbvHbvHbvHbzhbzibzjbzkbzlbxqbzmbuhbznbzobzpbxxbxAbxzbzqbzrbukbIbbztbzubzvbzvbzwbzxbzybzzbzAbzAbzAbzBbzAbzCbzDbzEbzFbzGbzHbzIbzJbzKbzKbzKbzLbusbzMbxXbzNbwobikbikbikbikbikbikbikbikbikbikbikbDyderderderbDzbikbDyderderderbDzbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaIndjtdjsdjuaIoaIoaIobdFaJraJrbrXbzVbrXbzWbzXbzYbzZbrXbcsbAabAabAbbAcbAbbAbbAbbAcbAbbcsbcsbngbngbngbAdbngbAebAebAebAebAebAebyvbAfbAgbAhbAibAjbAkbAlbAmbAnbAobApbAqbArbAsbAtbAubAvbAwbAwbAxbAybAzbAAbABbACbADbAEbvjbAFbwVbAGbwTbAHbvjbikbAIbAJbAKbALbAJbAJbAJbAJbAMbnAbCBbvwbCCbAPbAQbARbASbATbAUbucbAVbAWbAXbAYbAZbBabBbbBcbvHbBdbuhbBebzlbBfbBgbuhbBhbBibxwbxxbxAbxzbxvbxAbukbDdbvXbBjbBkbBlbBmbBnbBobBpbBqbBrbBsbBtbBubKpbupbBwbBxbBybusbBzbBAbBBbxUbBCbKwbusbzMbxXbBEbwobikbikbikbikaabaabaabaabaabaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8916,7 +8941,7 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkhdjYdjHdjHdjHdjHdjHdkidjHdjHdjFdjydjydjydjydjydjydkjbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevdeEdeDdeGdeDbNlbNmbNnbNnbNnbNnbNnbNobNpbNqbICbWSbngbNsbNtbNubNvbNwbNxbNybNybNybNzbNzbNAbvvbNBbNCbHmbCpbNDbNEbNFbKvbNGbKzbNHbNIbNJbNKbNLbFNbNMbMabikbikbikbHybNNbNObNPbNQbMebMfbMgbHybPibNUbQObPjbNVbNWbNXbNYbNZbOabObbOcbKUbKUbOdbOebKUbKUbJkbKZbOfbOgbOhbOibOjbOkbLdbOlbOmbOnbOobOpbOqbOrbOrbOsbOtbOubOvbOwbJVbJVbOxbJVbOybJVbOzbJVbOAbOBbOBbOCbODbOEbOFbOGbOHcsjbOJbOKbOLbNabOMcxHbikbikbikbGxbORbJFbOPbOQbGzbOObNibGxbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkmdkldkodkndjHdjFdjHdjHdjFdjHdkqdkpdkrbikbikbikbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevdewbFnbBRbBRbngbngbBRbBRbBRbBRbBRbngbngbBRbBRbBRbngbOVbOVbOVbOWbOVbNzbOXbOYbOZbPabNzbDXbvvbPbbPcbPcbCpbCpbCpbCpbCpbPdbKzbISbIRbPebNKbPgbPhbMabMabvjbvjbvjbHybHzbHybHybHybHybHybHybHybQPbvwbQQbPkbPlbPmbPnbPlbPlbPobPpbPqbPrbPsbPtbPubPvbPwbMqbPxbPybPzbPAbPBbPCbPDbPEbPFbPGbPHbPIbPJbPKbPLbMHbPMbLhbLhbPNbPObPNbPPbPQbPPbPPbPPbPRbPSbPTbPTbPUbPVbPWbPXbOFbPYbPZbQabQbbQcbQdbNabOMcxHbikbikbikbGxbNfbNgbGxbGzbGxbGxbGzbGxbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjydjydjydjydjydjydjFdjOdjHdksdjHdkudktdkvbikbikbikbikbikbikbikbikbikbikbikbikbikdeJdeIdevdeKdevdeLdeMbikbikbikbikbikbikbikbikbikbikbQgaabbikbikbikbikbOVbQhbQibQjbQkbNzbQlbQmbQnbQobNzbDXbvvbQpbQqbQrbQsbQtbQubQvbQwbQxbQybQzbQAbQBbQCbQDbQEbQFbQGbQHbQIbQJbQKbQLbQMbQRbuabQSbvwbShbSgbSibvwbSjbPlbQTbQUbQVbQWbQXbJkbQYbQZbRabRbbRcbRdbRebRfbRgbRhbRibLbbRjbOibRkbRlbRmbRnbRobRpbLgbRqbMHbMHbMHbRrbLhbPNbRsbRtbRubRvbRwbRxbRybPPbRzbRAbRBbPTbPTbRCbPWbRDbREbWHbRGbRHbRIbRJbRKbNabRLbwobikbikbikbGxbGxbGxbGxbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydkxdkwdkydkxdkzdjFdjHdjHdjFdjHdkBdkAdkCbikbikbikbikbikbikbikbikbikbikbikbikbikdeOdeNdePdePdePdeNdeQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbOVbRMbRNbRObRPbNybRQbRRbRSbRTbNzbDXbRUbRVbvvbvvbFXbRWbubbQNbQMbRXbRYbRXbRZbSabSabSbbScbSdbSabSabSebSabSfbSabQMbQRbuabSlbSkbTJbTIbTLbTKbvwbPlbSmbQUbSnbSobSpbJkbSqbSrbSsbStbSubSvbSwbSxbJkbSybSzbLbbSAbSBbSBbSCbSDbSEbSFbSGbLgbSHbSIbMHbSJbSKbLhbPNbSLbSMbSNbSObSPbSQbSRbPPbSSbRAbSTbSTbPTbSUbSVbSWbSXbSYbSZbTabTbbTcbTdbNabOMbwobTebikbikbikbikbikbikbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydkxdkwdkydkxdkzdjFdjHdjHdjFdjHdkBdkAdkCbikbikbikbikbikbikbikbikbikbikbikbikbikdeOdeNdePdePdePdeNdeQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbOVbRMbRNbRObRPbNybRQbRRbRSbRTbNzbDXbRUbRVbvvbvvbFXbRWbubbQNbQMbRXbRYbRXbRZbSabSabSbbScbSdbSabSabSebSabSfbSabQMbQRbuabSlbSkbTJbTIbTLbTKbvwbPlbSmbQUbSnbSobSpbJkbSqbSrbSsbStbSubSvbSwbSxbJkbSybSzbLbbSAbSBbSBbSCbSDbSEbSFbSGbLgbSHbSIbMHbSJbSKbLhbPNbSLbSMbSNbSObSPbSQbSRbPPbSSbRAbSTbSTbPTbSUdnjbSWbSXbSYbSZbTabTbbTcbTdbNabOMbwobTebikbikbikbikbikbikbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjZdjYdkDdkDdkDdkDdkDdkEdjHdjHdjFdjydjydjydjydjydjydjBbikbikbikbikbikbikbikbikbikbikbikdeRdeSdeSdeSdeTbikbikbikbikbikbikbikbikbOUbOTbQebOTbQfbikbikbikbOVbOVbTjbTkbRObTlbNybTmbQnbTnbTobNzbDXbTpbTqbTrbTsbTtbTubTvbTwbTxbTybTzbTAbTBbTCbTCbTDbTEbTEbTEbTEbTEbTEbTFbTGbTHbTNbTMbTPbTOdlidjmdlkdljdllbPlbTQbQUbQVbTRbSpbJkbSqbSrbTSbTTbTUbTVbTWbTXbJsbTYbTZbLbbLbbUabUabLbbSDbLdbUbbUcbLgbUdbUebUfbUgbUhbLhbPNbUibUjbUkbUlbUmbUnbUobPPbUpbRAbSTbSTbPTbUqbUrbUsbUtbUubUvbUwbUxbUybUzbNabOMbUAbUBbUAbUCbUDbUCbUCbUCbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikaabaabaabaabaabbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkhdjYdkDdkDdkDdkFdkGdjFdjHdjHdjFdjHdjHdjHdkHdjHdkIdjFbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbTgbTfbTibThbTgbUIbUIbUIbOVbUJbUKbULbUMbUNbUObUPbUQbUQbURbNzbUSbUTbUUbUVbUVbUWbUXbUYbUVbUZbUZbVabVbbONbUZbUZbVdbQMbQMbVebVfbVfbVfbVgbVhbVfbVfbVibVjbVkbVkbVlbVkbVmbVnbVkbVobVpbVqbPlbVrbVsbSqbVtbVubVvbVwbVxbVybVubJkbSybVzbVAbVBbVCbVDbVEbVFbVGbVHbVIbVJbVKbVLbVMbVNbVObLhbPNbPNbVPbVQbVRbVSbVRbVTbPPbVUbVVbVWbVWbPTbVXbVYbVZbNabNabNabNabNabNabNabNabOMbUAbWabWbbWcbWdbWdbWebUCbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikaabbWfbWfbWfbWfbWgbWgbWhbWhbWhbWhbWiaabaabbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkKdkJdkDdkLdkMdjFdjHdjHdkNdjHdjHdjHdkOdjHdkPdjFbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbQebUEbUFbUEbQebUIbWmbWlbOVbWnbWpbWqbWrbWsbNzbWtbWubWvbWwbNzbUTbUTbWxbUVbWybWzbWAbWBbWCbUZdmbbWEbWFbWGcAzbUZbWIbWJbWKbVfbWLbWMbWObWNbWPbWQbWRceLbWTbWUbWVbWWbWXbWYbWZbXabXbbXcbXdbXebXfbXgbXhbSrbXibXjbXkbXlbXmbXnbJsbXobXpbXqbXrbVDbXsbXsbXtbXubLgbXvbXwbXxbXybXzbXAbXBbLhbXCbXDbXEbXFbXEbXEbXGbXHbXIbXJbXKbXLbXMbPTbXNbXObPXbEXbxXbXPbXQbXRbXRbXQbXRbXSbUAbXTbXUbWcbWdbXWbXVbUCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWfbXXbXYbXXbWgbWhbWhbXZbYabXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 358042bd6f2..366fa34f260 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -18,11 +18,11 @@ "ar" = (/obj/docking_port/stationary/transit{dir = 4; dwidth = 1; height = 4; id = "pod3_transit"; name = "pod 3 in transit"; width = 3},/turf/space/transit/east{dir = 8},/area/space) "as" = (/obj/docking_port/stationary/transit{dir = 8; dwidth = 10; height = 35; id = "whiteship_transit"; name = "whiteship in transit"; width = 21},/turf/space/transit/horizontal{dir = 4},/area/space) "at" = (/turf/unsimulated/wall,/area/vox_station) -"au" = (/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) +"au" = (/turf/unsimulated/floor/vox,/area/vox_station) "av" = (/obj/docking_port/stationary/transit{dir = 4; dwidth = 1; height = 4; id = "pod4_transit"; name = "pod 4 in transit"; width = 3},/turf/space/transit/east{dir = 8},/area/space) "aw" = (/obj/docking_port/stationary/transit{dir = 1; dwidth = 1; height = 4; id = "pod1_transit"; name = "pod 1 in transit"; width = 3},/turf/space/transit,/area/space) "ax" = (/obj/docking_port/stationary/transit{dir = 1; dwidth = 1; height = 4; id = "pod2_transit"; name = "pod 2 in transit"; width = 3},/turf/space/transit,/area/space) -"ay" = (/obj/vox/win_button,/turf/unsimulated/floor{tag = "icon-light_on"; icon_state = "light_on"},/area/vox_station) +"ay" = (/obj/vox/win_button,/turf/unsimulated/floor/vox{icon_state = "light_on"},/area/vox_station) "az" = (/obj/docking_port/stationary{dir = 1; dwidth = 1; height = 4; id = "pod1_away"; name = "recovery ship bay 1"; width = 3},/turf/space,/area/space) "aA" = (/obj/docking_port/stationary{dir = 1; dwidth = 1; height = 4; id = "pod2_away"; name = "recovery ship bay 2"; width = 3},/turf/space,/area/space) "aB" = (/obj/machinery/door/airlock/shuttle,/turf/simulated/shuttle/plating,/area/centcom/evac) @@ -32,11 +32,11 @@ "aF" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (WEST)"; icon_state = "fakewindows"; dir = 8},/area/vox_station) "aG" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows2 (WEST)"; icon_state = "fakewindows2"; dir = 8},/area/vox_station) "aH" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (EAST)"; icon_state = "fakewindows"; dir = 4},/area/vox_station) -"aI" = (/obj/machinery/door/airlock/centcom,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) -"aJ" = (/obj/structure/girder/displaced,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) -"aK" = (/obj/structure/closet/crate,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) +"aI" = (/obj/machinery/door/airlock/centcom,/turf/unsimulated/floor/vox,/area/vox_station) +"aJ" = (/obj/structure/girder/displaced,/turf/unsimulated/floor/vox,/area/vox_station) +"aK" = (/obj/structure/closet/crate,/turf/unsimulated/floor/vox,/area/vox_station) "aL" = (/obj/machinery/computer/shuttle/syndicate/recall,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) -"aM" = (/obj/structure/stool/bed/chair/comfy/red,/obj/effect/landmark{name = "voxstart"},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) +"aM" = (/obj/structure/stool/bed/chair/comfy/red,/obj/effect/landmark{name = "voxstart"},/turf/unsimulated/floor/vox,/area/vox_station) "aN" = (/turf/space,/area/space) "aO" = (/turf/unsimulated/wall{tag = "icon-iron6"; icon_state = "iron6"},/area/space) "aP" = (/obj/structure/window/reinforced,/turf/unsimulated/wall{tag = "icon-iron12"; icon_state = "iron12"},/area/space) @@ -57,11 +57,11 @@ "be" = (/obj/machinery/computer/shuttle/ert,/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops) "bf" = (/obj/machinery/door/airlock/external{id_tag = "specops_away"; name = "Shuttle Hatch"; req_access_txt = "109"},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/centcom/specops) "bg" = (/obj/docking_port/stationary{dir = 8; dwidth = 2; height = 11; id = "specops_away"; name = "centcom bay 3"; width = 5},/turf/space,/area/space) -"bh" = (/obj/structure/kitchenspike,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) -"bi" = (/obj/structure/table/woodentable,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) -"bj" = (/obj/item/weapon/stool,/obj/effect/landmark{name = "voxstart"},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vox_station) -"bk" = (/obj/machinery/door/airlock/centcom{opacity = 1},/turf/unsimulated/floor,/area/vox_station) -"bl" = (/turf/unsimulated/floor,/area/vox_station) +"bh" = (/obj/structure/kitchenspike,/turf/unsimulated/floor/vox,/area/vox_station) +"bi" = (/obj/structure/table/woodentable,/turf/unsimulated/floor/vox,/area/vox_station) +"bj" = (/obj/item/weapon/stool,/obj/effect/landmark{name = "voxstart"},/turf/unsimulated/floor/vox,/area/vox_station) +"bk" = (/obj/machinery/door/airlock/centcom{opacity = 1},/turf/unsimulated/floor/vox,/area/vox_station) +"bl" = (/turf/unsimulated/floor/plating/vox,/area/vox_station) "bm" = (/obj/docking_port/stationary/transit{dir = 2; dwidth = 2; height = 18; id = "skipjack_transit"; name = "skipjack in transit"; width = 19},/turf/space/transit,/area/space) "bn" = (/obj/docking_port/stationary{dir = 2; dwidth = 2; height = 18; id = "skipjack_away"; name = "vox bay 1"; width = 19},/turf/space,/area/space) "bo" = (/obj/docking_port/stationary/transit{dir = 8; dwidth = 3; height = 5; id = "mining_transit"; name = "mining in transit"; width = 7},/turf/space/transit,/area/space) @@ -440,11 +440,11 @@ "ix" = (/turf/unsimulated/floor{dir = 8; icon_state = "carpetside"},/area/wizard_station) "iy" = (/obj/effect/landmark/start{name = "wizard"},/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/wizard_station) "iz" = (/turf/unsimulated/floor{dir = 4; icon_state = "carpetside"},/area/wizard_station) -"iA" = (/turf/space,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite/mothership) -"iB" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_r (NORTH)"; icon_state = "propulsion_r"; dir = 1},/turf/space,/area/shuttle/syndicate_elite/mothership) -"iC" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion (NORTH)"; icon_state = "propulsion"; dir = 1},/turf/space,/area/shuttle/syndicate_elite/mothership) -"iD" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_l (NORTH)"; icon_state = "propulsion_l"; dir = 1},/turf/space,/area/shuttle/syndicate_elite/mothership) -"iE" = (/turf/space,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite/mothership) +"iA" = (/obj/docking_port/stationary/transit{dir = 8; dwidth = 3; height = 5; id = "sst_transit"; name = "sst in transit"; width = 11},/turf/space/transit,/area/space) +"iB" = (/obj/machinery/door/airlock/external{id_tag = "sst_away"; req_access_txt = "150"},/turf/unsimulated/floor{name = "plating"},/area/syndicate_mothership/elite_squad) +"iC" = (/obj/docking_port/stationary{dir = 8; dwidth = 3; height = 5; id = "sst_away"; name = "syndicate docking bay"; width = 11},/turf/space,/area/space) +"iD" = (/obj/item/weapon/gun/projectile/automatic/pistol/m1911,/obj/item/ammo_box/magazine/m45,/obj/item/ammo_box/magazine/m45,/obj/item/ammo_box/magazine/m45,/obj/structure/closet{icon_closed = "cabinet_closed"; icon_opened = "cabinet_open"; icon_state = "cabinet_closed"},/obj/item/clothing/head/helmet/space/deathsquad/beret,/obj/item/clothing/shoes/combat,/obj/item/clothing/under/syndicate/combat,/obj/item/clothing/gloves/combat,/obj/item/clothing/suit/space/deathsquad/officer,/obj/item/clothing/under/rank/centcom/captain,/obj/item/weapon/storage/box/handcuffs,/obj/item/weapon/storage/box/flashbangs,/obj/item/clothing/mask/gas,/obj/item/weapon/tank/emergency_oxygen/double,/obj/item/device/radio/headset/ert{pixel_x = 6; pixel_y = -6},/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops) +"iE" = (/turf/space,/turf/unsimulated/wall{dir = 1; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/space) "iF" = (/obj/machinery/door/airlock/centcom{aiControlDisabled = 1; name = "Assault Pod"; opacity = 1; req_one_access_txt = "150"},/turf/simulated/floor/plating,/area/shuttle/assault_pod) "iG" = (/obj/effect/decal/warning_stripes/southwest,/turf/simulated/floor/plating/airless,/area/syndicate_mothership) "iH" = (/turf/space,/obj/machinery/gun_turret/assault_pod,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/assault_pod) @@ -456,8 +456,8 @@ "iN" = (/obj/structure/table/woodentable,/obj/item/trash/tray,/obj/item/weapon/paper/spells,/turf/unsimulated/floor{dir = 10; icon_state = "carpetside"},/area/wizard_station) "iO" = (/turf/unsimulated/floor{dir = 2; icon_state = "carpetside"},/area/wizard_station) "iP" = (/obj/structure/table/woodentable,/obj/effect/landmark{name = "Teleport-Scroll"},/turf/unsimulated/floor{dir = 6; icon_state = "carpetside"},/area/wizard_station) -"iQ" = (/turf/simulated/shuttle/wall{dir = 4; icon_state = "wall3"},/area/shuttle/syndicate_elite/mothership) -"iR" = (/obj/structure/window/reinforced,/obj/structure/shuttle/engine/heater{tag = "icon-heater (NORTH)"; icon_state = "heater"; dir = 1},/turf/simulated/floor/plating/airless,/area/shuttle/syndicate_elite/mothership) +"iQ" = (/turf/space,/turf/unsimulated/wall{dir = 2; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/space) +"iR" = (/obj/structure/rack,/obj/item/device/radio/headset/heads/captain{pixel_x = 3; pixel_y = -3},/obj/item/device/radio/headset/syndicate,/obj/item/device/radio/headset/heads/ntrep{pixel_x = -3; pixel_y = 3},/obj/item/device/radio/headset/ert{pixel_x = 6; pixel_y = -6},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "iS" = (/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/assault_pod) "iT" = (/obj/effect/decal/warning_stripes/west,/turf/simulated/floor/plating/airless,/area/syndicate_mothership) "iU" = (/obj/structure/stool/bed/chair{dir = 1},/obj/machinery/light/small,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/assault_pod) @@ -471,7 +471,7 @@ "jc" = (/turf/simulated/floor/plasteel,/area/tdome/arena) "jd" = (/obj/structure/stool/bed/chair,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/wizard_station) "je" = (/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) -"jf" = (/obj/effect/landmark{name = "Syndicate-Commando-Bomb"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"jf" = (/obj/structure/rack,/obj/item/weapon/storage/belt/utility/full/multitool{pixel_x = -3; pixel_y = 3},/obj/item/weapon/storage/belt/military,/obj/item/weapon/storage/belt/military/assault{pixel_x = 3; pixel_y = -3},/obj/item/weapon/storage/belt/champion/wrestling,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "jg" = (/mob/living/silicon/decoy{icon_state = "ai-malf"; name = "GLaDOS"},/turf/unsimulated/floor{icon_state = "whiteshiny"},/area/syndicate_mothership/control) "jh" = (/obj/structure/window/reinforced{dir = 4},/obj/item/device/radio/intercom/syndicate,/turf/unsimulated/floor{icon_state = "circuit"},/area/syndicate_mothership) "ji" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/light/small{tag = "icon-bulb1 (WEST)"; icon_state = "bulb1"; dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/assault_pod) @@ -498,9 +498,9 @@ "jD" = (/obj/structure/table/woodentable,/obj/item/weapon/dice/d20,/obj/item/weapon/dice,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/wizard_station) "jE" = (/obj/structure/rack,/obj/item/clothing/suit/wizrobe/marisa,/obj/item/clothing/shoes/sandal/marisa,/obj/item/clothing/head/wizard/marisa,/obj/item/weapon/twohanded/staff/broom,/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) "jF" = (/obj/structure/rack,/obj/item/clothing/suit/wizrobe/magusblue,/obj/item/clothing/head/wizard/magus,/obj/item/weapon/twohanded/staff,/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) -"jG" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) -"jH" = (/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) -"jI" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"jG" = (/obj/structure/rack,/obj/item/weapon/storage/backpack/holding{pixel_x = -3; pixel_y = 3},/obj/item/weapon/storage/backpack/satchel,/obj/item/weapon/storage/backpack/holding{pixel_x = -6; pixel_y = 6},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"jH" = (/obj/structure/rack,/obj/item/weapon/implanter/adrenalin{pixel_x = 12; pixel_y = -12},/obj/item/weapon/implanter/emp{pixel_x = 9; pixel_y = -9},/obj/item/weapon/implanter/explosive{pixel_x = 6; pixel_y = -6},/obj/item/weapon/implanter/explosive_macro{pixel_x = 3; pixel_y = -3},/obj/item/weapon/implanter/freedom,/obj/item/weapon/implanter/krav_maga{pixel_x = -9; pixel_y = 9},/obj/item/weapon/implanter/loyalty{pixel_x = -6; pixel_y = 6},/obj/item/weapon/implanter/storage{pixel_x = -3; pixel_y = 3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"jI" = (/turf/space,/area/adminconstruction) "jJ" = (/obj/effect/decal/warning_stripes/north,/turf/simulated/floor/plating/airless,/area/syndicate_mothership) "jK" = (/obj/effect/decal/warning_stripes/north,/obj/machinery/light,/turf/simulated/floor/plating/airless,/area/syndicate_mothership) "jL" = (/obj/docking_port/stationary/transit{dwidth = 3; height = 7; id = "steel_rain_transit"; name = "steel_rain in transit"; width = 7},/turf/space/transit/horizontal,/area/space) @@ -525,7 +525,7 @@ "ke" = (/obj/structure/rack,/obj/item/clothing/suit/wizrobe/red,/obj/item/clothing/shoes/sandal,/obj/item/clothing/head/wizard/red,/obj/item/weapon/twohanded/staff,/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) "kf" = (/obj/machinery/light/spot,/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) "kg" = (/obj/structure/rack,/obj/item/clothing/suit/wizrobe/magusred,/obj/item/clothing/head/wizard/magus,/obj/item/weapon/twohanded/staff,/turf/unsimulated/floor{icon_state = "grimy"},/area/wizard_station) -"kh" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"kh" = (/obj/structure/rack,/obj/item/weapon/gun/energy/lasercannon,/obj/item/weapon/gun/energy/lasercannon{pixel_x = 6; pixel_y = -6},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "ki" = (/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/space,/area/syndicate_mothership/elite_squad) "kj" = (/turf/simulated/shuttle/wall{dir = 4; icon_state = "wall3"},/area/syndicate_mothership/elite_squad) "kk" = (/obj/machinery/computer/pod{id_tags = list("syndicate_elite"); name = "Hull Door Control"; req_access_txt = "150"},/turf/unsimulated/floor{icon_state = "dark"},/area/syndicate_mothership/elite_squad) @@ -575,9 +575,9 @@ "lc" = (/obj/structure/table/reinforced,/obj/structure/kitchenspike,/turf/unsimulated/floor{dir = 4; icon_state = "chapel"},/area/wizard_station) "ld" = (/obj/structure/table/reinforced,/obj/structure/kitchenspike,/turf/unsimulated/floor{dir = 1; icon_state = "chapel"},/area/wizard_station) "le" = (/obj/effect/decal/cleanable/cobweb2,/obj/structure/showcase,/turf/unsimulated/floor{dir = 4; icon_state = "chapel"},/area/wizard_station) -"lf" = (/obj/machinery/door/airlock/external{name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "syndicate_elite"; name = "Side Hull Door"; opacity = 0},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"lf" = (/obj/structure/rack,/obj/item/weapon/gun/energy/laser/instakill/blue{pixel_x = 3; pixel_y = -3},/obj/item/weapon/gun/energy/laser/instakill/red{pixel_x = -3; pixel_y = 3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "lg" = (/turf/unsimulated/floor{name = "plating"},/area/syndicate_mothership/elite_squad) -"lh" = (/obj/machinery/door/airlock/external{req_access_txt = "150"},/turf/unsimulated/floor{name = "plating"},/area/syndicate_mothership/elite_squad) +"lh" = (/obj/machinery/computer/card/centcom,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "li" = (/turf/unsimulated/wall/abductor{icon_state = "alien7"},/area/abductor_ship) "lj" = (/obj/structure/stool/bed/abductor,/turf/unsimulated/floor/abductor,/area/abductor_ship) "lk" = (/obj/structure/table/abductor,/obj/item/weapon/surgicaldrill/alien,/obj/item/weapon/circular_saw/alien,/turf/unsimulated/floor/abductor,/area/abductor_ship) @@ -591,8 +591,8 @@ "ls" = (/obj/effect/decal/cleanable/blood,/turf/unsimulated/floor{icon_state = "chapel"},/area/wizard_station) "lt" = (/mob/living/carbon/human/monkey,/turf/unsimulated/floor{dir = 8; icon_state = "chapel"},/area/wizard_station) "lu" = (/turf/unsimulated/floor{icon_state = "chapel"},/area/wizard_station) -"lv" = (/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) -"lw" = (/obj/machinery/door/airlock/external{name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "syndicate_elite"; name = "Side Hull Door"; opacity = 0; req_access_txt = "150"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"lv" = (/obj/structure/stool/bed/chair/comfy/black{dir = 1},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"lw" = (/obj/structure/stool/bed/chair/comfy/black{dir = 8},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "lx" = (/obj/machinery/door/airlock/glass_security{name = "Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{id_tag = "syndicate_elite_mech_room"; name = "Mech Room Door"},/turf/unsimulated/floor{icon_state = "dark"},/area/syndicate_mothership/elite_squad) "ly" = (/turf/unsimulated/wall/abductor,/area/abductor_ship) "lz" = (/turf/unsimulated/wall/abductor{icon_state = "alien4"},/area/abductor_ship) @@ -605,8 +605,8 @@ "lG" = (/mob/living/simple_animal/hostile/creature{name = "Experiment 35b"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/wizard_station) "lH" = (/turf/unsimulated/floor{dir = 1; icon_state = "chapel"},/area/wizard_station) "lI" = (/turf/unsimulated/floor{dir = 4; icon_state = "chapel"},/area/wizard_station) -"lJ" = (/obj/machinery/computer/pod{id_tags = list("syndicate_elite"); name = "Hull Door Control"; req_access_txt = "150"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) -"lK" = (/obj/machinery/computer/syndicate_elite_shuttle,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate_elite/mothership) +"lJ" = (/obj/structure/stool/bed/chair/comfy/black,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"lK" = (/obj/structure/rack,/obj/item/weapon/storage/box/syndie_kit/hardsuit,/obj/item/weapon/storage/box/syndie_kit/elite_hardsuit{pixel_x = -6; pixel_y = 6},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "lL" = (/obj/machinery/abductor/experiment{team = 2},/turf/unsimulated/floor/abductor,/area/abductor_ship) "lM" = (/obj/machinery/abductor/pad{team = 2},/turf/unsimulated/floor/abductor,/area/abductor_ship) "lN" = (/obj/machinery/abductor/console{team = 2},/turf/unsimulated/floor/abductor,/area/abductor_ship) @@ -628,10 +628,6 @@ "md" = (/obj/machinery/computer/mech_bay_power_console,/obj/structure/cable,/turf/simulated/floor/plasteel,/area/shuttle/gamma/space) "me" = (/obj/effect/decal/cleanable/blood,/turf/unsimulated/floor{dir = 8; icon_state = "chapel"},/area/wizard_station) "mf" = (/obj/structure/stool,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) -"mg" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite/mothership) -"mh" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/syndicate_elite/mothership) -"mi" = (/obj/machinery/door/airlock/external{name = "Shuttle Airlock"; req_access_txt = "150"},/obj/machinery/door/poddoor{icon_state = "pdoor1"; id_tag = "syndicate_elite"; name = "Front Hull Door"; opacity = 1},/turf/simulated/shuttle/plating,/area/shuttle/syndicate_elite/mothership) -"mj" = (/turf/space,/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite/mothership) "mk" = (/obj/structure/stool,/obj/effect/landmark{name = "Syndicate-Spawn"},/obj/effect/decal/warning_stripes/east,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "ml" = (/obj/structure/stool,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/syndicate_mothership) "mm" = (/obj/structure/stool,/obj/structure/sign/poster/legit{pixel_y = 32},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) @@ -640,7 +636,6 @@ "mp" = (/obj/structure/stool,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "mq" = (/obj/structure/stool,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/centcom/evac) "mr" = (/turf/unsimulated/wall,/area/trader_station/sol) -"ms" = (/turf/simulated/floor/plating/airless,/area/shuttle/syndicate_elite/mothership) "mt" = (/turf/space,/area/syndicate_mothership/elite_squad) "mu" = (/obj/effect/landmark{name = "Syndicate-Commando"; tag = "Commando"},/obj/machinery/light/spot,/turf/unsimulated/floor{icon_state = "dark"},/area/syndicate_mothership/elite_squad) "mv" = (/obj/machinery/light/spot,/turf/unsimulated/floor{icon_state = "dark"},/area/syndicate_mothership) @@ -952,7 +947,6 @@ "wc" = (/turf/unsimulated/floor{tag = "icon-warning (NORTHWEST)"; icon_state = "warning"; dir = 9},/area/centcom/specops) "wd" = (/turf/unsimulated/floor{dir = 5; icon_state = "warning"},/area/centcom/specops) "we" = (/turf/space,/area/centcom/specops) -"wf" = (/obj/item/weapon/gun/projectile/automatic/pistol/m1911,/obj/item/ammo_box/magazine/m45,/obj/item/ammo_box/magazine/m45,/obj/item/ammo_box/magazine/m45,/obj/structure/closet{icon_closed = "cabinet_closed"; icon_opened = "cabinet_open"; icon_state = "cabinet_closed"},/obj/item/clothing/head/helmet/space/deathsquad/beret,/obj/item/clothing/shoes/combat,/obj/item/clothing/under/syndicate/combat,/obj/item/clothing/gloves/combat,/obj/item/clothing/suit/space/deathsquad/officer,/obj/item/clothing/under/rank/centcom/captain,/obj/item/weapon/storage/box/handcuffs,/obj/item/weapon/storage/box/flashbangs,/obj/item/clothing/mask/gas,/obj/item/weapon/tank/emergency_oxygen/double,/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops) "wg" = (/obj/machinery/telecomms/relay/preset/centcom,/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops) "wh" = (/obj/machinery/recharge_station/upgraded,/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops) "wi" = (/turf/unsimulated/wall{icon = 'icons/obj/library.dmi'; icon_state = "book-5"; name = "bookcase (Tactics)"},/area/centcom/specops) @@ -1153,7 +1147,6 @@ "Ex" = (/obj/structure/table,/obj/item/weapon/storage/box/beakers,/obj/item/weapon/reagent_containers/glass/beaker/bluespace,/obj/item/weapon/reagent_containers/glass/beaker/bluespace,/obj/item/weapon/reagent_containers/glass/beaker/bluespace,/obj/item/weapon/reagent_containers/glass/beaker/bluespace,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) "Ey" = (/obj/structure/table,/obj/machinery/reagentgrinder,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) "Ez" = (/obj/structure/table,/obj/item/weapon/storage/pill_bottle/random_drug_bottle,/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) -"EA" = (/turf/space,/turf/unsimulated/wall{dir = 1; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/adminconstruction) "EB" = (/obj/machinery/door/airlock/external,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "ADMINLOCKDOWN"; name = "Security Doors"; opacity = 0},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "EC" = (/obj/machinery/door/airlock/hatch{name = "External Airlock"; req_access_txt = "0"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "ED" = (/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5_end (WEST)"},/area/admin) @@ -1243,7 +1236,6 @@ "Gk" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{dir = 2; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5"; name = "window"; opacity = 0; tag = "icon-window5"},/area/admin) "Gl" = (/obj/structure/stool/bed/chair/comfy/black,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin) "Gm" = (/obj/machinery/computer/card,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"Gn" = (/obj/structure/stool/bed/chair{dir = 1},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Go" = (/obj/machinery/door/airlock/glass{name = "Computer Hub"; req_access_txt = "0"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "ADMINLOCKDOWN"; name = "Security Doors"; opacity = 0},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Gp" = (/obj/effect/landmark{name = "aroomwarp"; tag = ""},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Gq" = (/obj/machinery/door/airlock/hatch{desc = "For all your shady business needs"; name = "Gambling Den"; req_access_txt = "0"},/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin) @@ -1252,12 +1244,10 @@ "Gt" = (/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/devilskiss,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin) "Gu" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5_end (WEST)"},/area/admin) "Gv" = (/obj/machinery/computer/artillerycontrol{luminosity = 255},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"Gw" = (/obj/structure/stool/bed/chair{dir = 8},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Gx" = (/obj/item/weapon/stool,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin) "Gy" = (/obj/structure/table/woodentable,/obj/item/weapon/lighter/zippo/engraved,/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin) "Gz" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 4; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5 (EAST)"},/area/admin) "GA" = (/obj/machinery/computer/communications,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"GB" = (/obj/structure/stool/bed/chair,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "GC" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{dir = 1; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/admin) "GD" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/admin) "GE" = (/obj/machinery/computer/message_monitor,/obj/item/weapon/paper/monitorkey,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) @@ -1386,44 +1376,44 @@ ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaN ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdkdjdjdjdlbsbqbEbqbqbFbsbGbHbGbHbGbsbIbIbIbIbIbsbxbJbxbJbxbsbybybybybybsbzbKbzbKbzbsbLbMbMbMbNbD ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdkdjdjdjdlbsbqbObqbqbqbsbPbQbPbQbPbsbIbIbIbIbIbsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsbLbMbMbMbNbD ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdkdjdjdjdlbsbqbqbRbSbqbsbTbTbTbTbTbsbUbUbUbUbVbsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsbLbMbMbMbNbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdndmdmdmdrbscabqbqbqbqbscbcccdcccebscfcgchcicfbsbxbxbJbxbxbsbybybybybybsbzbzbzbzbzbsbLbMbMbMbNbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdxdvdvdvdybsbqcabqbqctbscucccdcccvbscfcwcxcycfbsbxbxbJbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcRcScTcocScUcocScVcocWcXcocScUcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqbEcabqbRbsbTbTbTbTbTbsdbcwcxcydbbsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcododpcodocXcododqcodocUcodocTcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqbqbqcabqbsdsdtdsdtdsbsducwcxcydubsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapaparapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqdGbqbqcabsbGbHbGbHbGbsducwcxcydubsbxbJbxbJbxbsbybybybybybsbzbKbzbKbzbsczbMbMbMcAbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcocSdpcodKcTcocScTcodLcUcocScXcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdCdBdBdBdDbsbRbqdNbqbEbsbtbubtbubtbsdOdPdQdRdObsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsdSdTdTdTdUbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcodocTcodocUcodocUcodoedcodoeecoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNhyhzhzhzhzhzbZejejejejejbZejejejejejbZejejejejejbZekekekekekbZekekekekekbZekekekekekbZekekekekekel -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeqbserererererbseseseteueubsevevevevevbsewexexexeybsezeAeAeAeBbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckbockckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbseqeDeqeqeqbsereEeFeGerbseHeHeIeJeJbseveKeveLevbseMeNeNeNeObsePeQeQeQeRbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapavapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqeqeqeXeqbsereYeYeYerbseHeZeZeZeJbsevevevevevbseMeNeNeNeObsePeQeQeQeRbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfffffffffffgfgfhfififjfgfgfgfgfgfgfgfgfgfkfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeqbserererererbseHeIeIeIeJbsevevevevevbseMeNeNeNeObsePeQeQeQeRbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNftfufvfwfffgfxfyfzfAfAfBfCfDdJdMfGfHfIfHfHfJfKfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbseqeqeqfMeqbserfNfOfPerbsfQfRfRfRfSbsevfTevevevbsfUfVfVfVfWbsePeQeQeQeRbD -ckckckckckckckclckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfffffffufufufffggbfyfyfyfyfygcgdgdgdgefHfHfHgffHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqgkeqeqeqbserglgmgnerbsgogpgpgpgqbsevevevgrevbsgsgtgtgtgubsgveQeQeQgwbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNgygzgAfufufufffggBfygCgDgEgFgGgdgdgdgdfHfHgHfHgIfIfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeDbserglgmgnerbsgJeIgKeIgLbsevevevevevbsgMeNeNeNgNbsgveQeQeQgwbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckcmckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNgOgPgQfufufufffggRgdgegegegegegdgdgdgdfHfHfHgSfHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbsgTeqeqeqeqbserglgmgnerbsgJgUgUgUgLbsgVgVgVgVgVbsgMeNeNeNgNbsgveQeQeQgwbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfffffffffffffffggWgdgdgdgdgdgdgdgdgdgdgXfHfHfHfHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqfMeqgkeqbsergYgZhaerbsgJgJeIgLgLbshbhbhbhbhbbsgMeNeNeNgNbsgveQeQeQgwbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfggWgdgdgdgdgdhcgdgdhcgdhdhehehehfhefgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqgTbserererererbshhhhhihjhjbshkhkhkhkhkbshlhmhmhmhnbshohphphphqbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfghrgdgdgdgdgehshtgehsgehuhvhvhvhwhvfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNhyhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhB -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfgfghChDhDhCfgfgfgfgfgfgfgfgfgfgfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfghEhFhFhFfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZaPaPaPaPaPbZaPaPaPaPaPbZaPaPaPaPaPbZ -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfghFhFhFhFfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphHhIhJhKhLbshMhNhOhPhQbshRhShThUhVbD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNfgfgfgfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphWhWhXhWhWbshYhZhZhZhYbsiaiaiaiaiabD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphWhWhWhWhWbshYhZhZhZhYbsiaiaiaiaiabD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpibichWicibbshYidhZidhYbsieifiaigiebD -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZhzhzhzhzhzbZhzhzhzhzhzbZhzhzhzhzhzbZ -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatatatatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdndmdmdmdrbscabqbqbqbqbscbcccdcccebscfcgchcicfbsbxbxbJbxbxbsbybybybybybsbzbzbzbzbzbsbLbMbMbMbNbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdxdvdvdvdybsbqcabqbqctbscucccdcccvbscfcwcxcycfbsbxbxbJbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcRcScTcocScUcocScVcocWcXcocScUcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqbEcabqbRbsbTbTbTbTbTbsdbcwcxcydbbsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcododpcodocXcododqcodocUcodocTcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqbqbqcabqbsdsdtdsdtdsbsducwcxcydubsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsczbMbMbMcAbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapaparapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdzdjdjdjdAbsbqdGbqbqcabsbGbHbGbHbGbsducwcxcydubsbxbJbxbJbxbsbybybybybybsbzbKbzbKbzbsczbMbMbMcAbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcocSdpcodKcTcocScTcodLcUcocScXcoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpdCdBdBdBdDbsbRbqdNbqbEbsbtbubtbubtbsdOdPdQdRdObsbxbxbxbxbxbsbybybybybybsbzbzbzbzbzbsdSdTdTdTdUbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcodocTcodocUcodocUcodoedcodoeecoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNhyhzhzhzhzhzbZejejejejejbZejejejejejbZejejejejejbZekekekekekbZekekekekekbZekekekekekbZekekekekekel +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNcocococococococococococococococoaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeqbserererererbseseseteueubsevevevevevbsewexexexeybsezeAeAeAeBbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckbockckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbseqeDeqeqeqbsereEeFeGerbseHeHeIeJeJbseveKeveLevbseMeNeNeNeObsePeQeQeQeRbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapavapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqeqeqeXeqbsereYeYeYerbseHeZeZeZeJbsevevevevevbseMeNeNeNeObsePeQeQeQeRbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNfffffffffffgfgfhfififjfgfgfgfgfgfgfgfgfgfkfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeqbserererererbseHeIeIeIeJbsevevevevevbseMeNeNeNeObsePeQeQeQeRbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNftfufvfwfffgfxfyfzfAfAfBfCfDdJdMfGfHfIfHfHfJfKfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbseqeqeqfMeqbserfNfOfPerbsfQfRfRfRfSbsevfTevevevbsfUfVfVfVfWbsePeQeQeQeRbD +ckckckckckckckclckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNfffffffufufufffggbfyfyfyfyfygcgdgdgdgefHfHfHgffHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqgkeqeqeqbserglgmgnerbsgogpgpgpgqbsevevevgrevbsgsgtgtgtgubsgveQeQeQgwbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNgygzgAfufufufffggBfygCgDgEgFgGgdgdgdgdfHfHgHfHgIfIfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqeDbserglgmgnerbsgJeIgKeIgLbsevevevevevbsgMeNeNeNgNbsgveQeQeQgwbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckcmckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNgOgPgQfufufufffggRgdgegegegegegdgdgdgdfHfHfHgSfHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeoepeneoepbsgTeqeqeqeqbserglgmgnerbsgJgUgUgUgLbsgVgVgVgVgVbsgMeNeNeNgNbsgveQeQeQgwbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckiAckckckckckckckckckaNaNaNaNaNfffffffffffffffggWgdgdgdgdgdgdgdgdgdgdgXfHfHfHfHfHfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpepeneoepenbseqfMeqgkeqbsergYgZhaerbsgJgJeIgLgLbshbhbhbhbhbbsgMeNeNeNgNbsgveQeQeQgwbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNfggWgdgdgdgdgdhcgdgdhcgdhdhehehehfhefgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpeneoepeneobseqeqeqeqgTbserererererbshhhhhihjhjbshkhkhkhkhkbshlhmhmhmhnbshohphphphqbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNfghrgdgdgdgdgehshtgehsgehuhvhvhvhwhvfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNhyhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhAhzhzhzhzhzhB +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNapapapapapapapapapapapapapapapapapapapapapapapapaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNfgfghChDhDhCfgfgfgfgfgfgfgfgfgfgfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNfghEhFhFhFfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZaPaPaPaPaPbZaPaPaPaPaPbZaPaPaPaPaPbZ +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNfghFhFhFhFfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphHhIhJhKhLbshMhNhOhPhQbshRhShThUhVbD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNfgfgfgfgfgfgaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphWhWhXhWhWbshYhZhZhZhYbsiaiaiaiaiabD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbphWhWhWhWhWbshYhZhZhZhYbsiaiaiaiaiabD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbpibichWicibbshYidhZidhYbsieifiaigiebD +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZhzhzhzhzhzbZhzhzhzhzhzbZhzhzhzhzhzbZ +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatatatatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihiiijikiliminihioipiqihaNaNirisisisisisitaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauauataNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikikikikixiyizihaNaNisiAiBiCiDiEitaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauayauataNaNaNaNaNaNaNaNaNaNaNbZdEdEdEdEdEbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZdFdFdFdFdFbZaNaNaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihiLiLikikikiMihiNiOiPihaNaNisiQiRiRiRiQititititaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauauataNaNaNaNaNaNaNaNaNbZbZbZiZiZiZiZiZjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaiZiZiZiZiZbZbZbZaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikjdjdihihjeihihaNaNisiQjfjfjfiQitjgjhitaNaNaNaNaNaNaNaNaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmxmwatatatatataFaGaGaGaGaGaGaGaHatataIatataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihjAjAikjBjCjDihjEjejFihaNaNisiQjGjHjIiQititititititititititititaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmzmyataJaJaJaKauauauauauauauauaKaKaKauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkbikikjBkckdihkekfkgihaNaNisiQkhjHjIiQkikjkkklkmknkjkokpkqkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmBmAataKauauauauauauauaMauauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkCkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkJikikikikihihihihihihaNaNisiQkhjHjIiQkKkjknknkLknkjknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNmDmCmFmEatbhauauauauauaubibibiauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkTkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkWkXkYkZiklalblcldleihaNaNisiQjHjHjHlflglhknknkLknkjkokpkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmGmEatbhauauauauaubjbibibibjauauauauauaKataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlolplqikikiklrlsltluihaNaNisiQlvjHjHlwlglhknknknknlxknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmEmEatbhauauauauauaubjbjbjauauauauauauauataNaNaNaNaNaNaNaNaNbZbZbZlBlBlBlBlBlClDjpjpjpjpjpjplEjpjpjpjpjpjplDlClBlBlBlBlBbZbZbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlGlplqikikiklHlIlHlIihaNaNisiQlJjHlKiQkKkjknknkLknkjkokpkrkrksaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmEmEatauauauauauauauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZlWlWlWlWlWbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZlXlXlXlXlXbZaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlomambkJmcladclumeddihaNaNismgmhmimhmjkikjknknkLknkjknkrkrkrksaNaNaNaNaNaNmHmEmEmEmImEmEmEmEmEmJatauauaKaJaJaKauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNisaNmgmsmjaNmtkjknknmuknkjkokpmvkrksaNaNaNaNaNaNmKmEmLmNmMmOmOmMmEmQmPatatbkatatatatatatatatatatatatatbkatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikikikikixiyizihaNaNisaNaNaNaNaNitaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauayauataNaNaNaNaNaNaNaNaNaNaNbZdEdEdEdEdEbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZdFdFdFdFdFbZaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihiLiLikikikiMihiNiOiPihaNaNisaNaNaNaNaNititititaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauauataNaNaNaNaNaNaNaNaNbZbZbZiZiZiZiZiZjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaiZiZiZiZiZbZbZbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikjdjdihihjeihihaNaNisaNaNaNaNaNitjgjhitaNaNaNaNaNaNaNaNaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmxmwatatatatataFaGaGaGaGaGaGaGaHatataIatataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihjAjAikjBjCjDihjEjejFihaNaNisaNaNaNaNaNititititititititititititaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmzmyataJaJaJaKauauauauauauauauaKaKaKauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkbikikjBkckdihkekfkgihaNaNisaNaNaNaNaNkikjkkklkmknkjkokpkqkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmBmAataKauauauauauauauaMauauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkCkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkJikikikikihihihihihihaNaNisaNaNaNaNaNkKkjknknkLknkjknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNmDmCmFmEatbhauauauauauaubibibiauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkTkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkWkXkYkZiklalblcldleihaNaNisaNaNaNaNaNlgiBknknkLknkjkokpkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmGmEatbhauauauauaubjbibibibjauauauauauaKataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlolplqikikiklrlsltluihaNaNisaNaNaNaNiClgiBknknknknlxknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmEmEatbhauauauauauaubjbjbjauauauauauauauataNaNaNaNaNaNaNaNaNbZbZbZlBlBlBlBlBlClDjpjpjpjpjpjplEjpjpjpjpjpjplDlClBlBlBlBlBbZbZbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlGlplqikikiklHlIlHlIihaNaNisaNaNaNaNaNkKkjknknkLknkjkokpkrkrksaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmEmEatauauauauauauauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZlWlWlWlWlWbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZlXlXlXlXlXbZaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlomambkJmcladclumeddihaNaNisaNaNaNaNaNkikjknknkLknkjknkrkrkrksaNaNaNaNaNaNmHmEmEmEmImEmEmEmEmEmJatauauaKaJaJaKauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNisaNaNaNaNaNmtkjknknmuknkjkokpmvkrksaNaNaNaNaNaNmKmEmLmNmMmOmOmMmEmQmPatatbkatatatatatatatatatatatatatbkatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNititititititititititititititititititaNaNaNaNaNaNmKmEmEmEmEmEmEmEmEmQmRatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckbmckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNmKmEmMmOmOmOmSmMmEmEmTatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckaackckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNmUmVmEmEmEmEmEmEmEmEatatblblatatatatatatatatatatatatatblblatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1526,7 +1516,7 @@ aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXvkvkvkvxujujujvyvyujujujvzvdvAvBvCbesXvEtTuEtRtRvFtRtRtZsqsqsusususususqsqtQtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXvGvHsXvIvJujujujujvLujsXvdvMvNvOvPsXvQtRtRtRtZsutQtRtStTtTtTtTtTtTtTtTtTuEtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXbfbfsXsXsXvSvTvUvVvdsXvWtRtRtRvXsutQtRtRtRtRtRtRtRtRtRtRtRtRtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwbwcwdwbwesXwfwgwhwiwjsXwkudududwlsuwmudududududuetRucudududududwnsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwbwcwdwbwesXiDwgwhwiwjsXwkudududwlsuwmudududududuetRucudududududwnsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwrwswtwrwesXsXsXsXsXsXsXsqsqsqsqsqsqsqsqsqsqsqsqsqwusqsqsqsqsqsqsqsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwCwDwEwFwGwCwHwIwJwKwLwMwNwOwPwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwCwCwCwIwIwIwIwIwIwKxcxdxexdxfwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1580,34 +1570,34 @@ aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbW aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtaNaNaNaNaNDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDtDwDxDyDyDyDzDwDuDvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDADBDCDDDEDFDGDHDADuaNaNaNaNaNaNDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDJDKDKDKDKDKDLDADwDMDwDMDwDMDwDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDODKDPcQDRDKDSDADTDKDUDKDVDWDXDYDADuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDZDKEaEbEcDKEdDADKDKDKDKDKDKDKEeDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfEgEhDKDKDKEhEiDAEjDKEkDKElDWDXDYEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwDKDKDKDwDwDADKDKDKDKDKDKDKEmDAEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDtDwDxDyDyDyDzDwiEaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDADBDCDDDEDFDGDHDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDJDKDKDKDKDKDLDADuaNaNaNaNaNaNDvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDODKDPcQDRDKDSDADwDMDwDMDwDMDwDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDZDKDKDKDKDKEdDADTDKDUDKDVDWDXDYDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfEgDKEaEbEcDKEiDADKDKDKDKDKDKDKEeDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNiQDAiRDKDKDKDKDKjfDAEjDKEkDKElDWDXDYEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAjGEhDKDKDKEhjHDADKDKDKDKDKDKDKEmDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDuaNDADwDwDMEoDMDwDwDwDwDwDMEpDMDwDwDwEnaNDtDwEqErErEsDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwEtDKDKDKDKDKDKDKDKDKDKDKDKEuDAEnaNDtDwEvEwExEyEwEzDwEAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwEtDKDKDKDKDKDKDKDKDKDKDKDKEuDAEnaNDvDwEvEwExEyEwEzDwjIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEBDKECDKDKDKDKDKDKDKDKDKDKDKDKDKDKDAaNaNaNEDEEEFEwEwEwEGEDaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWnnbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwDwDwDwDMEHDMDwDwDwDwDwEIDKDKDAaNaNaNEJEKEwEwEwEwELEJaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEnaNEMDAENEOEPDKDKEQERESETEuDADKDKDAaNaNDtDAEUEwEVEWEwEXDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEnaNEMDAENEOEPDKDKEQERESETEuDADKDKDAiEaNDtDAEUEwEVEWEwEXDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWjLbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKDKDKDKDKDKDKEYDKDKDADwEZDwDwDwFaDwDwFaDwDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFbFcFdDKDKDKFeFeFeDKEHDKDKDAFfEwEwdfDADKDAFhFiFjDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKDKFkDwDwDwDwDADKDKDAEwEwFlFmDADKDAFnFoFpDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKkhFkDwDwDwDwDADKDKDAEwEwFlFmDADKDAFnFoFpDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFqFrFsDKFtDAFuFvFwFxDADKDKDAFyEwEwFzDADKDAFAFBFCDNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKFDDAFEFvFvFvFFDKDKDAFGEwEwFHDADKDKDKDKDKEfaNaNaNaNDtDwFIFJFKDwDuaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYlfDKDKDKFDDAFEFvFvFvFFDKDKDAFGEwEwFHDADKDKDKDKDKEfaNaNaNaNDtDwFIFJFKDwDuaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFMFNFODKFPDAFQFvFRFSDADKDKDAFTFUEwEwFVDKDKDKDKDKDAaNaNaNDtDwFWFXFXFXFYDwDuaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwDwDwDwDwDwDwDwGaDKDKGbDwDwDwDwDwDwDwDwGcDwDADuaNDtDwFWFXFXFXFXFXFYDADuaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDAGdGeGfGgGhGiGjGbDAGaDKDKDKDKDKDKGbDwDwDwDwDwGaDKGbDwDwGkDwFWFXFXFXGlFXFXFXFYDAaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIGmDKDKGnDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXFXGrGsGtFXFXFXGuaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNGvGwDKDKDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXGxGyGrGrGxFXFXGzaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfGADKDKGBDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKFkDwDwGkDwGCFXFXGxGxGxFXFXGDDAaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDAGEGFGGGHGIGJGKFkDAEIDKDKDKDKDKDKFkDwDwEIDKFkDwDwDwDAEnaNEMDwGCFXFXFXFXFXGDDAEnaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDwDwDwDwDwDwDwDwDwEIDKDKFkDwDwDwDwDwGLDwDwDwDADAaNaNaNEMDwGCFXFXFXGDDwEnaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMaNaNaNaNaNaNaNaNaNDvDAGMGMDAaNDAFvGNFvFvFvGNFvDADAaNaNaNaNEMDwFIFJFKDwEnaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwDwDwDwDwDwDwDwDwGaDKDKGbDwDwDwDwDwDwDwDwGcDwDADuaNDtDwFWFXFXFXFXFXFYDADuaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDAGaGdGeGfGgGhGiGjGbDAGaDKDKDKDKDKDKGbDwDwDwDwDwGaDKGbDwDwGkDwFWFXFXFXGlFXFXFXFYDAaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIGmlhDKDKlvDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXFXGrGsGtFXFXFXGuaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDKlwDKDKDKDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXGxGyGrGrGxFXFXGzaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfGAGvDKDKlJDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKFkDwDwGkDwGCFXFXGxGxGxFXFXGDDAaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDAEIGEGFGGGHGIGJGKFkDAEIDKDKDKDKDKDKFkDwDwEIDKFkDwDwDwDAEnaNEMDwGCFXFXFXFXFXGDDAEnaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDwDwDwDwDwDwDwDwDwDwEIDKDKFkDwDwDwDwDwGLDwDwDwDADAaNaNaNEMDwGCFXFXFXGDDwEnaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDAGMGMDAaNDAFvGNFvFvFvGNFvDADAaNaNaNaNEMDwFIFJFKDwEnaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwGaDKDKDAaNDAGOFvFvGPFvFvGQDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKDKDKDKDAaNDAGRGPFvFvFvGPGSDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfDKDKDKDKDKDKDKDAaNDAGTFvFvGPFvFvGUDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1624,7 +1614,7 @@ aNaNaNaNaNaNHjdHdHdHdHdHHjIdIeIeIeIeIeIeIeIeIeIeIeIeIeIfHjdIdIdIdIdIHjaNaNaNaNaN aNaNaNaNHjHjHjIhIhIhIhIhjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaIhIhIhIhIhHjHjHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNjUjWlLlNlMkajZaNjUjWlOlQlPkajZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfDKDKDKDKDKDKFkDAEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIkIkIkIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIoIoIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkwlRkxkxkxkAkzaNkwlSkxkxkxkAkzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDMIqDMDwDwEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIrIkIrIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIsIoIsIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkEkGlTkIlUkNkMaNkEkGlVkIlYkNkMaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAItDKDKDKIuDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNHjIiIjIkIkIvIkIkIlImjcjcjcjcjcIwIxIwjcjcjcjcjcInIlIoIoIyIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkQkRkxkxkxkAkSaNkQkRkxkxkxkAkSaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKDKDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNHjIiIjIkIkIvIkIkIlImjcjcjcjcjcIwIxIwjcjcjcjcjcInIlIoIoIyIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkQkRkxkxkxkAkSaNkQkRkxkxkxkAkSaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKlKDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIrIkIrIkIlImjcjcjcjcjcIwIzIwjcjcjcjcjcInIlIoIsIoIsIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkUlikVlkljlmllaNkUlikVlkljlmllaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNIADKDKDKIBDNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIkIkIkIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIoIoIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNlylnlAlzlFaNaNaNlylnlAlzlFaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfICDKDKDKIDEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjHjHjIEIEIEIEIEjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaIEIEIEIEIEHjHjHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwIFIGIHIIIJDwEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN diff --git a/code/__DEFINES/error_handler.dm b/code/__DEFINES/error_handler.dm new file mode 100644 index 00000000000..0c98f4a9b9f --- /dev/null +++ b/code/__DEFINES/error_handler.dm @@ -0,0 +1,9 @@ +// Settings for the error handler and error viewer + +#define ERROR_COOLDOWN 600 // The "cooldown" time for each occurrence of a unique error +#define ERROR_LIMIT 9 // How many occurrences before the next will silence them +#define ERROR_MAX_COOLDOWN (ERROR_COOLDOWN * ERROR_LIMIT) +#define ERROR_SILENCE_TIME 6000 // How long a unique error will be silenced for + +// How long to wait between messaging admins about occurrences of a unique error +#define ERROR_MSG_DELAY 50 diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index f57e096e0ec..915cb8816e8 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -62,11 +62,12 @@ #define HAS_TAIL 16 #define TAIL_OVERLAPPED 32 #define HAS_SKIN_TONE 64 -#define HAS_SKIN_COLOR 128 -#define HAS_MARKINGS 256 -#define TAIL_WAGGING 512 -#define NO_EYES 1024 -#define HAS_FUR 2048 +#define HAS_ICON_SKIN_TONE 128 +#define HAS_SKIN_COLOR 256 +#define HAS_MARKINGS 512 +#define TAIL_WAGGING 1024 +#define NO_EYES 2048 +#define HAS_FUR 4096 //Species Diet Flags #define DIET_CARN 1 diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 36bb824e642..a8c548bdd7a 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -46,6 +46,14 @@ if(S.flags & IS_WHITELISTED) whitelisted_species += S.name + paths = subtypesof(/datum/emote) + for(var/T in paths) + var/datum/emote/E = new T + if(istype(T, /datum/emote/custom)) + continue + emotes += E + + init_subtypes(/datum/table_recipe, table_recipes) return 1 diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index 09830792201..5d2427603c7 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -91,4 +91,23 @@ */ /proc/log_startup_progress(var/message) to_chat(world, "[message]") - log_to_dd(message) \ No newline at end of file + log_to_dd(message) + +// Helper procs for building detailed log lines + +/proc/datum_info_line(var/datum/d) + if(!istype(d)) + return + if(!istype(d, /mob)) + return "[d] ([d.type])" + var/mob/m = d + return "[m] ([m.ckey]) ([m.type])" + +/proc/atom_loc_line(var/atom/a) + if(!istype(a)) + return + var/turf/t = get_turf(a) + if(istype(t)) + return "[a.loc] ([t.x],[t.y],[t.z]) ([a.loc.type])" + else if(a.loc) + return "[a.loc] (0,0,0) ([a.loc.type])" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 3d1648fa77a..9657f867b5a 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -100,27 +100,42 @@ proc/random_name(gender, species = "Human") else return current_species.get_random_name(gender) -proc/random_skin_tone() - switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino")) - if("caucasian") . = -10 - if("afroamerican") . = -115 - if("african") . = -165 - if("latino") . = -55 - if("albino") . = 34 - else . = rand(-185,34) - return min(max( .+rand(-25, 25), -185),34) +proc/random_skin_tone(species = "Human") + if(species == "Human" || species == "Drask") + switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino")) + if("caucasian") . = -10 + if("afroamerican") . = -115 + if("african") . = -165 + if("latino") . = -55 + if("albino") . = 34 + else . = rand(-185, 34) + return min(max(. + rand(-25, 25), -185), 34) + else if(species == "Vox") + . = rand(1, 6) + return . -proc/skintone2racedescription(tone) - switch (tone) - if(30 to INFINITY) return "albino" - if(20 to 30) return "pale" - if(5 to 15) return "light skinned" - if(-10 to 5) return "white" - if(-25 to -10) return "tan" - if(-45 to -25) return "darker skinned" - if(-65 to -45) return "brown" - if(-INFINITY to -65) return "black" - else return "unknown" +proc/skintone2racedescription(tone, species = "Human") + if(species == "Human") + switch (tone) + if(30 to INFINITY) return "albino" + if(20 to 30) return "pale" + if(5 to 15) return "light skinned" + if(-10 to 5) return "white" + if(-25 to -10) return "tan" + if(-45 to -25) return "darker skinned" + if(-65 to -45) return "brown" + if(-INFINITY to -65) return "black" + else return "unknown" + else if(species == "Vox") + switch(tone) + if(2) return "dark green" + if(3) return "brown" + if(4) return "gray" + if(5) return "emerald" + if(6) return "azure" + else return "green" + else + return "unknown" proc/age2agedescription(age) switch(age) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index b6dc1c58b8f..e1e8b818356 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -4,6 +4,7 @@ var/global/list/all_languages[0] var/global/list/language_keys[0] // Table of say codes for all languages var/global/list/all_superheroes[0] var/global/list/all_nations[0] +var/global/list/emotes[0] var/global/list/whitelisted_species = list() var/list/clients = list() //list of all clients diff --git a/code/_onclick/_defines.dm b/code/_onclick/_defines.dm index 3c76c35e807..a02a1f43590 100644 --- a/code/_onclick/_defines.dm +++ b/code/_onclick/_defines.dm @@ -1 +1,3 @@ -#define CLICKCATCHER_PLANE -99 \ No newline at end of file +#define CLICKCATCHER_PLANE -99 + +#define HUD_PLANE 90 \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 02c5bfc2ac3..e49e99ad6b7 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -186,4 +186,3 @@ to_chat(usr, "Switched HUD mode. Press F12 to toggle.") else to_chat(usr, "This mob type does not use a HUD.") - diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 7aa9839d663..861209033af 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -209,6 +209,7 @@ else A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7" A.layer = 20 + A.plane = HUD_PLANE x++ if(x == 4) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 1f0e6205200..58fb139ce33 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -10,9 +10,11 @@ name = "" icon = 'icons/mob/screen_gen.dmi' layer = 20 + plane = HUD_PLANE unacidable = 1 var/obj/master = null //A reference to the object in the slot. Grabs or items, generally. var/datum/hud/hud = null + appearance_flags = NO_CLIENT_COLOR /obj/screen/Destroy() master = null diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index ee953edac3f..50b6716c977 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -69,6 +69,7 @@ var/const/tk_maxrange = 15 //item_state = null w_class = 10.0 layer = 20 + plane = HUD_PLANE var/last_throw = 0 var/atom/movable/focus = null diff --git a/code/controllers/ProcessScheduler/core/process.dm b/code/controllers/ProcessScheduler/core/process.dm index 27ba2479ae5..620dafca4ec 100644 --- a/code/controllers/ProcessScheduler/core/process.dm +++ b/code/controllers/ProcessScheduler/core/process.dm @@ -326,6 +326,11 @@ stat("[name]", "T#[getTicks()] | AR [averageRunTime] | LR [lastRunTime] | HR [highestRunTime] | D [cpu_defer_count]") /datum/controller/process/proc/catchException(var/exception/e, var/thrower) + if(istype(e)) // Real runtimes go to the real error handler + // There are two newlines here, because handling desc sucks + e.desc = " Caught by process: [name]\n\n" + e.desc + world.Error(e, e_src = thrower) + return var/etext = "[e]" var/eid = "[e]" // Exception ID, for tracking repeated exceptions var/ptext = "" // "processing..." text, for what was being processed (if known) diff --git a/code/datums/Emote_system/emote.dm b/code/datums/Emote_system/emote.dm new file mode 100644 index 00000000000..07089785740 --- /dev/null +++ b/code/datums/Emote_system/emote.dm @@ -0,0 +1,584 @@ +/******************************************************************************************************* + Emotes +Remember, only 1 instance of each emote is made, and used by all mobs that can access it. As such, the +ONLY place you can safely set object variables during runtime is in New(). Otherwise override the emote. +The only exception to this is custom emotes, which are created as needed and only last until they are finished +VampyrBytes + +*******************************************************************************************************/ +#define EMOTE_COOLDOWN 20 //Time in deciseconds that the cooldown lasts +#define HEARING_RANGE 7 +#define INVALID -1 //Using -1 as I can't see how a negative number could be a valid input + +/datum/emote + var/name = "" + var/desc = "" + var/list/commands[0] // list of commands that trigger the emote. + var/text = "" + var/selfText = "" // the version of text that you should see - eg, if text is screams, you want scream here, as You screams is bad grammer + var/startText = "" // if you need to put something in before [user] + var/selfStart = 1 // whether the start text is used in what you see + + var/audible = 0 + var/mimeText = "" + var/mimeSelf = "" //self version of mimeText + var/sound // sound file + var/vol = 50 + var/muzzleAffected = 0 // whether being muzzled affects this emote + var/muzzledNoise = "" // if the emote is audible and you're muzzled, this is what type of noise you make (eg weak, loud). + var/cooldown = 0 // How long the cooldown should be on this emote. Defaults to EMOTE_COOLDOWN if not set and the emote plays a sound + + var/restrained = 0 // 1 if being restrained prevents this emote + + var/canTarget = 0 // 1 if the emote accepts a target + var/targetMob = 0 // 0 if target can be any atom, 1 if it has to be a mob, + var/mustTarget = 0 // 1 if the emote needs a target to work (won't get None as an option) + var/targetText = "at" // what goes inbetween user and target + var/takesNumber = 0 // 1 if the emote uses a number parameter + + var/emoteSpanClass = "notice" + var/userSpanClass = "em" + var/baseLevel = 1 + var/allowParent = 0 // 1 if you want the parent available as well as this one + + +/datum/emote/New() + var/pathString = "[type]" + var/count = 0 + for(var/i in 1 to lentext(pathString)) + var/char = copytext(pathString, i, i+1) + if(char == "/") + count++ + if(count == 4) + baseLevel = 0 + break + + if(sound && !cooldown) + cooldown = EMOTE_COOLDOWN + + if(targetText) + if(!findtextEx(targetText, " ", lentext(targetText))) + targetText += " " + +/datum/emote/proc/doEmote(var/mob/user, var/command = "") + if(!istype(user)) + return + if(cooldown) + if(handle_emote_CD(user)) + return + + var/message = "" + var/list/params[0] + + params = getParams(user) + + for(var/p in params) + if(params[p] == INVALID) + return + + if(text) + message = createMessage(user, params) + + if(message) + message = addExtras(user, params, message) + . = processMessage(user, params, message) + + if(!doMime(user) && (!muzzleAffected || !isMuzzled(user))) + if(playSound(user, params)) + . = 2 + + doAction(user, params) + + for(var/obj/item/weapon/implant/I in user) + if(I.implanted) + I.trigger(command, user) + + return + +// for things that the emote does that aren't text or sound based +/datum/emote/proc/doAction(var/mob/user, var/list/params) + return + +/datum/emote/proc/getParams(var/mob/user) + var/list/params[0] + + if(takesNumber) + user.set_typing_indicator(1) + user.hud_typing = 1 + params["num"] = getNumber(user) + user.hud_typing = 0 + user.set_typing_indicator(0) + + if(canTarget) + user.set_typing_indicator(1) + user.hud_typing = 1 + params["target"] = getTarget(user) + user.hud_typing = 0 + user.set_typing_indicator(0) + return params + +// return INVALID from either of these getters if you've tested the input and it's failed +/datum/emote/proc/getNumber(var/mob/user) + var/number = input("How many?", "Enter number") as null|num + return number + +/datum/emote/proc/getTarget(var/mob/user) + if(user.sdisabilities & BLIND || user.blinded || user.paralysis) + return + var/list/targets = list() + if(!mustTarget) + targets += "None" + var/target + if(targetMob) + target = getMobTarget(user, targets) + else + target = getAtomTarget(user, targets) + if(!target) + return INVALID + if(target == "None") + return + return target + +/datum/emote/proc/getMobTarget(var/mob/user, var/list/targets) + for(var/mob/M in view(getLoc(user))) + targets += M + var/mob/target = input("Select target", "Target Mob") as null|anything in targets + return target + + +/datum/emote/proc/getAtomTarget(var/mob/user, var/list/targets) + for(var/A in oview(getLoc(user))) + if(ismob(A) || isobj(A) || isturf(A)) + targets += A + var/atom/target = input("Select target", "Target") as null|anything in targets + return target + +// returns the reason the user can't currently do the emote +/datum/emote/proc/prevented(var/mob/user) + if(user.stat == DEAD) + return "you are dead" + if(user.stat == UNCONSCIOUS) + return "you are unconscious" + if(restrained && user.restrained()) + return "you are restrained" + if(isbrain(user)) + var/mob/living/carbon/brain/brain = user + if(!(brain.container && istype(brain.container, /obj/item/device/mmi))) + return "you need to be in an mmi to do this" + +// return 1 if this emote can be used by this type of user +/datum/emote/proc/available(var/mob/user) + return + +/datum/emote/proc/createMessage(var/mob/user, var/list/params) + if(!text) + return + var/message = "" + + if(doMime(user)) + message = mimeMessage(user, params) + if(message) + return message + + if(muzzleAffected && isMuzzled(user)) + message = muzzleMessage(user, params) + return message + + if(checkForParams(params)) + message = paramMessage(user, params) + return message + + message = standardMessage(user, params) + + return message + +/datum/emote/proc/isMuzzled(var/mob/user) + if(user.sdisabilities & MUTE || user.is_muzzled()) + return 1 + if(!isliving(user)) + return + var/mob/living/L = user + if(L.silent) + return 1 + +/datum/emote/proc/checkForParams(var/list/params) + for(var/p in params) + if(p == "target") + continue + return 1 + +/datum/emote/proc/addExtras(var/mob/user, var/list/params, var/message = "") + if(!message) + return + if(startText) + message = "[startText] [message]" + message = addPunc(message) + message = "[message]" + return message + +/datum/emote/proc/addPunc(var/message = "") + var/regex/endingPunc = new("\[\\.!\\?\"]$") + if(!endingPunc.Find(message)) + message += "." + return message + +/datum/emote/proc/standardMessage(var/mob/user, var/list/params) + var/message = "\The [user] [text]" + if("target" in params) + message = addTarget(user, params, message) + return message + +/datum/emote/proc/mimeMessage(var/mob/user, var/list/params) + if(!mimeText) + return + if(checkForParams(params)) + return paramMimeMessage(user, params) + var/message = "\The [user] [mimeText]" + if(message && "target" in params) + message = addTarget(user, params, message) + return message + +/datum/emote/proc/muzzleMessage(var/mob/user, var/list/params) + var/message = "\The [user] makes a " + if(muzzledNoise) + message += "[muzzledNoise] " + message += "noise" + return message + +// if the emote takes a non target parameter, set up and return the with parameter version in here +/datum/emote/proc/paramMessage(var/mob/user, var/list/params) + return + +// as above, but for mimes when there is mimeText +/datum/emote/proc/paramMimeMessage(var/mob/user, var/list/params) + return + +/datum/emote/proc/addTarget(var/mob/user, var/list/params, var/message = "") + if(!canTarget) + return message + if(!params["target"]) + return message + if(params["target"] == user) + message += " [targetText][getHimself(user)]" + return message + message += " [targetText]\the [params["target"]]" + return message + + +// What you should see when you perform the emote +/datum/emote/proc/createSelfMessage(var/mob/user, var/list/params, var/message = "") + if(!selfText) + return message + + message = replacetext(message, text, selfText) + message = changeTextMacros(user, message) + + if(mimeSelf) + message = replacetext(message, mimeText, mimeSelf) + + if(startText && !selfStart) + var/start = findtextEx(message, startText) + var/end = start + lentext(startText) + 1 + message = copytext(message, 1, start) + copytext(message, end, lentext(message) + 1) + + message = replaceMobWithYou(user, message) + + return message + +/datum/emote/proc/replaceMobWithYou(var/mob/M, var/message = "", var/mob/user) // user passed in in case an override needs to do something different if M != user (see johnny) VB + + message = replacetext(message, "\The [M]", "You") + message = replacetext(message, "\the [M]", "you") + + return message + +/datum/emote/proc/processMessage(var/mob/user, var/list/params, var/message = "") + var/visualOrAudible = audible + 1 + if(doMime(user)) + visualOrAudible = 1 + + log_emote("[user.name]/[user.key] : [message]") + sendToDead(message) + for(var/mob/M in getRecipients(getLoc(user, message), visualOrAudible)) + var/msg = "" + + if(M==user) + msg = createSelfMessage(user, params, message) + if(msg) + outputMessage(M, msg) + continue + + if(M.stat == UNCONSCIOUS || (M.sleeping && M.stat != DEAD)) + if(!visualOrAudible == 2) + continue + msg = "... You can almost hear someone talking ..." + outputMessage(M, msg) + continue + + if(M.sdisabilities & DEAF || M.ear_deaf) + if(M.sdisabilities & BLIND || M.blinded || M.paralysis) + continue + if(!(M in getRecipients(user, 1)) || M.see_invisible < user.invisibility) + continue + + msg = createDeafMessage(user, params, message) + if(!msg && visualOrAudible == 2) + continue + if(msg) + outputMessage(M, msg) + continue + + if(M.sdisabilities & BLIND || M.blinded || M.paralysis || (M.see_invisible < user.invisibility && visualOrAudible == 2)) + if(!(M in getRecipients(user, 2))) + continue + + msg = createBlindMessage(user, params, message) + if(!msg && visualOrAudible == 1) + continue + if(msg) + outputMessage(M, msg) + continue + + if(M.see_invisible < user.invisibility && visualOrAudible == 1) + continue + + msg = message + outputMessage(M, msg, user) + + if(visualOrAudible == 2) + handleListeningObjects(user, message) + + return visualOrAudible + +/datum/emote/proc/outputMessage(var/mob/M, var/msg = "", var/mob/user) + msg = replaceMobWithYou(M, msg, user) + to_chat(M, msg) + +/datum/emote/proc/getLoc(var/mob/user, var/message = "") + var/loc = checkForHolopad(user, message) + if(loc) + return loc + return user + +/datum/emote/proc/checkForHolopad(var/mob/user, var/message = "") + if(!isAI(user)) + return + var/mob/living/silicon/ai/AI = user + var/obj/machinery/hologram/holopad/T = AI.holo + if(!(T && T.hologram && T.master == AI)) + return + if(message) + to_chat(AI, "Holopad action relayed, [message]") + return T + +/datum/emote/proc/handleListeningObjects(var/mob/user, var/message = "") + // based on say code + var/omsg = replacetext(message, "[user] ", "") + var/list/listening_obj = new + for(var/atom/movable/A in view(HEARING_RANGE, user)) + if(istype(A, /mob)) + var/mob/M = A + for(var/obj/O in M.contents) + listening_obj |= O + else if(istype(A, /obj)) + var/obj/O = A + listening_obj |= O + for(var/obj/O in listening_obj) + O.hear_message(user, omsg) + +/datum/emote/proc/getRecipients(var/location, var/visualOrAudible) + if(visualOrAudible == 1) + return viewers(location) + return get_mobs_in_view(HEARING_RANGE, location) + +// set up different messages for blind people here. Empty will mean no message for +//non-audible emotes and the standard message for audible ones +/datum/emote/proc/createBlindMessage(var/mob/user, var/list/params, var/message) + if(audible && selfText) + message = "You hear someone [selfText]" + message = addExtras(message) + return message + +// set up different messages for deaf people here. Empty will mean no message for +// audible emotes and standard for non-audible ones +/datum/emote/proc/createDeafMessage(var/mob/user, var/list/params, var/message) + message = mimeMessage(user, params) + message = addExtras(message) + return message + +/datum/emote/proc/sendToDead(var/message = "") + for(var/mob/M in dead_mob_list) + if(!M.client || istype(M, /mob/new_player)) + continue //skip monkeys, leavers and new players + if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) + M.show_message(message) + +/datum/emote/proc/playSound(var/mob/user, var/list/params) + if(!sound) + return + playsound(user, sound, vol) + return 1 + +/datum/emote/proc/doMime(var/mob/user) + if(mimeText && user.mind && user.mind.miming) + return 1 + +//Emote Cooldown System (it's so simple!) +/datum/emote/proc/handle_emote_CD(var/mob/user) + if(user.emote_cd == 2) return 1 // Cooldown emotes were disabled by an admin, prevent use + if(user.emote_cd == 1) return 1 // Already on CD, prevent use + + user.emote_cd = 1 // Starting cooldown + + spawn(cooldown) + if(user.emote_cd == 2) return 1 // Don't reset if cooldown emotes were disabled by an admin during the cooldown + user.emote_cd = 0 // Cooldown complete, ready for more! + + return 0 // Proceed with emote +//--FalseIncarnate + +/datum/emote/proc/changeTextMacros(var/mob/user, var/message = "") + message = swapHisToYour(user, message) + message = swapHimselfToYourself(user, message) + return message + +/datum/emote/proc/getHis(var/mob/user) + var/his = "[user]\his" + his = copytext(his, lentext("[user]") + 1) + return his + +/datum/emote/proc/swapHisToYour(var/mob/user, var/message = "") + var/his = getHis(user) + message = replacetext(message, " [his] ", " your ") + return message + +/datum/emote/proc/getHimself(var/mob/user) + var/himself = "[user]\himself" + himself = copytext(himself, lentext("[user]") + 1) + return himself + +/datum/emote/proc/swapHimselfToYourself(var/mob/user, var/message) + var/himself = getHimself(user) + message = replacetext(message, "[himself]", "yourself") + return message + +/****************************************************************************************** + Emote Verbs +******************************************************************************************/ + +/datum/emote/proc/addVerbs(var/mob/user) + if(!istype(user)) + return + new /obj/emoteVerb(user, src, commands) + +// Dummy object to allow access to the verb, needed as verbs require a valid loc for setting the src +/obj/emoteVerb + var/datum/emote/emote + var/mob/owner + +/obj/emoteVerb/New(var/mob/user, var/datum/emote/toAccess) + if(!(istype(user))) + return + if(!(istype(toAccess))) + return + if(!toAccess.commands) + return + owner = user + emote = toAccess + name = "[emote]" + loc = user + user.verbs += new/obj/emoteVerb/proc/runEmote(src, emote.commands[1], emote.desc) + +/obj/emoteVerb/proc/runEmote() + set src = usr.contents + set category = "Emotes" + return usr.emoteHandler.runEmote(emote.commands[1]) + +/obj/emoteVerb/Destroy() + owner.verbs -= new/obj/emoteVerb/proc/runEmote(src, emote.commands[1]) + ..() + +/obj/emoteVerb/custom + +obj/emoteVerb/custom/New(var/mob/user) + if(!(istype(user))) + return + owner = user + name = "custom" + user.verbs += new/obj/emoteVerb/proc/runEmote(src, "custom", "Make your own emote") + +/obj/emoteVerb/custom/runEmote() + set src = usr.contents + set category = "Emotes" + return usr.emoteHandler.runEmote("me") + + + +/************************************************************************************************************************** + Custom Emotes +As these are made as needed, they aren't searched for the appropriate one. As such, you need to specify conditions for which +one is used in /datum/emote_handler/customEmote(). + +***************************************************************************************************************************/ + +/datum/emote/custom + name = "Custom emote" + baseLevel = 0 + +/datum/emote/custom/New(var/mob/user, var/message = "", var/isAudible) + if(!message) + message = getMessage(user) + text = message + audible = isAudible + +/datum/emote/custom/proc/getMessage(var/mob/user) +// user.set_typing_indicator(1) +// user.hud_typing = 1 + var/input = sanitize(copytext(input(user,"What do you want to emote?.", "Custom emote") as text|null,1,MAX_MESSAGE_LEN)) +// user.hud_typing = 0 +// user.set_typing_indicator(0) + input = strip_html_properly(input) + return input + +/datum/emote/custom/available(var/mob/user) + return 1 + +/datum/emote/custom/prevented(var/mob/user) + if(!user.use_me) + return "you are prevented from using custom emotes" + +// Yeah, no +/datum/emote/custom/createSelfMessage(var/mob/user, var/list/params, var/message = "") + return + +/datum/emote/custom/replaceMobWithYou(var/mob/M, var/message = "", var/mob/user) + return message + +/datum/emote/custom/ghost + name = "Ghost emote" + startText = "DEAD: " + emoteSpanClass = "game deadsay" + +/datum/emote/custom/ghost/prevented(var/mob/user) + . = ..() + if(.) + return + if(user.client.prefs.muted & MUTE_DEADCHAT) + return "you are muted from deadchat" + if(!(user.client.prefs.toggles & CHAT_DEAD)) + return "you have deadchat muted" + if(!user.client.holder) + if(!config.dsay_allowed) + return "deadchat is globally muted" + +/datum/emote/custom/ghost/getMessage(var/mob/user) + var/input = sanitize(copytext(input(user,"What do you want to emote?.", "Custom emote") as text|null,1,MAX_MESSAGE_LEN)) + input = strip_html_properly(input) + return input + +/datum/emote/custom/ghost/processMessage(var/mob/user, var/list/params, var/message = "") + if(!message) + return + log_emote("Ghost/[user.key] : [message]") + sendToDead(message) + diff --git a/code/datums/Emote_system/emote_handler.dm b/code/datums/Emote_system/emote_handler.dm new file mode 100644 index 00000000000..be962a72dc7 --- /dev/null +++ b/code/datums/Emote_system/emote_handler.dm @@ -0,0 +1,90 @@ +/datum/emoteHandler + var/mob/owner + var/list/commands + +/datum/emoteHandler/New(var/mob/user) + owner = user + setupCommands() + +/datum/emoteHandler/proc/setupCommands(var/reset = 0) + spawn(0) // needed so at mob creation species is set before emotes are allocated + if(reset) + deleteEmoteVerbs() + commands = new/list() + for(var/e in emotes) + var/datum/emote/emote = e + if(emote.baseLevel || emote.allowParent) + var/datum/emote/found = searchTree(emote) + if(found) + for(var/command in found.commands) + commands[lowertext(command)] = found + found.addVerbs(owner) + +/datum/emoteHandler/proc/deleteEmoteVerbs() + for(var/obj/emoteVerb/E in owner.contents) + qdel(E) + +/datum/emoteHandler/proc/runEmote(var/command = "", var/message = "", var/audible = 0) // message and audible only used in custom emotes + if(!command) + return 0 + if(command == "help") + showCommands() + return 1 + + var/datum/emote/emote + + if(copytext(command, 1, 3) == "me" && !message && lentext(command) >= 4) + message = copytext(command, 4) + command = "me" + + if(command == "me") + emote = customEmote(message, audible) + if(!emote) + return 0 + + if(!commands[command] && !(command == "me")) + to_chat(owner, "Unknown emote, please check *help for emotes available to your character") + return 0 + + if(!emote) + emote = commands[command] + + if(!emote.available(owner)) // something's changed, remake the commands list, then try again to see if they've got a different version + setupCommands() + return runEmote(command, message, audible) + + var/prevented = emote.prevented(owner) + if(prevented) + to_chat(owner, "You can't do that because [prevented]!") + return 0 + return emote.doEmote(owner, command) + +/datum/emoteHandler/proc/showCommands() + var/emoteList = "Available emotes are " + var/commandAdded = 0 + for(var/c in commands) + if(commandAdded) + emoteList += ", " + emoteList += c + commandAdded = 1 + + to_chat(owner, emoteList) + +// recursive search of subtypes - starts checking at the lowest level and breaks out if it finds one that can be done +/datum/emoteHandler/proc/searchTree(var/datum/emote/emote) + var/list/subtypes = subtypesof(emote.type) + var/datum/emote/found + for(var/t in subtypes) + var/datum/emote/em = new t + if(em.allowParent) + continue + found = searchTree(em) + if(found) + return (found) + if(emote.available(owner)) + return emote + +/datum/emoteHandler/proc/customEmote(var/custom, var/audible) + if(isobserver(owner)) + return new /datum/emote/custom/ghost(owner, custom, audible) + return new /datum/emote/custom(owner, custom, audible) diff --git a/code/datums/Emote_system/emotes.dm b/code/datums/Emote_system/emotes.dm new file mode 100644 index 00000000000..a5383c30c23 --- /dev/null +++ b/code/datums/Emote_system/emotes.dm @@ -0,0 +1,1718 @@ + +/datum/emote/airguitar + name = "airguitar" + desc = "Makes the mob play an air guitar" + commands = list("airguitar") + text = "is strumming the air and headbanging like a safari chimp" + selfText = "are strumming the air and headbanging like a safari chimp" + restrained = 1 + +/datum/emote/airguitar/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/alarm + name = "alarm" + desc = "makes the mob sound an alarm" + commands = list("alarm") + text = "sounds an alarm" + selfText = "sound an alarm" + audible = 1 + +/datum/emote/alarm/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/alarm/createBlindMessage(var/mob/user, var/params, var/messaage) + return "You hear an alarm" + +/datum/emote/alert + name = "alert" + desc = "Makes the mob sound an alert" + commands = list("alert") + text = "lets out a distressed noise" + selfText = "let out a distressed noise" + audible = 1 + +/datum/emote/alert/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/beep + name = "beep" + desc = "makes the mob let out a beep" + commands = list("beep") + text = "beeps" + selfText = "beep" + audible = 1 + +/datum/emote/beep/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/beep/targetted + sound = 'sound/machines/twobeep.ogg' + cooldown = 50 + canTarget = 1 + targetMob = 1 + +/datum/emote/beep/targetted/available(var/mob/user) + if(user.is_mechanical()) + return 1 + +/datum/emote/blink + name = "blink" + desc = "Makes the mob blink" + commands = list("blink", "blinks") + text = "blinks" + selfText = "blink" + +/datum/emote/blink/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isbrain(user)) + return 1 + +/datum/emote/blink/rapid + name = "rapid blink" + desc = "Makes the mob blink rapidly" + commands = list("blink_r", "blinks_r") + allowParent = 1 + +/datum/emote/blink/rapid/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/blink/rapid/standardMessage(var/mob/user) + var/message = ..() + message += " rapidly" + return message + +/datum/emote/blush + name = "blush" + desc = "Makes the mob blush" + commands = list("blush", "blushes") + text = "blushes" + selfText = "blush" + +/datum/emote/blush/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/boop + name = "boop" + desc = "Makes the mob boop" + commands = list("boop", "boops") + text = "boops" + selfText = "boop" + +/datum/emote/boop/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/bounce + name = "bounce" + desc = "Makes the mob bounce" + commands = list("bounce", "bounces") + text = "bounces in place" + selfText = "bounce in place" + +/datum/emote/bounce/available(var/mob/user) + if(isslime(user)) + return 1 + +/datum/emote/bow + name = "bow" + desc = "Makes the mob bow" + commands = list("bow", "bows") + text = "bows" + selfText = "bow" + canTarget = 1 + targetMob = 1 + targetText = "to" + +/datum/emote/bow/available(var/mob/user) + if(isrobot(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/bow/prevented(var/mob/user) + . = ..() + if(!. && user.buckled) + return "you are buckled to something" + +/datum/emote/burp + name = "burp" + desc = "Makes the mob burp" + commands = list("burp", "burps") + text = "burps" + selfText = "burp" + audible = 1 + mimeText = "opens their mouth rather obnoxiously" + mimeSelf = "open your mouth rather obnoxiously" + muzzleAffected = 1 + muzzledNoise = "peculiar" + +/datum/emote/burp/available(var/mob/user) + if(ishuman(user)) + return 1 + if(islarva(user) || isalienadult(user)) + return 1 + +/datum/emote/buzz + name = "buzz" + desc = "Makes the mob buzz" + commands = list("buzz", "buzzes", "buzzs") + text = "buzzes" + selfText = "buzz" + audible = 1 + sound = 'sound/machines/buzz-sigh.ogg' + canTarget = 1 + targetMob = 1 + +/datum/emote/buzz/available(var/mob/user) + if(user.is_mechanical()) + return 1 + +/datum/emote/buzz/buzz2 + name = "buzz 2" + desc = "makes the mob buzz in an irritated way" + commands = list("buzz2") + text = "makes an irritated buzzing sound" + selfText = "make an irritated buzzing sound" + sound = "sound/machines/buzz-two.ogg" + allowParent = 1 + +/datum/emote/chirp + name = "chirp" + desc = "Makes the mob chirp" + commands = list("chirp", "chirps") + text = "chirps" + selfText = "chirp" + audible = 1 + sound = 'sound/misc/nymphchirp.ogg' + vol = 40 + cooldown = 50 + +/datum/emote/chirp/available(var/mob/user) + if(istype(user, /mob/living/simple_animal/diona)) + return 1 + +/datum/emote/choke + name = "choke" + desc = "Makes the mob choke" + commands = list("choke", "chokes") + text = "chokes" + selfText = "choke" + audible = 1 + mimeText = "clutches" + mimeSelf = "clutch" + muzzleAffected = 1 + muzzledNoise = "strong" + +/datum/emote/choke/available(var/mob/user) + if(ishuman(user)) + return 1 + if(islarva(user) || isalienadult(user)) + return 1 + +// This has to be done here not mimeText because \his will throw a compile error +// instead of a runtime if there's not a valid target in the string *frown VB +/datum/emote/choke/mimeMessage(var/mob/user, var/list/params) + var/message = "[user] [mimeText] \his throat desperately" + return message + +/datum/emote/chuckle + name = "chuckle" + desc = "chuckle" + commands = list("chuckle", "chuckles") + text = "chuckles" + selfText = "chuckle" + audible = 1 + mimeText = "appears to chuckle" + mimeSelf = "appear to chuckle" + muzzleAffected = 1 + +/datum/emote/chuckle/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/clap + name = "clap" + desc = "clap" + commands = list("clap", "claps") + text = "claps" + selfText = "clap" + audible = 1 + mimeText = "claps silently" + restrained = 1 + +/datum/emote/clap/available(var/mob/user) + if(isrobot(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/collapse + name = "collapse" + desc = "Makes the mob collapse" + commands = list("collapse", "collapses") + text = "collapses" + selfText = "collapse" + audible = 1 + mimeText = "collapses without a sound" + +/datum/emote/collapse/available(var/mob/user) + if(islarva(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/collapse/doAction(var/mob/user, var/list/params) + user.Paralyse(2) + +/datum/emote/cough + name = "cough" + desc = "Makes the mob cough" + commands = list("cough", "coughs") + text = "coughs" + selfText = "cough" + audible = 1 + mimeText = "appears to cough" + mimeSelf = "appear to cough" + muzzleAffected = 1 + muzzledNoise = "strong" + +/datum/emote/cough/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/cry + name = "cry" + desc = "Makes the mob cry" + commands = list("cry", "cries") + text = "cries" + selfText = "cry" + audible = 1 + mimeText = "cries silently" + muzzleAffected = 1 + muzzledNoise = "weak" + +/datum/emote/cry/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/dance + name = "dance" + desc = "makes the mob dance around happily" + commands = list("dance", "dances") + text = "dances around happily" + selfText = "dance around happily" + restrained = 1 + +/datum/emote/dance/available(var/mob/user) + if(islarva(user)) + return 1 + +/datum/emote/dap + name = "dap" + desc = "Makes the mob give daps" + commands = list("dap", "daps") + text = "gives daps" + selfText = "give daps" + restrained = 1 + canTarget = 1 + targetMob = 1 + targetText = "to" + +/datum/emote/dap/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/dap/addTarget(var/mob/user, var/list/params, var/message = "") + if(!params["target"] || params["target"] == user) + message = "[user] sadly can't find anybody to give daps to, and daps \himself. Shameful" + return message + return ..() + +/datum/emote/deathgasp + name = "deathgasp" + desc = "Makes the mob let out it's final gasp" + commands = list("deathgasp", "deathgasps") + audible = 1 + +/datum/emote/deathgasp/alien + text = "lets out a waning guttural screech, green blood bubbling from its maw..." + selfText = "let out a waning guttural screech, green blood bubbling from your maw..." + +/datum/emote/deathgasp/alien/available(var/mob/user) + if(isalienadult(user)) + return 1 + +// sorry, no selftext for humans as we'd have to add a var to species for it and that's yuk - VB +/datum/emote/deathgasp/human + text = "dummytext" + +/datum/emote/deathgasp/human/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/deathgasp/human/standardMessage(var/mob/user, var/list/params) + var/mob/living/carbon/human/U = user + var/message = "\The [user] [U.species.death_message]" + return message + +/datum/emote/deathgasp/human/createSelfMessage(var/mob/user, var/list/params, var/message) + return message + +/datum/emote/deathgasp/human/replaceMobWithYou(var/mob/user, var/message) + return message + +/datum/emote/deathgasp/robot + text = "shudders violently for a moment, then becomes motionless, its eyes slowly darkening" + selfText = "shudder violently for a moment, then become motionless, your eyes slowly darkening" + audible = 0 + +/datum/emote/deathgasp/robot/available(var/mob/user) + if(isrobot(user)) + return 1 + +/datum/emote/drone + name = "drone" + desc = "Makes the mob drone and rumble" + commands = list("drone", "drones", "rumble", "rumbles", "hum", "hums") + text = "rumbles" + selfText = "rumble" + audible = 1 + sound = 'sound/voice/DraskTalk.ogg' + canTarget = 1 + targetMob = 1 + +/datum/emote/drone/available(var/mob/user) + if(user.get_species() == "Drask") + return 1 + +/datum/emote/drone/addTarget(var/mob/user, var/list/params, var/message) + if(!params["target"]) + return message + message = replacetext(message, "rumbles", "drones") + return ..() + +/datum/emote/drone/createSelfMessage(var/mob/user, var/list/params, var/message) + message = ..() + message = replacetext(message, "drones", "drone") + return message + +/datum/emote/drool + name = "drool" + desc = "Makes the mob drool" + commands = list("drool", "drools") + text = "drools" + selfText = "drool" + +/datum/emote/drool/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/eyebrow + name = "eyebrow" + desc = "Makes the mob raise an eyebrow" + commands = list("eyebrow") + text = "raises an eyebrow" + selfText = "raise an eyebrow" + +/datum/emote/eyebrow/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/faint + name = "faint" + desc = "makes the mob faint" + commands = list("faint", "faints") + text = "faints" + selfText = "faint" + +/datum/emote/faint/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/faint/doAction(var/mob/user, var/list/params) + if(!user.sleeping) + user.sleeping += 1 + +/datum/emote/fart + name = "fart" + desc = "makes the mob fart" + commands = list("fart", "farts") + text = "farts" + selfText = "fart" + cooldown = 50 + audible = 1 + +/datum/emote/fart/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/fart/standardMessage(var/mob/user) + var/message + + if(TOXIC_FARTS in user.mutations) + message = "\The [user] unleashes a [pick("horrible","terrible","foul","disgusting","awful")] fart" + return message + message = "\The [user] [pick("passes wind","farts")]" + return message + +/datum/emote/fart/createSelfMessage(var/mob/user, var/list/params, var/message) + message = ..() + message = replacetext(message, "unleashes", "unleash") + message = replacetext(message, "passes", "pass") + return message + +/datum/emote/fart/doAction(var/mob/user) + if(TOXIC_FARTS in user.mutations) + for(var/mob/M in range(get_turf(user),2)) + if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT)) + continue + if(M == user) + continue + M.reagents.add_reagent("jenkem", 1) + + if(locate(/obj/item/weapon/storage/bible) in get_turf(user)) + to_chat(viewers(user), "[user] farted on the Bible!") + to_chat(viewers(user), "A mysterious force smites [user]!") + var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread + s.set_up(3, 1, user) + s.start() + user.gib() + +/datum/emote/flap + name = "flap" + desc = "Makes the mob flap their wings" + commands = list("flap", "flaps") + text = "flaps" + selfText = "flap" + restrained = 1 + audible = 1 + +/datum/emote/flap/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/flap/standardMessage(var/mob/user, var/list/params) + var/message = "\The [user] [text] \his wings" + return message + +/datum/emote/flap/angry + name = "angry flap" + desc = "makes the mob flap their wings angrily" + commands = list("a_flap", "a_flaps") + allowParent = 1 + +/datum/emote/flap/angry/standardMessage(var/mob/user) + var/message = ..() + message += " angrily" + return message + +/datum/emote/flash + name = "flash" + desc = "Makes the lights on the mob flash quickly" + commands = list("flash", "flashes") + text = "flash quickly" + selfText = "flash quickly" + startText = "The lights on" + +/datum/emote/flash/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/flip + name = "flip" + desc = "Makes the mob flip, possibly in the direction of someone" + commands = list("flip", "flips") + text = "flips" + selfText = "flip" + canTarget = 1 + targetMob = 1 + targetText = "in" + +/datum/emote/flip/available(var/mob/user) + if(isrobot(user)) + return 1 + +/datum/emote/flip/prevented(var/mob/user) + . = ..() + if(!. && user.buckled) + return "you are buckled to something" + +/datum/emote/flip/createMessage(var/mob/user, var/list/params) + var/message = "" + if(user.lying || user.weakened) + message = "\The [user] flops and flails around on the floor" + else + message = ..() + return message + +/datum/emote/flip/addTarget(var/mob/user, var/list/params, var/message) + message = ..() + if(params["target"]) + message += "'s general direction" + return message + +/datum/emote/flip/createSelfMessage(var/mob/user, var/list/params, var/message) + message = ..() + message = replacetext(message, "flops", "flop") + message = replacetext(message, "flails", "flail") + return message + +/datum/emote/flip/doAction(var/mob/user, var/list/params, var/message) + if(user.lying || user.weakened) + return + user.SpinAnimation(5,1) + +/datum/emote/flip/flipOver + desc = "Makes the mob flip, possibly in the direction of, or even over someone" + +/datum/emote/flip/flipOver/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/flip/flipOver/createMessage(var/mob/user, var/params) + var/message = "" + var/obj/item/weapon/grab/G = user.get_active_hand() + if(istype(G) && G.affecting && !G.affecting.buckled) + params["target"] = G.affecting + message = "\The [user] [text] over [params["target"]]!" + return message + return ..() + +/datum/emote/flip/flipOver/doAction(var/mob/user, var/params, var/message) + var/obj/item/weapon/grab/G = user.get_active_hand() + if(G == params["target"]) + var/turf/oldloc = user.loc + var/turf/newloc = G.affecting.loc + if(isturf(oldloc) && isturf(newloc)) + user.SpinAnimation(5,1) + user.forceMove(newloc) + G.affecting.forceMove(oldloc) + return + ..() + +/datum/emote/frown + name = "frown" + desc = "Makes the mob frown" + commands = list("frown", "frowns") + text = "frowns" + selfText = "frown" + +/datum/emote/frown/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/gasp + name = "gasp" + desc = "Makes the mob gasp" + commands = list("gasp", "gasps") + text = "gasps" + selfText = "gasp" + audible = 1 + mimeText = "appears to be gasping" + mimeSelf = "appear to be gasping" + muzzleAffected = 1 + muzzledNoise = "weak" + +/datum/emote/gasp/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/giggle + name = "giggle" + desc = "Makes the mob giggle" + commands = list("giggle", "giggles") + text = "giggles" + selfText = "giggle" + audible = 1 + mimeText = "giggles silently" + muzzleAffected = 1 + +/datum/emote/giggle/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/glare + name = "glare" + desc = "Makes the mob glare" + commands = list("glare", "glares") + text = "glares" + selfText = "glare" + canTarget = 1 + targetMob = 1 + +/datum/emote/glare/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/gnarl + name = "gnarl" + desc = "Makes the mob gnarl and show its teeth" + commands = list("gnarl", "gnarls") + text = "gnarls and shows its teeth" + selfText = "gnarl and show your teeth" + audible = 1 + muzzleAffected = 1 + +/datum/emote/gnarl/available(var/mob/user) + if(islarva(user)) + return 1 + +/datum/emote/grin + name = "grin" + desc = "Makes the mob grin" + commands = list("grin", "grins") + text = "grins" + selfText = "grin" + +/datum/emote/grin/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/groan + name = "groan" + desc = "Makes the mob groan" + commands = list("groan", "groans") + text = "groans" + selfText = "groan" + audible = 1 + mimeText = "appears to groan" + mimeSelf = "appear to groan" + muzzleAffected = 1 + +/datum/emote/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/grumble + name = "grumble" + desc = "Makes the mob grumble" + commands = list("grumble", "grumbles") + text = "grumbles" + selfText = "grumble" + audible = 1 + mimeText = "grumbles" + muzzleAffected = 1 + +/datum/emote/grumble/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/halt + name = "halt" + desc = "Makes the mob sound a halt warning. Only available with a security module" + commands = list("halt") + text = "'s speakers skreech, \"Halt! Security!\"" + selfText = " speakers skreech, \"Halt! Security!\"" + audible = 1 + sound = 'sound/voice/halt.ogg' + +/datum/emote/halt/available(var/mob/user) + if(isrobot(user)) + return 1 + +/datum/emote/halt/prevented(var/mob/user) + . = ..() + if(.) + return + var/mob/living/silicon/robot/U = user + if(!(istype(U.module, /obj/item/weapon/robot_module/security))) + return "you are not security" + +/datum/emote/handshake + name = "handshake" + desc = "Makes the mob shake hands with a target" + commands = list("handshake") + text = "shakes hands" + selfText = "shake hands" + canTarget = 1 + targetMob = 1 + mustTarget = 1 + targetText = "with" + restrained = 1 + +/datum/emote/handshake/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/handshake/prevented(var/mob/user) + . = ..() + if(!. && user.r_hand) + return "you need your right hand free" + +/datum/emote/handshake/addTarget(var/mob/user, var/list/params, var/message) + var/mob/target = params["target"] + if(target.r_hand) + message = "\The [user] holds out his hand to [params["target"]]" + return message + return ..() + +/datum/emote/hiss + name = "hiss" + desc = "Makes the mob hiss" + commands = list("hiss", "hisses") + text = "hisses" + selfText = "hiss" + audible = 1 + +/datum/emote/hiss/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + +/datum/emote/hug + name = "hug" + desc = "Makes the mob hug a target or themselves" + commands = list("hug", "hugs") + text = "hugs" + selfText = "hug" + canTarget = 1 + targetMob = 1 + targetText = "" + +/datum/emote/hug/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/hug/getTarget(var/mob/user) + var/mob/target = ..() + if(target) + return target + return user + +/datum/emote/jiggle + name = "jiggle" + desc = "Makes the mob jiggle" + commands = list("jiggle", "jiggles") + text = "jiggles" + selfText = "jiggle" + +/datum/emote/jiggle/available(var/mob/user) + if(isslime(user)) + return 1 + +/datum/emote/johnny + name = "johnny" + desc = "Yeah, just try it" + commands = list("johnny") + text = "takes a drag from a cigarette and blows their name out in smoke" + selfText = "take a drag from a cigarette and blow their name out in smoke" + audible = 1 + mimeText = "takes a drag from a cigarette and blows" + mimeSelf = "take a drag from a cigarette and blow" + canTarget = 1 + targetMob = 1 + mustTarget = 1 + targetText = "" + +/datum/emote/johnny/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/johnny/getTarget(var/mob/user) + var/mob/target = ..() + if(target != user) + return target + to_chat(user, "You need a target that isn't yourself") + return INVALID + +/datum/emote/johnny/createMessage(var/mob/user, var/params) + if(doMime(user)) + return ..() + var/message = "\The [user] says \"[params["target"]], please. They had a family.\" [user] [text]" + return message + +/datum/emote/johnny/createSelfMessage(var/mob/user, var/list/params, var/message = "") + message = ..() + message = replacetext(message, "says", "say") + return message + +/datum/emote/johnny/createDeafMessage(var/mob/user, vap/list/params, var/message) + message = "\The [user] says something, then [text]" + return message + +/datum/emote/johnny/replaceMobWithYou(var/mob/M, var/message, var/mob/user) + if(user && M != user) + return message + return ..() + +/datum/emote/johnny/createBlindMessage(var/mob/user, var/list/params, var/message) + message = "You hear someone say \"[params["target"]], please, They had a family\"" + return message + +/datum/emote/jump + name = "jump" + desc = "Makes the mob jump" + commands = list("jump", "jumps") + text = "jumps" + selfText = "jump" + +/datum/emote/jump/available(var/mob/user) + if(islarva(user) || isalienadult(user)) + return 1 + if(issmall(user)) + return 1 + +/datum/emote/laugh + name = "laugh" + desc = "Makes the mob laugh" + commands = list("laugh", "laughs") + text = "laughs" + selfText = "laugh" + audible = 1 + mimeText = "acts out a laugh" + mimeSelf = "act out a laugh" + muzzleAffected = 1 + +/datum/emote/laugh/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/law + name = "law" + desc = "Makes the mob prove it is the law" + commands = list("law") + text = "shows its legal authorization barcode" + selfText = "show your legal authorization barcode" + audible = 1 + sound = 'sound/voice/biamthelaw.ogg' + +/datum/emote/law/available(var/mob/user) + if(isrobot(user)) + return 1 + +/datum/emote/law/prevented(var/mob/user) + . = ..() + if(.) + return + var/mob/living/silicon/robot/U = user + if(!(istype(U.module, /obj/item/weapon/robot_module/security))) + return "You are not THE LAW, pal" + +/datum/emote/light + name = "light" + desc = "makes the mob light up" + commands = list("light", "lights") + text = "lights up for a bit, then stops" + selfText = "light up for a bit, then stop" + +/datum/emote/light/available(var/mob/user) + if(isslime(user)) + return 1 + +/datum/emote/look + name = "look" + desc = "Makes the mob look" + commands = list("look", "looks") + text = "looks" + selfText = "look" + canTarget = 1 + targetMob = 1 + +/datum/emote/look/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/look/addTarget(var/mob/user, var/list/params, var/message) + if(!params["target"]) + message += " around" + return message + return ..() + +/datum/emote/moan + name = "moan" + desc = "Makes the mob moan" + commands = list("moan", "moans") + text = "moans" + selfText = "moan" + audible = 1 + +/datum/emote/moan/available(var/mob/user) + if(isslime(user)) + return 1 + if(islarva(user)) + return 1 + +/datum/emote/mumble + name = "mumble" + desc = "Makes the mob mumble" + commands = list("mumble", "mumbles") + text = "mumbles" + selfText = "mumble" + audible = 1 + mimeText = "mumbles" + +/datum/emote/mumble/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/no + name = "no" + desc = "Makes the mob let out a negative blip" + commands = list("no") + text = "emits a negative blip" + selfText = "emit a negative blip" + audible = 1 + sound = 'sound/machines/synth_no.ogg' + +/datum/emote/no/New() + ..() + commands += "no" + +/datum/emote/no/available(var/mob/user) + if(user.is_mechanical()) + return 1 + +/datum/emote/nod + name = "nod" + desc = "Makes the mob nod" + commands = list("nod", "nods") + text = "nods" + selfText = "nod" + +/datum/emote/nod/available(var/mob/user) + if(islarva(user)) + return 1 + if(isrobot(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/notice + name = "notice" + desc = "Makes the mob play a loud tone" + commands = list("notice") + text = "plays a loud tone" + selfText = "play a loud tone" + audible = 1 + +/datum/emote/notice/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/pale + name = "pale" + desc = "Makes the mob go pale" + commands = list("pale", "pales") + text = "goes pale for a second" + selfText = "go pale for a second" + +/datum/emote/pale/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/ping + name = "ping" + desc = "Makes the mob ping" + commands = list("ping", "pings") + text = "pings" + selfText = "ping" + audible = 1 + sound = 'sound/machines/ping.ogg' + canTarget = 1 + targetMob = 1 + +/datum/emote/ping/available(var/mob/user) + if(user.is_mechanical()) + return 1 + +/datum/emote/point + name = "point" + desc = "Makes the mob point" + commands = list("point", "points") + text = "points" + selfText = "point" + canTarget = 1 + +/datum/emote/point/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/point/createMessage(var/mob/user, var/list/params) + if(params["target"]) + return + return ..() + +/datum/emote/point/doAction(var/mob/user, var/list/params) + if(!params["target"]) + return + user.pointed(params["target"]) + +/datum/emote/quiver + name = "quiver" + desc = "Makes the mob quiver" + commands = list("quiver", "quivers") + text = "quivers" + selfText = "quiver" + +/datum/emote/quiver/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/raise + name = "raise" + desc = "Makes the mob raise a hand" + commands = list("raise", "raises") + text = "raises a hand" + selfText = "raise a hand" + restrained = 1 + +/datum/emote/raise/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/roar + name = "roar" + desc = "Makes the mob roar" + commands = list("roar", "roars") + text = "roars" + selfText = "roar" + audible = 1 + muzzleAffected = 1 + muzzledNoise = "loud" + +/datum/emote/roar/available(var/mob/user) + if(isalienadult(user)) + return 1 + +/datum/emote/roll + name = "roll" + desc = "Makes the mob roll" + commands = list("roll", "rolls") + text = "rolls" + selfText = "roll" + +/datum/emote/roll/available(var/mob/user) + if(islarva(user)) + return 1 + if(issmall(user)) + return 1 + +/datum/emote/salute + name = "salute" + desc = "Makes the mob salute" + commands = list("salute", "salutes") + text = "salutes" + selfText = "salute" + canTarget = 1 + targetMob = 1 + targetText = "to" + +/datum/emote/salute/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/salute/prevented(var/mob/user) + . = ..() + if(!. && user.buckled) + return "you are buckled to something" + +/datum/emote/salute/getMobTarget(var/mob/user, var/list/targets) + var/mob/target = ..() + if(target != user) + return target + +/datum/emote/scratch + name = "scratch" + desc = "Makes the mob scratch" + commands = list("scratch", "scratches") + text = "scratches" + selfText = "scratch" + restrained = 1 + +/datum/emote/scratch/available(var/mob/user) + if(islarva(user) || isalienadult(user)) + return 1 + if(issmall(user)) + return 1 + +/datum/emote/scream + name = "scream" + desc = "makes the mob scream" + commands = list("scream", "screams") + audible = 1 + mimeText = "acts out a scream" + muzzledNoise = "very loud" + cooldown = 50 + vol = 80 + +/datum/emote/scream/machine + name = "machine scream" + sound = 'sound/goonstation/voice/robot_scream.ogg' + +/datum/emote/scream/machine/available(var/mob/user) + if(user.is_mechanical()) + return 1 + +/datum/emote/scream/human + name = "human scream" + +/datum/emote/scream/human/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/scream/human/playSound(var/mob/user) + var/mob/living/carbon/human/H = user + + if(H.gender == FEMALE) + playsound(H, "[H.species.female_scream_sound]", vol, 1, 0, pitch = H.get_age_pitch()) + else + playsound(H, "[H.species.male_scream_sound]", vol, 1, 0, pitch = H.get_age_pitch()) + return 1 + +/datum/emote/scretch + name = "scretch" + desc = "makes the mob scretch" //whatever that is! + commands = list("scretch", "scretches") + text = "scretches" + selfText = "scretch" + audible = 1 + muzzleAffected = 1 + +/datum/emote/scretch/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + +/datum/emote/shake + name = "shake" + desc = "Makes the mob shake its head" + commands = list("shake", "shakes") + text = "shakes" + selfText = "shake" + +/datum/emote/shake/available(var/mob/user) + if(islarva(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/shake/standardMessage(var/mob/user) + var/message = ..() + message += " [getHis(user)] head" + return message + +/datum/emote/shiver + name = "shiver" + desc = "Makes the mob shiver" + commands = list("shiver", "shivers") + text = "shivers" + selfText = "shiver" + audible = 1 + mimeText = "shivers" + +/datum/emote/shiver/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + if(isslime(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/shiver/createBlindMessage(var/mob/user, var/list/params, var/message) + message = "you hear someone's teeth chattering together" + +/datum/emote/shrug + name = "shrug" + desc = "Makes the mob shrug" + commands = list("shrug", "shrugs") + text = "shrugs" + selfText = "shrug" + +/datum/emote/shrug/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/sigh + name = "sigh" + desc = "Makes the mob sigh" + commands = list("sigh", "sighs") + text = "sighs" + selfText = "sigh" + audible = 1 + mimeText = "sighs" + muzzleAffected = 1 + muzzledNoise = "weak" + +/datum/emote/sigh/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/sign + name = "sign" + desc = "Makes the mob sign a number" + commands = list("sign", "signs") + text = "signs" + selfText = "sign" + restrained = 1 + takesNumber = 1 + +/datum/emote/sign/available(var/mob/user) + if(isalienadult(user) || islarva(user)) + return 1 + +/datum/emote/sign/getNumber(var/mob/user) + var/number = ..() + if(number == null) + to_chat(user, "You need a number to sign") + return INVALID + return number + +/datum/emote/sign/paramMessage(var/mob/user, var/list/params) + var/message = "\The [user] [text] [params["num"]]" + return message + +/datum/emote/sign/fingers + desc = "Makes the mob raise a number of fingers" + text = "raises" + selfText = "raise" + +/datum/emote/sign/fingers/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/sign/fingers/getNumber(var/mob/user) + var/number = ..() + if(number == INVALID) + return INVALID + var/fingersAvailable = 0 + if(!user.r_hand) + fingersAvailable += 5 + if(!user.l_hand) + fingersAvailable += 5 + if(fingersAvailable < number) + to_chat(user, "You don't have enough fingers free") + return INVALID + return number + +/datum/emote/sign/fingers/paramMessage(var/mob/user, var/list/params) + var/message = "\The [user] [text] [params["num"]] finger\s" // no, we can't just add " finger\s" to the parent version because the text macro won't work then :( VB + return message + +/datum/emote/slap + name = "slap" + desc = "makes the mob slap someone" + commands = list("slap", "slaps") + text = "slaps" + selfText = "slap" + audible = 1 + sound = 'sound/effects/snap.ogg' + canTarget = 1 + targetMob = 1 + targetText = "" + +/datum/emote/slap/New() + ..() + cooldown = 0 + +/datum/emote/slap/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/slap/getMobTarget(var/mob/user, var/list/targets) + for(var/mob/M in view(getLoc(user), 1)) + targets += M + var/mob/target = input("Select target", "Target Mob") as null|anything in targets + if(target == "None") + target = user + return target + +/datum/emote/slap/createBlindMessage(var/mob/user, var/list/params, var/message) + message = ..() + message = replacetext(message, "someone", "a") + return message + +/datum/emote/slap/doAction(var/mob/user, var/list/params) + if(user == params["target"]) + var/mob/living/U = user + U.adjustFireLoss(4) + +/datum/emote/smile + name = "smile" + desc = "Makes the mob smile" + commands = list("smile", "smiles") + text = "smiles" + selfText = "smile" + +/datum/emote/smile/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/snap + name = "snap" + desc = "Makes the mob snap it's fingers" + commands = list("snap", "snaps") + text = "snaps" + selfText = "snap" + audible = 1 + sound = 'sound/effects/fingersnap.ogg' + +/datum/emote/snap/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/snap/prevented(var/mob/user) + . = ..() + if(.) + return + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/L = H.get_organ("l_hand") + var/obj/item/organ/external/R = H.get_organ("r_hand") + var/left_hand_good = 0 + var/right_hand_good = 0 + if(L && (!(L.status & ORGAN_DESTROYED)) && (!(L.status & ORGAN_SPLINTED)) && (!(L.status & ORGAN_BROKEN))) + left_hand_good = 1 + if(R && (!(R.status & ORGAN_DESTROYED)) && (!(R.status & ORGAN_SPLINTED)) && (!(R.status & ORGAN_BROKEN))) + right_hand_good = 1 + + if(!left_hand_good && !right_hand_good) + return "You need at least one hand in good working order to snap your fingers" + +/datum/emote/snap/standardMessage(var/mob/user, var/list/params) + var/message = ..() + message += " [getHis(user)] fingers" + params["prob"] = prob(5) + if(!params["prob"]) + return message + message += " right off!" + return message + +/datum/emote/snap/playSound(var/mob/user, var/list/params) + if(params["prob"]) + playsound(user.loc, 'sound/effects/snap.ogg', 50, 1) + return 1 + return ..() + +/datum/emote/snap/createBlindMessage(var/mob/user, var/list/params, var/message) + message = ..() + message += " their fingers" + return message + +/datum/emote/snap/createDeafMessage(var/mob/user, var/list/params, var/message) + return message + +/datum/emote/sneeze + name = "sneeze" + desc = "Makes the mob sneeze" + commands = list("sneeze", "sneezes") + text = "sneezes" + selfText = "sneeze" + audible = 1 + mimeText = "sneeze" + muzzleAffected = 1 + muzzledNoise = "strange" + +/datum/emote/sneeze/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/sniff + name = "sniff" + desc = "Makes the mob sniff" + commands = list("sniff", "sniffs") + text = "sniffs" + selfText = "sniff" + audible = 1 + mimeText = "sniffs" + +/datum/emote/sniff/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/snore + name = "snore" + desc = "Makes the mob snore" + commands = list("snore", "snores") + text = "snores" + selfText = "snore" + audible = 1 + mimeText = "sleeps soundly" + mimeSelf = "sleep soundly" + muzzleAffected = 1 + +/datum/emote/snore/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/squish + name = "squish" + desc = "Makes the mob squish" + commands = list("squish", "squishes") + text = "squishes" + selfText = "squish" + audible = 1 + sound = 'sound/effects/slime_squish.ogg' + canTarget = 1 + targetMob = 1 + +/datum/emote/squish/available(var/mob/user) + if(isslime(user)) + return 1 + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.species.name == "Slime People") //Only Slime People can squish + return 1 + for(var/obj/item/organ/external/L in H.organs) // if your limbs are squishy you can squish too! + if(L.dna.species =="Slime People") + return 1 + +/datum/emote/stare + name = "stare" + desc = "Makes the mob stare" + commands = list("stare", "stares") + text = "stares" + selfText = "stare" + canTarget = 1 + targetMob = 1 + +/datum/emote/stare/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/sulk + name = "sulk" + desc = "Makes the mob sulk" + commands = list("sulk", "sulks") + text = "sulks down sadly" + selfText = "sulk down sadly" + +/datum/emote/sulk/available(var/mob/user) + if(islarva(user)) + return 1 + +/datum/emote/sway + name = "sway" + desc = "Makes the mob sway" + commands = list("sway", "sways") + text = "sways around dizzily" + selfText = "sway around dizzily" + +/datum/emote/sway/available(var/mob/user) + if(islarva(user)) + return 1 + if(isslime(user)) + return 1 + +/datum/emote/tail + name = "tail" + desc = "Makes the mob wave it's tail" + commands = list("tail") + text = "waves it's tail" + selfText = "wave your tail" + +/datum/emote/tail/available(var/mob/user) + if(islarva(user) || isalienadult(user)) + return 1 + if(issmall(user)) + return 1 + +/datum/emote/tail/wag + name = "wag" + desc = "Makes the mob start wagging its tail" + commands = list("wag", "wags") + text = "starts" + selfText = "start" + +/datum/emote/tail/wag/available(var/mob/user) + if(issmall(user)) + return + if(ishuman(user)) + return 1 + +/datum/emote/tail/wag/prevented(var/mob/user) + . = ..() + if(.) + return + var/mob/living/carbon/human/H = user + if(H.species.bodyflags & TAIL_WAGGING) + if(H.wear_suit && (H.wear_suit.flags_inv & HIDETAIL || istype(H.wear_suit, /obj/item/clothing/suit/space))) + return "your clothing is stopping you wag your tail" + return + if(!H.body_accessory) + return "you have no tail to wag!" + if(!H.body_accessory.try_restrictions()) + return "your clothing is stopping you wag your tail" + +/datum/emote/tail/wag/standardMessage(var/mob/user, var/list/params) + var/message = ..() + message += " wagging [getHis(user)] tail" + return message + +/datum/emote/tail/wag/doAction(var/mob/user, var/list/params) + var/mob/living/carbon/human/H = user + H.start_tail_wagging(1) + +/datum/emote/tail/wag/stop + name = "swag" + desc = "Makes the mob stop wagging its tail" + commands = list("swag", "swags") + text = "stops" + selfText = "stop" + allowParent = 1 + +// seemingly no way to tell if a mob is wagging it's tail! VB +/datum/emote/tail/wag/stop/prevented(var/mob/user) + . = ..() + if(.) + return + var/mob/living/carbon/human/H = user + if(!(H.species.bodyflags & TAIL_WAGGING) && !H.body_accessory) + return "you can't stop wagging a tail you don't have!" + +/datum/emote/tail/wag/stop/doAction(var/mob/user, var/list/params) + var/mob/living/carbon/human/H = user + H.stop_tail_wagging(1) + +/datum/emote/tremble + name = "tremble" + desc = "Makes the mob tremble" + commands = list("tremble", "trembles") + text = "trembles" + selfText = "tremble" + +/datum/emote/tremble/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/twitch_s + name = "twitch_s" + desc = "Makes the mob twitch" + commands = list("twitch_s", "twitches_s") + text = "twitches" + selfText = "twitch" + +/datum/emote/twitch_s/available(var/mob/user) + if(ishuman(user)) + return 1 + if(isrobot(user)) + return 1 + +/datum/emote/twitch_s/twitch + name = "twitch" + desc = "Makes the mob twitch violently" + commands = list("twitch", "twitches") + allowParent = 1 + +/datum/emote/twitch_s/twitch/available(var/mob/user) + if(isslime(user)) + return 1 + if(islarva(user)) + return 1 + return ..() + +/datum/emote/twitch_s/twitch/standardMessage(var/mob/user, var/list/params) + var/message = ..() + message += " violently" + return message + +/datum/emote/vibrate + name = "vibrate" + desc = "Makes the mob vibrate" + commands = list("vibrate", "vibrates") + text = "vibrates" + selfText = "vibrate" + +/datum/emote/vibrate/available(var/mob/user) + if(isslime(user)) + return 1 + +/datum/emote/wave + name = "wave" + desc = "Makes the mob wave" + commands = list ("wave", "waves") + text = "waves" + selfText = "wave" + +/datum/emote/wave/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/whimper + name = "whimper" + desc = "Makes the mob whimper" + commands = list("whimper", "whimpers") + text = "whimpers" + selfText = "whimper" + audible = 1 + mimeText = "appears hurt" + mimeSelf = "appear hurt" + muzzleAffected = 1 + +/datum/emote/whimper/available(var/mob/user) + if(islarva(user) || isalienadult(user)) + return 1 + if(ishuman(user)) + return 1 + +/datum/emote/whistle + name = "whistle" + desc = "Makes the mob whistle" + commands = list("whistle", "whistles") + text = "whistles" + selfText = "whistle" + audible = 1 + +/datum/emote/whistle/available(var/mob/user) + if(isbrain(user)) + return 1 + +/datum/emote/wink + name = "wink" + desc = "Makes the mob wink" + commands = list("wink", "winks") + text = "winks" + selfText = "wink" + +/datum/emote/wink/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/yawn + name = "yawn" + desc = "makes the mob yawn" + commands = list("yawn", "yawns") + text = "yawns" + selfText = "yawn" + audible = 1 + mimeText = "yawns" + muzzleAffected = 1 + +/datum/emote/yawn/available(var/mob/user) + if(ishuman(user)) + return 1 + +/datum/emote/yes + name = "yes" + desc = "Makes the mob let out an affirmative beep" + commands = list("yes") + text = "lets out an affirmative beep" + selfText = "let out an affirmative beep" + audible = 1 + sound = 'sound/machines/synth_yes.ogg' + canTarget = 1 + targetMob = 1 + +/datum/emote/yes/available(var/mob/user) + if(user.is_mechanical()) + return 1 \ No newline at end of file diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 062b8441a30..3cb965964b3 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -54,6 +54,7 @@ qdel(W) continue W.layer = initial(W.layer) + W.plane = initial(W.plane) W.loc = affected_mob.loc W.dropped(affected_mob) var/mob/living/new_mob = new new_form(affected_mob.loc) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 0488f60ac03..e20144f564e 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -341,7 +341,7 @@ var/list/uplink_items = list() reference = "SPI" desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible with suppressors." item = /obj/item/weapon/gun/projectile/automatic/pistol - cost = 9 + cost = 4 /datum/uplink_item/dangerous/revolver name = "Syndicate .357 Revolver" @@ -693,7 +693,7 @@ var/list/uplink_items = list() desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the shots of the weapon for increased stealth and superior ambushing capability." reference = "US" item = /obj/item/weapon/suppressor - cost = 3 + cost = 1 surplus = 10 /datum/uplink_item/stealthy_weapons/pizza_bomb diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 6ad3a69258d..3ac3feb3bef 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -295,6 +295,10 @@ var/list/ghostteleportlocs = list() name = "\improper Special Ops Shuttle" icon_state = "shuttlered2" +/area/shuttle/syndicate_elite + name = "\improper Syndicate Elite Shuttle" + icon_state = "shuttlered" + /area/shuttle/syndicate_elite/mothership name = "\improper Syndicate Elite Shuttle" icon_state = "shuttlered" diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 13f334c010b..08784b71a61 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -116,11 +116,24 @@ //Skin tone. if(M.species.bodyflags & HAS_SKIN_TONE) - var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[M.s_tone]") as null|text - if (!new_tone) + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", M.s_tone) as null|text + if(!new_tone) new_tone = 35 M.s_tone = 35 - max(min(round(text2num(new_tone)), 220), 1) + if(M.species.bodyflags & HAS_ICON_SKIN_TONE) + var/prompt = "Please select skin tone: 1-[M.species.icon_skin_tones.len] (" + for(var/i = 1; i <= M.species.icon_skin_tones.len; i++) + prompt += "[i] = [M.species.icon_skin_tones[i]]" + if(i != M.species.icon_skin_tones.len) + prompt += ", " + prompt += ")" + + var/new_tone = input(prompt, "Character Generation", M.s_tone) as null|text + if(!new_tone) + new_tone = 0 + M.s_tone = max(min(round(text2num(new_tone)), M.species.icon_skin_tones.len), 1) + //Skin colour. if(M.species.bodyflags & HAS_SKIN_COLOR) var/new_body_colour = input("Please select body colour.", "Character Generation", rgb(M.r_skin, M.g_skin, M.b_skin)) as null|color diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 1238adebcf5..069edaa6ecf 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -103,9 +103,6 @@ if(isovermind(M) || isobserver(M)) M.show_message(rendered, 2) -/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null) - return - /mob/camera/blob/blob_act() return diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 83d21e8cfad..a4c4656391c 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -253,6 +253,7 @@ var/round_start_time = 0 cinematic.icon = 'icons/effects/station_explosion.dmi' cinematic.icon_state = "station_intact" cinematic.layer = 20 + cinematic.plane = HUD_PLANE cinematic.mouse_opacity = 0 cinematic.screen_loc = "1,0" diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 952b43d5f37..6079a3c1a2e 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -84,7 +84,6 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' /datum/game_mode/proc/create_vox(var/datum/mind/newraider) - var/sounds = rand(2,8) var/i = 0 var/newname = "" @@ -97,10 +96,12 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' var/obj/item/organ/external/head/head_organ = vox.get_organ("head") vox.real_name = capitalize(newname) + vox.dna.real_name = vox.real_name vox.name = vox.real_name newraider.name = vox.name vox.age = rand(12,20) vox.set_species("Vox") + vox.s_tone = rand(1, 6) vox.languages = list() // Removing language from chargen. vox.flavor_text = "" vox.add_language("Vox-pidgin") @@ -108,6 +109,16 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' vox.add_language("Tradeband") head_organ.h_style = "Short Vox Quills" head_organ.f_style = "Shaved" + vox.change_hair_color(97, 79, 25) //Same as the species default colour. + vox.change_eye_color(rand(1, 255), rand(1, 255), rand(1, 255)) + vox.underwear = "Nude" + vox.undershirt = "Nude" + vox.socks = "Nude" + + // Do the initial caching of the player's body icons. + vox.force_update_limbs() + vox.update_dna() + vox.update_eyes() for(var/obj/item/organ/external/limb in vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 1a0d7770a1a..50dcc0d62d1 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -33,9 +33,6 @@ return 0 return B.host.say_understands(other, speaking) -/mob/living/captive_brain/emote(var/message) - return - /mob/living/captive_brain/resist_borer() var/mob/living/simple_animal/borer/B = loc diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm index d836511fc42..f0e0dc1a883 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm @@ -238,7 +238,8 @@ action_icon_state = "defile" var/stamdamage= 25 var/toxdamage = 5 - var/confusion = 50 + var/confusion = 20 + var/maxconfusion = 30 /obj/effect/proc_holder/spell/aoe_turf/revenant/defile/cast(list/targets, mob/living/simple_animal/revenant/user = usr) if(attempt_cast(user)) @@ -251,7 +252,7 @@ to_chat(human, "You suddenly feel [pick("sick and tired", "tired and confused", "nauseated", "dizzy")].") human.adjustStaminaLoss(stamdamage) human.adjustToxLoss(toxdamage) - human.confused += confusion + human.confused = min(human.confused+confusion, maxconfusion) new/obj/effect/overlay/temp/revenant(human.loc) if(!istype(T, /turf/simulated/shuttle) && !istype(T, /turf/simulated/wall/rust) && !istype(T, /turf/simulated/wall/r_wall) && istype(T, /turf/simulated/wall) && prob(15)) new/obj/effect/overlay/temp/revenant(T) @@ -281,7 +282,7 @@ name = "Malfunction" desc = "Corrupts and damages nearby machines and mechanical objects." charge_max = 200 - range = 4 + range = 2 cast_amount = 45 unlock_amount = 150 action_icon_state = "malfunction" diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index aae6d31261a..72fa2b8dbbe 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -651,32 +651,7 @@ datum return 10 else return 20 - - - RCD - steal_target = /obj/item/weapon/rcd - explanation_text = "Steal a rapid construction device." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - + /*burger steal_target = /obj/item/weapon/reagent_containers/food/snacks/human/burger diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 6ef7350e4ad..19d725f8677 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -251,7 +251,7 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ /datum/objective/hijack martyr_compatible = 0 //Technically you won't get both anyway. - explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive." + explanation_text = "Hijack the shuttle by escaping on it with no loyalist NanoTrasen crew on board and alive. Syndicate agents, other enemies of NanoTrasen, cyborgs, and pets may be allowed to escape alive." check_completion() if(!owner.current || owner.current.stat) @@ -311,7 +311,7 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ return 0 /datum/objective/block - explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive." + explanation_text = "Do not allow any lifeforms, be it organic or synthetic to escape on the shuttle alive. AIs, Cyborgs, and pAIs are not considered alive." martyr_compatible = 1 check_completion() @@ -668,7 +668,7 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ if(5) target = /obj/item/weapon/gun target_amount = 6 - loot = "six guns" + loot = "six guns. Tasers and other non-lethal guns are acceptable" if(6) target = /obj/item/weapon/gun/energy target_amount = 4 @@ -797,15 +797,9 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ return 1 return 0 -#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken. - //Would be nice to use vox-specific kills but is currently not feasible. -var/global/vox_kills = 0 //Used to check the Inviolate. - /datum/objective/heist/inviolate_death explanation_text = "Follow the Inviolate. Minimise death and loss of resources." - check_completion() - if(vox_kills > MAX_VOX_KILLS) return 0 - return 1 + completed = 1 // Traders diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index 4d061d37eca..e4f7bc15657 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -64,27 +64,35 @@ datum/hSB if(P.wear_suit) P.wear_suit.loc = P.loc P.wear_suit.layer = initial(P.wear_suit.layer) + P.wear_suit.plane = initial(P.wear_suit.plane) P.wear_suit = null P.wear_suit = new/obj/item/clothing/suit/space(P) P.wear_suit.layer = 20 + P.wear_suit.plane = HUD_PLANE if(P.head) P.head.loc = P.loc P.head.layer = initial(P.head.layer) + P.head.plane = initial(P.head.plane) P.head = null P.head = new/obj/item/clothing/head/helmet/space(P) P.head.layer = 20 + P.head.plane = HUD_PLANE if(P.wear_mask) P.wear_mask.loc = P.loc P.wear_mask.layer = initial(P.wear_mask.layer) + P.wear_mask.plane = initial(P.wear_mask.plane) P.wear_mask = null P.wear_mask = new/obj/item/clothing/mask/gas(P) P.wear_mask.layer = 20 + P.wear_mask.plane = HUD_PLANE if(P.back) P.back.loc = P.loc P.back.layer = initial(P.back.layer) + P.back.plane = initial(P.back.plane) P.back = null P.back = new/obj/item/weapon/tank/jetpack(P) P.back.layer = 20 + P.back.plane = HUD_PLANE P.internal = P.back if("hsbmetal") var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/metal diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index 25d2807432e..d81b50c1922 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -43,11 +43,6 @@ typepath = /obj/item/weapon/hand_tele protected_jobs = list("Captain", "Research Director") -/datum/theft_objective/rcd - name = "a rapid-construction-device" - typepath = /obj/item/weapon/rcd - protected_jobs = list("Chief Engineer", "Quartermaster", "Cargo Technician", "Research Director", "Scientist", "Roboticist") - /datum/theft_objective/jetpack name = "a jetpack" typepath = /obj/item/weapon/tank/jetpack @@ -124,6 +119,11 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/device/aicard/C) typepath = /obj/item/clothing/suit/armor/laserproof protected_jobs = list("Head of Security", "Warden") +/datum/theft_objective/krav + name = "the warden's krav maga martial arts gloves" + typepath = /obj/item/clothing/gloves/color/black/krav_maga/sec + protected_jobs = list("Head Of Security", "Warden") + /datum/theft_objective/number var/min=0 var/max=0 diff --git a/code/game/gamemodes/vampire/traitor_vamp.dm b/code/game/gamemodes/vampire/traitor_vamp.dm index 9d4cb42b545..a5f2613dccc 100644 --- a/code/game/gamemodes/vampire/traitor_vamp.dm +++ b/code/game/gamemodes/vampire/traitor_vamp.dm @@ -2,12 +2,12 @@ name = "traitor+vampire" config_tag = "traitorvamp" traitors_possible = 3 //hard limit on traitors if scaling is turned off + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent") restricted_jobs = list("AI", "Cyborg") required_players = 10 required_enemies = 1 // how many of each type are required recommended_enemies = 3 var/protected_species_vampire = list("Machine") - var/special_job_protection = list("Chaplain") //this must exist or else Chaplain can role for Vampire. That said, we don't want to rule out him getting traitor, either /datum/game_mode/traitor/vampire/announce() to_chat(world, "The current game mode is - Traitor+Vampire!") @@ -23,8 +23,6 @@ for(var/mob/new_player/player in player_list) if((player.mind in possible_vampires) && (player.client.prefs.species in protected_species_vampire)) possible_vampires -= player.mind - if((player.mind in possible_vampires) && (player.mind.assigned_role in special_job_protection)) - possible_vampires -= player.mind if(possible_vampires.len > 0) var/datum/mind/vampire = pick(possible_vampires) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 1f8bbc44587..1a7fffcc6ea 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -4,6 +4,7 @@ //Potential replacement for genetics revives or something I dunno (?) #define CLONE_BIOMASS 150 +#define BIOMASS_MEAT_AMOUNT 50 /obj/machinery/clonepod anchored = 1 @@ -292,6 +293,13 @@ //Grow clones to maturity then kick them out. FREELOADERS /obj/machinery/clonepod/process() + var/show_message = 0 + for(var/obj/item/weapon/reagent_containers/food/snacks/meat/meat in range(1, src)) + qdel(meat) + biomass += BIOMASS_MEAT_AMOUNT + show_message = 1 + if(show_message) + visible_message("\The [src] sucks in and processes the nearby biomass.") if(stat & NOPOWER) //Autoeject if power is lost if (occupant) @@ -373,7 +381,7 @@ //Removing cloning pod biomass else if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) to_chat(user, "\blue \The [src] processes \the [W].") - biomass += 50 + biomass += BIOMASS_MEAT_AMOUNT user.drop_item() qdel(W) return diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 68ff1bf64c1..f7de2dd6b5f 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -28,17 +28,6 @@ var/storage_name = "Cryogenic Oversight Control" var/allow_items = 1 -/obj/machinery/computer/cryopod/robot - name = "robotic storage console" - desc = "An interface between crew and the robotic storage systems" - icon = 'icons/obj/robot_storage.dmi' - icon_state = "console" - circuit = /obj/item/weapon/circuitboard/robotstoragecontrol - - storage_type = "cyborgs" - storage_name = "Robotic Storage Control" - allow_items = 0 - /obj/machinery/computer/cryopod/attack_ai() src.attack_hand() @@ -146,7 +135,6 @@ //Decorative structures to go alongside cryopods. /obj/structure/cryofeed - name = "cryogenic feed" desc = "A bewildering tangle of machinery and pipes." icon = 'icons/obj/Cryogenic2.dmi' @@ -218,23 +206,6 @@ orient_right = 1 icon_state = "body_scanner_0-r" -/obj/machinery/cryopod/robot - name = "robotic storage unit" - desc = "A storage unit for robots." - icon = 'icons/obj/robot_storage.dmi' - icon_state = "pod_0" - base_icon_state = "pod_0" - occupied_icon_state = "pod_1" - on_store_message = "has entered robotic storage." - on_store_name = "Robotic Storage Oversight" - on_enter_occupant_message = "The storage unit broadcasts a sleep signal to you. Your systems start to shut down, and you enter low-power mode." - allow_occupant_types = list(/mob/living/silicon/robot) - disallow_occupant_types = list(/mob/living/silicon/robot/drone) - -/obj/machinery/cryopod/robot/right - orient_right = 1 - icon_state = "pod_0-r" - /obj/machinery/cryopod/New() announce = new /obj/item/device/radio/intercom(src) @@ -296,22 +267,6 @@ despawn_occupant() -// This function can not be undone; do not call this unless you are sure -// Also make sure there is a valid control computer -/obj/machinery/cryopod/robot/despawn_occupant() - var/mob/living/silicon/robot/R = occupant - if(!istype(R)) return ..() - - R.contents -= R.mmi - qdel(R.mmi) - for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc - for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags - O.loc = R - qdel(I) - qdel(R.module) - - return ..() - // This function can not be undone; do not call this unless you are sure // Also make sure there is a valid control computer /obj/machinery/cryopod/proc/despawn_occupant() @@ -406,11 +361,6 @@ else icon_state = base_icon_state - //TODO: Check objectives/mode, update new targets if this mob is the target, spawn new antags? - - //This should guarantee that ghosts don't spawn. - occupant.ckey = null - //Make an announcement and log the person entering storage. control_computer.frozen_crew += "[occupant.real_name]" @@ -682,7 +632,6 @@ return /obj/machinery/cryopod/proc/go_out() - if(!occupant) return @@ -704,3 +653,45 @@ //Attacks/effects. /obj/machinery/cryopod/blob_act() return //Sorta gamey, but we don't really want these to be destroyed. + +/obj/machinery/computer/cryopod/robot + name = "robotic storage console" + desc = "An interface between crew and the robotic storage systems" + icon = 'icons/obj/robot_storage.dmi' + icon_state = "console" + circuit = /obj/item/weapon/circuitboard/robotstoragecontrol + + storage_type = "cyborgs" + storage_name = "Robotic Storage Control" + allow_items = 0 + +/obj/machinery/cryopod/robot + name = "robotic storage unit" + desc = "A storage unit for robots." + icon = 'icons/obj/robot_storage.dmi' + icon_state = "pod_0" + base_icon_state = "pod_0" + occupied_icon_state = "pod_1" + on_store_message = "has entered robotic storage." + on_store_name = "Robotic Storage Oversight" + on_enter_occupant_message = "The storage unit broadcasts a sleep signal to you. Your systems start to shut down, and you enter low-power mode." + allow_occupant_types = list(/mob/living/silicon/robot) + disallow_occupant_types = list(/mob/living/silicon/robot/drone) + +/obj/machinery/cryopod/robot/right + orient_right = 1 + icon_state = "pod_0-r" + +/obj/machinery/cryopod/robot/despawn_occupant() + var/mob/living/silicon/robot/R = occupant + if(!istype(R)) return ..() + + R.contents -= R.mmi + qdel(R.mmi) + for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc + for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags + O.loc = R + qdel(I) + qdel(R.module) + + return ..() diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm index 57e1aecf514..881c0536803 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -29,6 +29,28 @@ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) rating_speed = M.rating +/obj/machinery/processor/process() + ..() + // The irony + // To be clear, if it's grinding, then it can't suck them up + if(processing) + return + var/mob/living/carbon/slime/picked_slime + for(var/mob/living/carbon/slime/slime in range(1, src)) + if(slime.loc == src) + continue + if(slime.stat) + picked_slime = slime + break + if(!picked_slime) + return + var/datum/food_processor_process/P = select_recipe(picked_slime) + if (!P) + return + + visible_message("[picked_slime] is sucked into \the [src].") + picked_slime.forceMove(src) + //RECIPE DATUMS /datum/food_processor_process var/input diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index 2b56b71fc43..6a4da6412f3 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -184,6 +184,7 @@ qdel(J) H.icon = HI H.layer = 25 + H.plane = HUD_PLANE usr.mapobjs += H #else @@ -308,6 +309,7 @@ H.icon = I qdel(I) H.layer = 25 + H.plane = HUD_PLANE usr.mapobjs += H #endif diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 9bcf3de53a8..2db551b67fa 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -129,7 +129,7 @@ var/const/SAFETY_COOLDOWN = 100 return if(sound) - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + playsound(src.loc, 'sound/machines/recycler.ogg', 100, 0) var/material_amount = materials.get_item_material_amount(I) if(!material_amount) qdel(I) @@ -155,7 +155,7 @@ var/const/SAFETY_COOLDOWN = 100 L.loc = src.loc if(issilicon(L)) - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + playsound(src.loc, 'sound/machines/recycler.ogg', 100, 0) else playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) @@ -219,4 +219,4 @@ var/const/SAFETY_COOLDOWN = 100 /obj/item/weapon/paper/recycler name = "paper - 'garbage duty instructions'" - info = "

New Assignment

You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.

There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!" \ No newline at end of file + info = "

New Assignment

You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.

There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!" diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index fe443662616..96db973ab21 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -10,7 +10,7 @@ unacidable = 1 var/datum/wires/syndicatebomb/wires = null - var/timer = 60 + var/timer = 120 var/open_panel = 0 //are the wires exposed? var/active = 0 //is the bomb counting down? var/defused = 0 //is the bomb capable of exploding? @@ -19,12 +19,12 @@ /obj/machinery/syndicatebomb/process() if(active && !defused && (timer > 0)) //Tick Tock - var/volume = (timer <= 10 ? 40 : 10) // Tick louder when the bomb is closer to being detonated. + var/volume = (timer <= 20 ? 40 : 10) // Tick louder when the bomb is closer to being detonated. playsound(loc, beepsound, volume, 0) - timer-- + timer = max(timer - 2,0) // 2 seconds per process() if(active && !defused && (timer <= 0)) //Boom active = 0 - timer = 60 + timer = 120 update_icon() if(payload in src) payload.detonate() @@ -123,7 +123,7 @@ /obj/machinery/syndicatebomb/proc/settings(var/mob/user) var/newtime = input(user, "Please set the timer.", "Timer", "[timer]") as num - newtime = Clamp(newtime, 60, 60000) + newtime = Clamp(newtime, 120, 60000) if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station timer = newtime src.loc.visible_message("\icon[src] timer set for [timer] seconds.") diff --git a/code/game/objects/effects/biomass_rift.dm b/code/game/objects/effects/biomass_rift.dm index 247f485b570..5b4cf9970a5 100644 --- a/code/game/objects/effects/biomass_rift.dm +++ b/code/game/objects/effects/biomass_rift.dm @@ -6,6 +6,7 @@ density = 0 anchored = 1 layer = 20 //DEBUG + plane = HUD_PLANE //DEBUG var/health = 10 var/stage = 1 var/obj/effect/rift/originalRift = null //the originating rift of that biomass diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 9445b5aa626..6bcfb253454 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -12,6 +12,7 @@ density = 0 anchored = 1 layer = 50 + plane = HUD_PLANE /obj/effect/decal/chempuff name = "chemicals" diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index bc697657b98..a635d2fdad9 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -31,6 +31,7 @@ icon_state = "blank" anchored = 1 layer = 99 + plane = HUD_PLANE mouse_opacity = 0 unacidable = 1//Just to be sure. diff --git a/code/game/objects/items/devices/autopsy.dm b/code/game/objects/items/devices/autopsy.dm index 25e4d12614d..be4009b0ed9 100644 --- a/code/game/objects/items/devices/autopsy.dm +++ b/code/game/objects/items/devices/autopsy.dm @@ -165,10 +165,12 @@ P.loc = usr usr.r_hand = P P.layer = 20 + P.plane = HUD_PLANE else if(!usr.l_hand) P.loc = usr usr.l_hand = P P.layer = 20 + P.plane = HUD_PLANE if(istype(usr,/mob/living/carbon/human)) usr:update_inv_l_hand() diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index 9b02799e496..575680f28ac 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -1,38 +1,45 @@ /obj/item/latexballon - name = "Latex glove" + name = "latex glove" desc = "" //todo icon_state = "latexballon" item_state = "lgloves" force = 0 throwforce = 0 - w_class = 1.0 + w_class = 1 throw_speed = 1 - throw_range = 15 + throw_range = 7 var/state var/datum/gas_mixture/air_contents = null -/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank) - if (icon_state == "latexballon_bursted") +/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank, mob/user) + if(icon_state == "latexballon_bursted") return - src.air_contents = tank.remove_air_volume(3) icon_state = "latexballon_blow" item_state = "latexballon" + user.update_inv_r_hand() + user.update_inv_l_hand() + to_chat(user, "You blow up [src] with [tank].") + air_contents = tank.remove_air_volume(3) /obj/item/latexballon/proc/burst() - if (!air_contents) + if(!air_contents || icon_state != "latexballon_blow") return playsound(src, 'sound/weapons/Gunshot.ogg', 100, 1) icon_state = "latexballon_bursted" item_state = "lgloves" + if(isliving(loc)) + var/mob/living/user = loc + user.update_inv_r_hand() + user.update_inv_l_hand() loc.assume_air(air_contents) /obj/item/latexballon/ex_act(severity) burst() switch(severity) - if (1) + if(1) qdel(src) - if (2) - if (prob(50)) + if(2) + if(prob(50)) qdel(src) /obj/item/latexballon/bullet_act() @@ -43,6 +50,10 @@ burst() return -/obj/item/latexballon/attackby(obj/item/W as obj, mob/user as mob, params) - if (can_puncture(W)) +/obj/item/latexballon/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/weapon/tank)) + var/obj/item/weapon/tank/T = W + blow(T, user) + return + if(is_sharp(W) || is_hot(W) || can_puncture(W)) burst() \ No newline at end of file diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 2cc37b0ba85..3e8e5f13c2a 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -331,6 +331,8 @@ H.updatehealth() //forces health update before next life tick playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) H.emote("gasp") + if(!H.heart_attack && (prob(10) || defib.combat)) // Your heart explodes. + H.heart_attack = 1 add_logs(M, user, "stunned", object="defibrillator") defib.deductcharge(revivecost) cooldown = 1 @@ -354,8 +356,8 @@ qdel(ghost) ghost = null var/tplus = world.time - H.timeofdeath - var/tlimit = 6000 //past this much time the patient is unrecoverable (in deciseconds) - var/tloss = 3000 //brain damage starts setting in on the patient after some time left rotting + var/tlimit = 1800 //past this much time the patient is unrecoverable (in deciseconds) + var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting var/total_burn = 0 var/total_brute = 0 if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total @@ -470,6 +472,8 @@ H.adjustStaminaLoss(50) H.Weaken(5) H.updatehealth() //forces health update before next life tick + if(!H.heart_attack && prob(10)) // Your heart explodes. + H.heart_attack = 1 playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) H.emote("gasp") add_logs(M, user, "stunned", object="defibrillator") @@ -499,8 +503,8 @@ qdel(ghost) ghost = null var/tplus = world.time - H.timeofdeath - var/tlimit = 6000 //past this much time the patient is unrecoverable (in deciseconds) - var/tloss = 3000 //brain damage starts setting in on the patient after some time left rotting + var/tlimit = 1800 //past this much time the patient is unrecoverable (in deciseconds) + var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting var/total_burn = 0 var/total_brute = 0 if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total diff --git a/code/game/objects/items/weapons/misc.dm b/code/game/objects/items/weapons/misc.dm index 15048ae13b5..ebe8ecb421d 100644 --- a/code/game/objects/items/weapons/misc.dm +++ b/code/game/objects/items/weapons/misc.dm @@ -127,10 +127,16 @@ icon = 'icons/obj/items.dmi' icon_state = "red_phone" flags = CONDUCT - force = 3.0 - throwforce = 2.0 + force = 3 + throwforce = 2 throw_speed = 1 throw_range = 4 w_class = 2 attack_verb = list("called", "rang") - hitsound = 'sound/weapons/ring.ogg' \ No newline at end of file + hitsound = 'sound/weapons/ring.ogg' + var/cooldown = 0 + +/obj/item/weapon/phone/attack_self(mob/user) + if(cooldown < world.time - 20) + playsound(user.loc, 'sound/weapons/ring.ogg', 50, 1) + cooldown = world.time \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/artistic_toolbox.dm b/code/game/objects/items/weapons/storage/artistic_toolbox.dm index 1b9be2bec62..56a3279dde0 100644 --- a/code/game/objects/items/weapons/storage/artistic_toolbox.dm +++ b/code/game/objects/items/weapons/storage/artistic_toolbox.dm @@ -135,6 +135,7 @@ affected_mob.adjustBruteLoss(-12) affected_mob.adjustFireLoss(-12) affected_mob.adjustToxLoss(-5) + affected_mob.setStaminaLoss(0) var/status = CANSTUN | CANWEAKEN | CANPARALYSE affected_mob.status_flags &= ~status affected_mob.dizziness = max(0, affected_mob.dizziness-10) diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 1dde63d198a..af927acf19a 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -20,34 +20,34 @@ attackby(obj/item/weapon/W as obj, mob/user as mob, params) if (istype(W, /obj/item/weapon/card/id)) if(src.broken) - to_chat(user, "\red It appears to be broken.") + to_chat(user, "It appears to be broken.") return if(src.allowed(user)) src.locked = !( src.locked ) if(src.locked) src.icon_state = src.icon_locked - to_chat(user, "\red You lock the [src.name]!") + to_chat(user, "You lock the [src.name]!") return else src.icon_state = src.icon_closed - to_chat(user, "\red You unlock the [src.name]!") + to_chat(user, "You unlock the [src.name]!") 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 else - to_chat(user, "\red Access Denied") + to_chat(user, "Access Denied") else if((istype(W, /obj/item/weapon/card/emag) || istype(W, /obj/item/weapon/melee/energy/blade)) && !broken) emag_act(user) return if(!locked) ..() else - to_chat(user, "\red Its locked!") + to_chat(user, "It's locked!") return show_to(mob/user as mob) if(locked) - to_chat(user, "\red Its locked!") + to_chat(user, "It's locked!") else ..() return diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index 59fac1b18c4..dba3fb620e3 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -156,14 +156,19 @@ // ----------------------------- /obj/item/weapon/storage/secure/briefcase name = "secure briefcase" + desc = "A large briefcase with a digital locking system." icon = 'icons/obj/storage.dmi' icon_state = "secure" item_state = "sec-case" - desc = "A large briefcase with a digital locking system." + flags = CONDUCT + hitsound = "swing_hit" force = 8.0 - throw_speed = 1 + throw_speed = 2 throw_range = 4 w_class = 4.0 + max_w_class = 3 + max_combined_w_class = 21 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") New() ..() diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index d92ad2399b2..9bbc26017be 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -151,6 +151,7 @@ for(var/obj/O in src.contents) O.screen_loc = "[cx],[cy]" O.layer = 20 + O.plane = HUD_PLANE cx++ if (cx > mx) cx = tx @@ -170,6 +171,7 @@ ND.sample_object.screen_loc = "[cx]:16,[cy]:16" ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" ND.sample_object.layer = 20 + ND.sample_object.plane = HUD_PLANE cx++ if (cx > (4+cols)) cx = 4 @@ -180,6 +182,7 @@ O.screen_loc = "[cx]:16,[cy]:16" O.maptext = "" O.layer = 20 + O.plane = HUD_PLANE cx++ if (cx > (4+cols)) cx = 4 @@ -337,8 +340,10 @@ W.dropped(usr) if(ismob(new_location)) W.layer = 20 + W.plane = HUD_PLANE else W.layer = initial(W.layer) + W.plane = initial(W.plane) W.loc = new_location else W.loc = get_turf(src) @@ -445,6 +450,7 @@ src.closer.master = src src.closer.icon_state = "x" src.closer.layer = 20 + src.closer.plane = HUD_PLANE orient2hud() return diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 46342d78a99..b86ccbff3cf 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -89,10 +89,6 @@ if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) atmosanalyzer_scan(air_contents, user) - else if (istype(W,/obj/item/latexballon)) - var/obj/item/latexballon/LB = W - LB.blow(src) - if(istype(W, /obj/item/device/assembly_holder)) bomb_assemble(W,user) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 42a2541f0bf..44048f5113c 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -418,4 +418,9 @@ if(istype(src.loc, /obj/structure/bigDelivery)) //nullspace ect.. read the comment above var/obj/structure/bigDelivery/BD = src.loc BD.attack_hand(usr) - open() \ No newline at end of file + open() + +/obj/structure/closet/tesla_act(var/power) + ..() + visible_message("[src] is blown apart by the bolt of electricity!", "You hear a metallic screeching sound.") + qdel(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index fd7989e2457..63b0a36a7a4 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -157,6 +157,7 @@ new /obj/item/weapon/gun/energy/gun/advtaser(src) new /obj/item/weapon/storage/belt/security/sec(src) new /obj/item/weapon/storage/box/holobadge(src) + new /obj/item/clothing/gloves/color/black/krav_maga/sec(src) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 266baab7f3b..b857a6bb6cd 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -53,6 +53,9 @@ new /obj/item/clothing/head/beret/sec(src) new /obj/item/clothing/head/beret/sec(src) new /obj/item/clothing/head/beret/sec(src) + new /obj/item/clothing/head/officer(src) + new /obj/item/clothing/head/officer(src) + new /obj/item/clothing/head/officer(src) /obj/structure/closet/redcorp name = "corporate security wardrobe" diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 39fb502d10b..133a3d15b39 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -3,6 +3,7 @@ desc = "A sturdy metal ladder." icon = 'icons/obj/structures.dmi' icon_state = "ladder11" + anchored = 1 var/id = null var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher var/obj/structure/ladder/down = null //the ladder below this one diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 3fcfc0ef4bf..efef25723a5 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -63,8 +63,11 @@ return var/obj/item/weapon/reagent_containers/RG = I if(RG.is_open_container()) - RG.reagents.add_reagent("toiletwater", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) - to_chat(user, "You fill [RG] from [src]. Gross.") + if(RG.reagents.total_volume >= RG.volume) + to_chat(user, "\The [RG] is full.") + else + RG.reagents.add_reagent("toiletwater", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) + to_chat(user, "You fill [RG] from [src]. Gross.") return if(istype(I, /obj/item/weapon/grab)) diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm index a99c18ab230..5c9509a3d68 100644 --- a/code/game/turfs/unsimulated.dm +++ b/code/game/turfs/unsimulated.dm @@ -7,6 +7,12 @@ /turf/unsimulated/can_lay_cable() return 0 +/turf/unsimulated/floor/plating/vox + icon_state = "plating" + name = "plating" + nitrogen = 100 + oxygen = 0 + /turf/unsimulated/floor/plating/snow name = "snow" icon = 'icons/turf/snow.dmi' diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm index b4e8842a840..f63535fb082 100644 --- a/code/game/turfs/unsimulated/floor.dm +++ b/code/game/turfs/unsimulated/floor.dm @@ -35,4 +35,9 @@ /turf/unsimulated/floor/abductor/New() ..() - icon_state = "alienpod[rand(1,9)]" \ No newline at end of file + icon_state = "alienpod[rand(1,9)]" + +/turf/unsimulated/floor/vox + icon_state = "dark" + nitrogen = 100 + oxygen = 0 \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index ef5d4bf3de3..9d5a0503298 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -158,7 +158,8 @@ var/list/admin_verbs_debug = list( /client/proc/cinematic, /proc/machine_upgrade, /client/proc/map_template_load, - /client/proc/map_template_upload + /client/proc/map_template_upload, + /client/proc/view_runtimes ) var/list/admin_verbs_possess = list( /proc/possess, diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index dc7cc24d6b7..3f2ae5b7f61 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1205,6 +1205,7 @@ if(I) I.loc = locker I.layer = initial(I.layer) + I.plane = initial(I.plane) I.dropped(M) M.update_icons() @@ -1266,6 +1267,7 @@ if(I) I.loc = M.loc I.layer = initial(I.layer) + I.plane = initial(I.plane) I.dropped(M) M.Paralyse(5) @@ -1295,6 +1297,7 @@ if(I) I.loc = M.loc I.layer = initial(I.layer) + I.plane = initial(I.plane) I.dropped(M) M.Paralyse(5) @@ -1346,6 +1349,7 @@ if(I) I.loc = M.loc I.layer = initial(I.layer) + I.plane = initial(I.plane) I.dropped(M) if(istype(M, /mob/living/carbon/human)) @@ -2264,6 +2268,7 @@ W.loc = H.loc W.dropped(H) W.layer = initial(W.layer) + W.plane = initial(W.plane) //teleport person to cell H.loc = pick(prisonwarp) H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) @@ -2930,6 +2935,16 @@ Secrets(usr) return 1 + else if(href_list["viewruntime"]) + var/datum/ErrorViewer/error_viewer = locate(href_list["viewruntime"]) + if(!istype(error_viewer)) + to_chat(usr, "That runtime viewer no longer exists.") + return + if(href_list["viewruntime_backto"]) + error_viewer.showTo(usr, locate(href_list["viewruntime_backto"]), href_list["viewruntime_linear"]) + else + error_viewer.showTo(usr, null, href_list["viewruntime_linear"]) + /proc/admin_jump_link(var/atom/target, var/source) if(!target) return // The way admin jump links handle their src is weirdly inconsistent... diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index e02ac49b821..b85d19451fe 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1234,3 +1234,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that // Clear the user's cache so they get resent. usr.client.cache = list() + +/client/proc/view_runtimes() + set category = "Debug" + set name = "View Runtimes" + set desc = "Open the Runtime Viewer" + + if(!check_rights(R_DEBUG)) + return + + error_cache.showTo(usr) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 46972243a06..5fb8335732d 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -485,6 +485,8 @@ client/proc/one_click_antag() break new_vox.key = theghost.key + ticker.mode.traitors += new_vox.mind + to_chat(new_vox, "\blue You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: \red [input]") to_chat(new_vox, "\red Don't forget to turn on your nitrogen internals!") @@ -497,9 +499,6 @@ client/proc/one_click_antag() /datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) - var/mob/living/carbon/human/new_vox = new(spawn_location.loc, "Vox") - var/obj/item/organ/external/head/head_organ = new_vox.get_organ("head") - var/sounds = rand(2,8) var/i = 0 var/newname = "" @@ -508,17 +507,21 @@ client/proc/one_click_antag() i++ newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) + var/mob/living/carbon/human/new_vox = new /mob/living/carbon/human/vox(spawn_location.loc) + + new_vox.add_language("Tradeband") new_vox.real_name = capitalize(newname) + new_vox.dna.real_name = new_vox.real_name new_vox.name = new_vox.real_name new_vox.age = rand(12,20) - new_vox.set_species("Vox") - new_vox.languages = list() // Removing language from chargen. new_vox.flavor_text = "" - new_vox.add_language("Vox-pidgin") - new_vox.add_language("Galactic Common") - new_vox.add_language("Tradeband") - head_organ.h_style = "Short Vox Quills" - head_organ.f_style = "Shaved" + new_vox.change_eye_color(rand(1, 255), rand(1, 255), rand(1, 255)) + new_vox.s_tone = rand(1, 6) + + // Do the initial caching of the player's body icons. + new_vox.force_update_limbs() + new_vox.update_dna() + new_vox.update_eyes() for(var/obj/item/organ/external/limb in new_vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) @@ -529,8 +532,8 @@ client/proc/one_click_antag() I.implanted = 1 cortical_stacks += I - ticker.mode.traitors += new_vox.mind new_vox.equip_vox_raider() + new_vox.regenerate_icons() return new_vox diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index b57968ba38d..e9405cb372a 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -266,8 +266,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "N2 Tank: [speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]
" dat += "Secondary Language: [language]
" dat += "Blood Type: [b_type]
" - if(species in list("Human", "Drask")) - dat += "Skin Tone: [-s_tone + 35]/220
" + if(species in list("Human", "Drask", "Vox")) + dat += "Skin Tone: [species == "Vox" ? "[s_tone]" : "[-s_tone + 35]/220"]
" dat += "Disabilities: \[Set\]
" dat += "Nanotrasen Relation: [nanotrasen_relation]
" dat += "Set Flavor Text
" @@ -1102,16 +1102,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("age") age = rand(AGE_MIN, AGE_MAX) if("hair") - if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Machine" || species == "Wryn" || species == "Vulpkanin") + if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) r_hair = rand(0,255) g_hair = rand(0,255) b_hair = rand(0,255) if("h_style") h_style = random_hair_style(gender, species) if("facial") - r_facial = rand(0,255) - g_facial = rand(0,255) - b_facial = rand(0,255) + if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) + r_facial = rand(0,255) + g_facial = rand(0,255) + b_facial = rand(0,255) if("f_style") f_style = random_facial_hair_style(gender, species) if("underwear") @@ -1128,10 +1129,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts g_eyes = rand(0,255) b_eyes = rand(0,255) if("s_tone") - if(species in list("Human", "Drask")) + if(species in list("Human", "Drask", "Vox")) s_tone = random_skin_tone() if("s_color") - if(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Wyrn", "Vulpkanin", "Machine")) + if(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Wryn", "Vulpkanin", "Machine")) r_skin = rand(0,255) g_skin = rand(0,255) b_skin = rand(0,255) @@ -1233,6 +1234,11 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts s_tone = 0 + if(!(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine"))) + r_skin = 0 + g_skin = 0 + b_skin = 0 + ha_style = "None" // No Vulp ears on Unathi m_style = "None" // No Unathi markings on Tajara @@ -1277,7 +1283,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_type = new_b_type if("hair") - if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Machine" || species == "Vulpkanin") + if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) var/input = "Choose your character's hair colour:" var/new_hair = input(user, input, "Character Preference", rgb(r_hair, g_hair, b_hair)) as color|null if(new_hair) @@ -1396,11 +1402,12 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts body_accessory = (new_body_accessory == "None") ? null : new_body_accessory if("facial") - var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", rgb(r_facial, g_facial, b_facial)) as color|null - if(new_facial) - r_facial = hex2num(copytext(new_facial, 2, 4)) - g_facial = hex2num(copytext(new_facial, 4, 6)) - b_facial = hex2num(copytext(new_facial, 6, 8)) + if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) + var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", rgb(r_facial, g_facial, b_facial)) as color|null + if(new_facial) + r_facial = hex2num(copytext(new_facial, 2, 4)) + g_facial = hex2num(copytext(new_facial, 4, 6)) + b_facial = hex2num(copytext(new_facial, 6, 8)) if("f_style") var/list/valid_facialhairstyles = list() @@ -1485,11 +1492,14 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_eyes = hex2num(copytext(new_eyes, 6, 8)) if("s_tone") - if(species != "Human" && species != "Drask") - return - var/new_s_tone = input(user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Character Preference") as num|null - if(new_s_tone) - s_tone = 35 - max(min( round(new_s_tone), 220),1) + if(species == "Human" || species == "Drask") + var/new_s_tone = input(user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Character Preference") as num|null + if(new_s_tone) + s_tone = 35 - max(min(round(new_s_tone), 220), 1) + else if(species == "Vox") + var/skin_c = input(user, "Choose your Vox's skin color:\n(1 = Default Green, 2 = Dark Green, 3 = Brown, 4 = Grey, \n5 = Emerald, 6 = Azure)", "Character Preference") as num|null + if(skin_c) + s_tone = max(min(round(skin_c), 6), 1) if("skin") if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 6e4623fa9be..bad4a3dabc5 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -51,8 +51,8 @@ origin_tech = "magnets=2;engineering=2" vision_flags = SEE_TURFS prescription_upgradable = 1 - species_fit = list("Vox") see_darkness = 0 //don't render darkness while wearing mesons + species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/eyes.dmi', "Drask" = 'icons/mob/species/drask/eyes.dmi' @@ -97,6 +97,10 @@ item_state = "glasses" prescription_upgradable = 0 scan_reagents = 1 //You can see reagents while wearing science goggles + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/science/equipped(mob/user, slot) if(slot == slot_glasses) @@ -120,6 +124,10 @@ desc = "These'll keep the soap out of your eyes." icon_state = "purple" item_state = "glasses" + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/night name = "Night Vision Goggles" @@ -140,6 +148,10 @@ desc = "Yarr." icon_state = "eyepatch" item_state = "eyepatch" + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/monocle name = "monocle" @@ -178,6 +190,10 @@ icon_state = "glasses" item_state = "glasses" prescription = 1 + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/regular/hipster name = "prescription glasses" @@ -190,12 +206,20 @@ name = "3D glasses" icon_state = "3d" item_state = "3d" + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/gglasses name = "Green Glasses" desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme." icon_state = "gglasses" item_state = "gglasses" + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/sunglasses desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." @@ -350,10 +374,6 @@ flash_protect = 2 tint = 0 action_button_name = "Flip welding goggles" - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) /obj/item/clothing/glasses/sunglasses/blindfold name = "blindfold" @@ -364,10 +384,6 @@ flash_protect = 2 tint = 3 //to make them blind prescription_upgradable = 0 - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) /obj/item/clothing/glasses/sunglasses/prescription prescription = 1 @@ -376,12 +392,6 @@ desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks many flashes." icon_state = "bigsunglasses" item_state = "bigsunglasses" - flash_protect = 1 - tint = 1 - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) /obj/item/clothing/glasses/thermal name = "Optical Thermal Scanner" @@ -392,6 +402,10 @@ vision_flags = SEE_MOBS invisa_view = 2 flash_protect = -1 + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) emp_act(severity) if(istype(src.loc, /mob/living/carbon/human)) @@ -410,10 +424,6 @@ desc = "Used for seeing walls, floors, and stuff through anything." icon_state = "meson" origin_tech = "magnets=3;syndicate=4" - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) /obj/item/clothing/glasses/thermal/monocle name = "Thermoncle" @@ -432,10 +442,6 @@ desc = "A set of implantable lenses designed to augment your vision" icon_state = "thermalimplants" item_state = "syringe_kit" - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) /obj/item/clothing/glasses/thermal/cyber name = "Eye Replacement Implant" diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 44138b8e907..8756290ad20 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -28,13 +28,17 @@ desc = "A heads-up display that scans the humans in view and provides accurate data about their health status." icon_state = "healthhud" HUDType = DATA_HUD_MEDICAL_ADVANCED + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi', + "Drask" = 'icons/mob/species/drask/eyes.dmi' + ) /obj/item/clothing/glasses/hud/health/health_advanced name = "\improper Advanced Health Scanner HUD" desc = "A heads-up display that scans the humans in view and provides accurate data about their health status. Includes anti-flash filter." icon_state = "advmedhud" flash_protect = 1 - HUDType = DATA_HUD_MEDICAL_ADVANCED /obj/item/clothing/glasses/hud/health/night name = "\improper Night Vision Health Scanner HUD" @@ -50,6 +54,10 @@ desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits." icon_state = "diagnostichud" HUDType = DATA_HUD_DIAGNOSTIC + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) /obj/item/clothing/glasses/hud/diagnostic/night name = "Night Vision Diagnostic HUD" @@ -67,11 +75,15 @@ var/global/list/jobs[0] flash_protect = 1 HUDType = DATA_HUD_SECURITY_ADVANCED + species_fit = list("Vox") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/eyes.dmi', + "Drask" = 'icons/mob/species/drask/eyes.dmi' + ) /obj/item/clothing/glasses/hud/security/chameleon name = "Chamleon Security HUD" desc = "A stolen security HUD integrated with Syndicate chameleon technology. Toggle to disguise the HUD. Provides flash protection." - flash_protect = 1 /obj/item/clothing/glasses/hud/security/chameleon/attack_self(mob/user) chameleon(user) @@ -97,15 +109,8 @@ desc = "Sunglasses with a HUD." icon_state = "sunhud" darkness_view = 1 - flash_protect = 1 tint = 1 - HUDType = DATA_HUD_SECURITY_ADVANCED prescription_upgradable = 1 - species_fit = list("Vox") - sprite_sheets = list( - "Vox" = 'icons/mob/species/vox/eyes.dmi', - "Drask" = 'icons/mob/species/drask/eyes.dmi' - ) /obj/item/clothing/glasses/hud/security/sunglasses/prescription prescription = 1 \ No newline at end of file diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index b1b015e6ecb..a9e8bbdb7e2 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -1,10 +1,10 @@ /obj/item/clothing/head/helmet name = "helmet" desc = "Standard Security gear. Protects the head from impacts." - icon_state = "helmet" + icon_state = "helmetmaterials" flags = HEADCOVERSEYES | HEADBANGPROTECT - item_state = "helmet" - armor = list(melee = 50, bullet = 15, laser = 50,energy = 10, bomb = 25, bio = 0, rad = 0) + item_state = "helmetmaterials" + armor = list(melee = 50, bullet = 15, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0) flags_inv = HIDEEARS|HIDEEYES cold_protection = HEAD min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT @@ -82,10 +82,19 @@ icon_state = "riot" item_state = "helmet" flags = HEADCOVERSEYES | HEADCOVERSMOUTH | HEADBANGPROTECT - armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) + armor = list(melee = 80, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) flags_inv = HIDEEARS strip_delay = 80 +/obj/item/clothing/head/helmet/riot/knight + name = "medieval helmet" + desc = "A classic metal helmet." + icon_state = "knight_green" + item_state = "knight_green" + flags = BLOCKHAIR | HEADCOVERSEYES | HEADCOVERSMOUTH + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) + flags_inv = HIDEMASK | HIDEEARS | HIDEEYES | HIDEFACE + /obj/item/clothing/head/helmet/justice name = "helmet of justice" desc = "WEEEEOOO. WEEEEEOOO. WEEEEOOOO." @@ -111,7 +120,7 @@ icon_state = "swat" flags = HEADCOVERSEYES item_state = "swat" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) + armor = list(melee = 80, bullet = 60, laser = 50, energy = 25, bomb = 50, bio = 10, rad = 0) flags_inv = HIDEEARS|HIDEEYES cold_protection = HEAD min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT @@ -136,7 +145,7 @@ icon_state = "thunderdome" flags = HEADCOVERSEYES item_state = "thunderdome" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) + armor = list(melee = 80, bullet = 60, laser = 50, energy = 10, bomb = 25, bio = 10, rad = 0) cold_protection = HEAD min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD @@ -172,7 +181,7 @@ obj/item/clothing/head/helmet/redtaghelm icon_state = "redtaghelm" flags = HEADCOVERSEYES item_state = "redtaghelm" - armor = list(melee = 30, bullet = 10, laser = 20,energy = 10, bomb = 20, bio = 0, rad = 0) + armor = list(melee = 30, bullet = 10, laser = 20, energy = 10, bomb = 20, bio = 0, rad = 0) // Offer about the same protection as a hardhat. flags_inv = HIDEEARS|HIDEEYES @@ -182,7 +191,7 @@ obj/item/clothing/head/helmet/bluetaghelm icon_state = "bluetaghelm" flags = HEADCOVERSEYES item_state = "bluetaghelm" - armor = list(melee = 30, bullet = 10, laser = 20,energy = 10, bomb = 20, bio = 0, rad = 0) + armor = list(melee = 30, bullet = 10, laser = 20, energy = 10, bomb = 20, bio = 0, rad = 0) // Offer about the same protection as a hardhat. flags_inv = HIDEEARS|HIDEEYES @@ -194,16 +203,6 @@ obj/item/clothing/head/blob flags = HEADCOVERSEYES|HEADCOVERSMOUTH flags_inv = HIDEMASK|HIDEEARS|HIDEEYES -/obj/item/clothing/head/helmet/knight - name = "medieval helmet" - desc = "A classic metal helmet." - icon_state = "knight_green" - item_state = "knight_green" - armor = list(melee = 41, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) - flags = BLOCKHAIR|HEADCOVERSEYES|HEADCOVERSMOUTH - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - strip_delay = 80 - /obj/item/clothing/head/helmet/knight/blue icon_state = "knight_blue" item_state = "knight_blue" @@ -251,4 +250,4 @@ obj/item/clothing/head/blob /obj/item/clothing/head/helmet/ert/janitor name = "emergency response team janitor helmet" desc = "A set of armor worn by janitorial members of the NanoTrasen Emergency Response Team. Has red and white highlights." - icon_state = "erthelmet_jan" \ No newline at end of file + icon_state = "erthelmet_jan" diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 30252e49772..51ee371df32 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -85,9 +85,9 @@ armor = list(melee = 60, bullet = 5, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0) strip_delay = 60 -/obj/item/clothing/head/customs - name = "customs officer's hat" - desc = "A serious looking hat for a serious job." +/obj/item/clothing/head/officer + name = "officer's cap" + desc = "A red cap with an old-fashioned badge on the front for establishing that you are, in fact, the law." icon_state = "customshelm" item_state = "customshelm" armor = list(melee = 30, bullet = 25, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index abdfaf7648e..609e24ca6bf 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -36,9 +36,43 @@ /obj/item/clothing/suit/armor/vest/security name = "security armor" - desc = "An armored vest that protects against some damage. This one has Nanotrasen corporate badge." - icon_state = "armorsec" + desc = "An armored vest that protects against some damage. This one has a clip for a holobadge." + icon_state = "armor" item_state = "armor" + var/obj/item/clothing/accessory/holobadge/attached_badge + +/obj/item/clothing/suit/armor/vest/security/attackby(obj/item/W as obj, mob/user as mob, params) + if(istype(W, /obj/item/clothing/accessory/holobadge)) + if(user.unEquip(W)) + add_fingerprint(user) + W.forceMove(src) + attached_badge = W + + action_button_name = "Remove Holobadge" + icon_state = "armorsec" + user.update_inv_wear_suit() + desc = "An armored vest that protects against some damage. This one has [attached_badge] attached to it." + to_chat(user, "You attach [attached_badge] to [src].") + return + ..() + +/obj/item/clothing/suit/armor/vest/security/attack_self(mob/user as mob) + if(attached_badge) + add_fingerprint(user) + user.put_in_hands(attached_badge) + + action_button_name = null + action.Remove(user) + icon_state = "armor" + user.update_inv_wear_suit() + desc = "An armored vest that protects against some damage. This one has a clip for a holobadge." + to_chat(user, "You remove [attached_badge] from [src].") + + attached_badge = null + + return + + ..() /obj/item/clothing/suit/armor/vest/blueshield name = "blueshield security armor" @@ -119,6 +153,32 @@ strip_delay = 80 put_on_delay = 60 +/obj/item/clothing/suit/armor/riot/knight + name = "plate armour" + desc = "A classic suit of plate armour, highly effective at stopping melee attacks." + icon_state = "knight_green" + item_state = "knight_green" + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/suit/armor/riot/knight/yellow + icon_state = "knight_yellow" + item_state = "knight_yellow" + +/obj/item/clothing/suit/armor/riot/knight/blue + icon_state = "knight_blue" + item_state = "knight_blue" + +/obj/item/clothing/suit/armor/riot/knight/red + icon_state = "knight_red" + item_state = "knight_red" + +/obj/item/clothing/suit/armor/riot/knight/templar + name = "crusader armour" + desc = "God wills it!" + icon_state = "knight_templar" + item_state = "knight_templar" + allowed = list(/obj/item/weapon/nullrod/claymore) + /obj/item/clothing/suit/armor/bulletproof name = "Bulletproof Vest" desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." @@ -240,33 +300,6 @@ icon_state = "tdgreen" item_state = "tdgreen" -/obj/item/clothing/suit/armor/riot/knight - name = "plate armour" - desc = "A classic suit of plate armour, highly effective at stopping melee attacks." - icon_state = "knight_green" - item_state = "knight_green" - slowdown = 0 - armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) - -/obj/item/clothing/suit/armor/riot/knight/yellow - icon_state = "knight_yellow" - item_state = "knight_yellow" - -/obj/item/clothing/suit/armor/riot/knight/blue - icon_state = "knight_blue" - item_state = "knight_blue" - -/obj/item/clothing/suit/armor/riot/knight/red - icon_state = "knight_red" - item_state = "knight_red" - -/obj/item/clothing/suit/armor/riot/knight/templar - name = "crusader armour" - desc = "God wills it!" - icon_state = "knight_templar" - item_state = "knight_templar" - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite,/obj/item/weapon/melee/classic_baton/telescopic,/obj/item/weapon/nullrod/claymore) - //Non-hardsuit ERT armor. /obj/item/clothing/suit/armor/vest/ert name = "emergency response team armor" @@ -302,4 +335,4 @@ /obj/item/clothing/suit/armor/vest/ert/janitor name = "emergency response team janitor armor" desc = "A set of armor worn by janitorial members of the Nanotrasen Emergency Response Team. Has red and white highlights." - icon_state = "ertarmor_jan" \ No newline at end of file + icon_state = "ertarmor_jan" diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index bbdb526c70a..d8586b6c0d8 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -219,3 +219,10 @@ /obj/item/stack/sheet/wood = 5) tools = list(/obj/item/weapon/weldingtool, /obj/item/weapon/screwdriver) + +/datum/table_recipe/glove_balloon + name = "Latex Glove Balloon" + result = /obj/item/latexballon + time = 15 + reqs = list(/obj/item/clothing/gloves/color/latex = 1, + /obj/item/stack/cable_coil = 5) \ No newline at end of file diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm new file mode 100644 index 00000000000..1ab10bc8e4f --- /dev/null +++ b/code/modules/error_handler/error_handler.dm @@ -0,0 +1,104 @@ +var/list/error_last_seen = list() +// error_cooldown items will either be positive (cooldown time) or negative (silenced error) +// If negative, starts at -1, and goes down by 1 each time that error gets skipped +var/list/error_cooldown = list() +var/total_runtimes = 0 +var/total_runtimes_skipped = 0 +// The ifdef needs to be down here, since the error viewer references total_runtimes +#ifdef DEBUG +/world/Error(var/exception/e, var/datum/e_src) + if(!istype(e)) // Something threw an unusual exception + log_to_dd("\[[time_stamp()]] Uncaught exception: [e]") + return ..() + if(!error_last_seen) // A runtime is occurring too early in start-up initialization + return ..() + total_runtimes++ + + var/erroruid = "[e.file][e.line]" + var/last_seen = error_last_seen[erroruid] + var/cooldown = error_cooldown[erroruid] || 0 + if(last_seen == null) // A new error! + error_last_seen[erroruid] = world.time + last_seen = world.time + if(cooldown < 0) + error_cooldown[erroruid]-- // Used to keep track of skip count for this error + total_runtimes_skipped++ + return // Error is currently silenced, skip handling it + + // Handle cooldowns and silencing spammy errors + var/silencing = 0 + // Each occurrence of a unique error adds to its "cooldown" time... + cooldown = max(0, cooldown - (world.time - last_seen)) + ERROR_COOLDOWN + // ... which is used to silence an error if it occurs too often, too fast + if(cooldown > ERROR_MAX_COOLDOWN) + cooldown = -1 + silencing = 1 + spawn(0) + usr = null + sleep(ERROR_SILENCE_TIME) + var/skipcount = abs(error_cooldown[erroruid]) - 1 + error_cooldown[erroruid] = 0 + if(skipcount > 0) + log_to_dd("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].") + error_cache.logError(e, skipCount = skipcount) + error_last_seen[erroruid] = world.time + error_cooldown[erroruid] = cooldown + + // The detailed error info needs some tweaking to make it look nice + var/list/srcinfo = null + var/list/usrinfo = null + var/locinfo + // First, try to make better src/usr info lines + if(istype(e_src)) + srcinfo = list(" src: [datum_info_line(e_src)]") + locinfo = atom_loc_line(e_src) + if(locinfo) + srcinfo += " src.loc: [locinfo]" + if(istype(usr)) + usrinfo = list(" usr: [datum_info_line(usr)]") + locinfo = atom_loc_line(usr) + if(locinfo) + usrinfo += " usr.loc: [locinfo]" + // The proceeding mess will almost definitely break if error messages are ever changed + // I apologize in advance + var/list/splitlines = splittext(e.desc, "\n") + var/list/desclines = list() + if(splitlines.len > 2) // If there aren't at least three lines, there's no info + for(var/line in splitlines) + if(length(line) < 3) + continue // Blank line, skip it + if(findtext(line, "source file:")) + continue // Redundant, skip it + if(findtext(line, "usr.loc:")) + continue // Our usr.loc is better, skip it + if(findtext(line, "usr:")) + if(usrinfo) + desclines.Add(usrinfo) + usrinfo = null + continue // Our usr info is better, replace it + if(srcinfo) + if(findtext(line, "src.loc:")) + continue + if(findtext(line, "src:")) + desclines.Add(srcinfo) + srcinfo = null + continue + if(copytext(line, 1, 3) != " ") + desclines += (" " + line) // Pad any unpadded lines, so they look pretty + else + desclines += line + if(srcinfo) // If these aren't null, they haven't been added yet + desclines.Add(srcinfo) + if(usrinfo) + desclines.Add(usrinfo) + if(silencing) + desclines += " (This error will now be silenced for [ERROR_SILENCE_TIME / 600] minutes)" + + // Now to actually output the error info... + log_to_dd("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") + for(var/line in desclines) + log_to_dd(line) + if(error_cache) + error_cache.logError(e, desclines, e_src = e_src) + +#endif diff --git a/code/modules/error_handler/error_viewer.dm b/code/modules/error_handler/error_viewer.dm new file mode 100644 index 00000000000..1b8bd092ee2 --- /dev/null +++ b/code/modules/error_handler/error_viewer.dm @@ -0,0 +1,197 @@ +// Error viewing datums, responsible for storing error info, notifying admins +// when errors occur, and showing them to admins on demand. + +// There are 3 different types used here: +// +// - ErrorCache keeps track of all error sources, as well as all individually +// logged errors. Only one instance of this datum should ever exist, and it's +// right here: + +#ifdef DEBUG +var/global/datum/ErrorViewer/ErrorCache/error_cache = new() +#else +// If debugging is disabled, there's nothing useful to log, so don't bother. +var/global/datum/ErrorViewer/ErrorCache/error_cache = null +#endif + +// - ErrorSource datums exist for each line (of code) that generates an error, +// and keep track of all errors generated by that line. +// +// - ErrorEntry datums exist for each logged error, and keep track of all +// relevant info about that error. + +// Common vars and procs are kept at the ErrorViewer level +/datum/ErrorViewer/ + var/name = "" + +/datum/ErrorViewer/proc/browseTo(var/user, var/html) + if(user) + var/datum/browser/popup = new(user, "error_viewer", "Runtime Viewer", 700, 500) + popup.add_head_content({""}) + popup.set_content(html) + popup.open(0) + +/datum/ErrorViewer/proc/buildHeader(var/datum/ErrorViewer/back_to, var/linear, var/refreshable) + // Common starter HTML for showTo + var/html = "" + + if(istype(back_to)) + html += "[back_to.makeLink("<<<", null, linear)] " + if(refreshable) + html += "[makeLink("Refresh", null, linear)]" + if(html) + html += "

" + return html + +/datum/ErrorViewer/proc/showTo(var/user, var/datum/ErrorViewer/back_to, var/linear) + // Specific to each child type + return + +/datum/ErrorViewer/proc/makeLink(var/linktext, var/datum/ErrorViewer/back_to, var/linear) + var/back_to_param = "" + if(!linktext) + linktext = name + if(istype(back_to)) + back_to_param = ";viewruntime_backto=\ref[back_to]" + if(linear) + back_to_param += ";viewruntime_linear=1" + return "[html_encode(linktext)]" + +/datum/ErrorViewer/ErrorCache + var/list/errors = list() + var/list/error_sources = list() + var/list/errors_silenced = list() + +/datum/ErrorViewer/ErrorCache/showTo(var/user, var/datum/ErrorViewer/back_to, var/linear) + var/html = buildHeader(null, linear, refreshable=1) + html += "[total_runtimes] runtimes, [total_runtimes_skipped] skipped

" + if(!linear) + html += "organized | [makeLink("linear", null, 1)]
" + var/datum/ErrorViewer/ErrorSource/error_source + for(var/erroruid in error_sources) + error_source = error_sources[erroruid] + html += "

[error_source.makeLink(null, src)]

" + else + html += "[makeLink("organized", null)] | linear
" + for(var/datum/ErrorViewer/ErrorEntry/error_entry in errors) + html += "

[error_entry.makeLink(null, src, 1)]

" + browseTo(user, html) + +/datum/ErrorViewer/ErrorCache/proc/logError(var/exception/e, var/list/desclines, var/skipCount, var/datum/e_src) + if(!istype(e)) + return // Abnormal exception, don't even bother + + var/erroruid = "[e.file][e.line]" + var/datum/ErrorViewer/ErrorSource/error_source = error_sources[erroruid] + if(!error_source) + error_source = new(e) + error_sources[erroruid] = error_source + + var/datum/ErrorViewer/ErrorEntry/error_entry = new(e, desclines, skipCount, e_src) + error_entry.error_source = error_source + errors += error_entry + error_source.errors += error_entry + if(skipCount) + return // Skip notifying admins about skipped errors + + // Show the error to admins with debug messages turned on, but only if one + // from the same source hasn't been shown too recently + if(error_source.next_message_at <= world.time) + var/const/viewtext = "\[view]" // Nesting these in other brackets went poorly + log_debug("Runtime in [e.file],[e.line]: [html_encode(e.name)] [error_entry.makeLink(viewtext)]") + error_source.next_message_at = world.time + ERROR_MSG_DELAY + +/datum/ErrorViewer/ErrorSource + var/list/errors = list() + var/next_message_at = 0 + +/datum/ErrorViewer/ErrorSource/New(var/exception/e) + if(!istype(e)) + name = "\[[time_stamp()]] Uncaught exceptions" + return + name = "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]" + +/datum/ErrorViewer/ErrorSource/showTo(var/user, var/datum/ErrorViewer/back_to, var/linear) + if(!istype(back_to)) + back_to = error_cache + var/html = buildHeader(back_to, refreshable=1) + for(var/datum/ErrorViewer/ErrorEntry/error_entry in errors) + html += "

[error_entry.makeLink(null, src)]

" + browseTo(user, html) + +/datum/ErrorViewer/ErrorEntry + var/datum/ErrorViewer/ErrorSource/error_source + var/exception/exc + var/desc = "" + var/srcRef + var/srcType + var/turf/srcLoc + var/usrRef + var/turf/usrLoc + var/isSkipCount + +/datum/ErrorViewer/ErrorEntry/New(var/exception/e, var/list/desclines, var/skipCount, var/datum/e_src) + if(!istype(e)) + name = "\[[time_stamp()]] Uncaught exception: [e]" + return + if(skipCount) + name = "\[[time_stamp()]] Skipped [skipCount] runtimes in [e.file],[e.line]." + isSkipCount = TRUE + return + name = "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]" + exc = e + if(istype(desclines)) + for(var/line in desclines) + // There's probably a better way to do this than non-breaking spaces... + desc += "  " + html_encode(line) + "
" + if(istype(e_src)) + srcRef = "\ref[e_src]" + srcType = e_src.type + srcLoc = get_turf(e_src) + if(usr) + usrRef = "\ref[usr]" + usrLoc = get_turf(usr) + +/datum/ErrorViewer/ErrorEntry/showTo(var/user, var/datum/ErrorViewer/back_to, var/linear) + if(!istype(back_to)) + back_to = error_source + var/html = buildHeader(back_to, linear) + html += "
[html_encode(name)]
[desc]
" + if(srcRef) + html += "
src: VV" + if(ispath(srcType, /mob)) + html += " PP" + html += " Follow" + if(istype(srcLoc)) + html += "
src.loc: VV" + html += " JMP" + if(usrRef) + html += "
usr: VV" + html += " PP" + html += " Follow" + if(istype(usrLoc)) + html += "
usr.loc: VV" + html += " JMP" + browseTo(user, html) + +/datum/ErrorViewer/ErrorEntry/makeLink(var/linktext, var/datum/ErrorViewer/back_to, var/linear) + if(isSkipCount) + return html_encode(name) + else + return ..() diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm index 2d7316cc0ef..7837bd61d7c 100644 --- a/code/modules/events/rogue_drones.dm +++ b/code/modules/events/rogue_drones.dm @@ -25,11 +25,11 @@ /datum/event/rogue_drone/announce() var/msg if(prob(33)) - msg = "A combat drone wing operating out of the NMV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution." + msg = "A combat drone wing operating out of the NSV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution." else if(prob(50)) - msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution." + msg = "Contact has been lost with a combat drone wing operating out of the NSV Icarus. If any are sighted in the area, approach with caution." else - msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution." + msg = "Unidentified hackers have targetted a combat drone wing deployed from the NSV Icarus. If any are sighted in the area, approach with caution." command_announcement.Announce(msg, "Rogue drone alert") /datum/event/rogue_drone/tick() diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 45ef929967a..6229105a8b3 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -693,6 +693,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite if(slots_free.len) halitem.screen_loc = pick(slots_free) halitem.layer = 50 + halitem.plane = HUD_PLANE switch(rand(1,6)) if(1) //revolver halitem.icon = 'icons/obj/guns/projectile.dmi' diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index ee84c1a5864..1320423a4e8 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -292,6 +292,7 @@ s.use(s.max_amount) s.forceMove(loc) s.layer = initial(s.layer) + s.plane = initial(s.plane) /obj/machinery/mineral/ore_redemption/power_change() ..() diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 7f63a8f1261..a6269b96d36 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -14,52 +14,8 @@ if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT)) return + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + . = src.say_dead(message) - -/mob/dead/observer/emote(var/act, var/type, var/message) - message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN)) - - if(!message) - return - - if(act != "me") - return - - log_emote("Ghost/[src.key] : [message]") - - if(src.client) - if(src.client.prefs.muted & MUTE_DEADCHAT) - to_chat(src, "\red You cannot emote in deadchat (muted).") - return - - if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT)) - return - - . = src.emote_dead(message) - -/* - for (var/mob/M in hearers(null, null)) - if (!M.stat) - if(M.job == "Chaplain") - if (prob (49)) - M.show_message("You hear muffled speech... but nothing is there...", 2) - if(prob(20)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - M.show_message("You hear muffled speech... you can almost make out some words...", 2) -// M.show_message("[stutter(message)]", 2) - if(prob(30)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - if (prob(50)) - return - else if (prob (95)) - M.show_message("You hear muffled speech... but nothing is there...", 2) - if(prob(20)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - M.show_message("You hear muffled speech... you can almost make out some words...", 2) -// M.show_message("[stutter(message)]", 2) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) -*/ diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 2bfe10a1f35..11e51987285 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -76,6 +76,10 @@ /mob/proc/death(gibbed) + //Makes it so gib/dust/melt all unbuckle their victims from anything they may be buckled to to avoid breaking beds/chairs/etc + if(gibbed && buckled) + buckled.unbuckle_mob() + //Quick fix for corpses kept propped up in chairs. ~Z drop_r_hand() drop_l_hand() diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm deleted file mode 100644 index 8d03cdd969a..00000000000 --- a/code/modules/mob/emote.dm +++ /dev/null @@ -1,124 +0,0 @@ -#define EMOTE_COOLDOWN 20 //Time in deciseconds that the cooldown lasts - -//Emote Cooldown System (it's so simple!) -/mob/proc/handle_emote_CD(cooldown = EMOTE_COOLDOWN) - if(emote_cd == 2) return 1 // Cooldown emotes were disabled by an admin, prevent use - if(src.emote_cd == 1) return 1 // Already on CD, prevent use - - src.emote_cd = 1 // Starting cooldown - spawn(cooldown) - if(emote_cd == 2) return 1 // Don't reset if cooldown emotes were disabled by an admin during the cooldown - src.emote_cd = 0 // Cooldown complete, ready for more! - - return 0 // Proceed with emote -//--FalseIncarnate - -// All mobs should have custom emote, really.. -/mob/proc/custom_emote(var/m_type=1,var/message = null) - - if(stat || !use_me && usr == src) - to_chat(usr, "You are unable to emote.") - return - - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - if(m_type == 2 && muzzled) return - - var/input - if(!message) - input = sanitize(copytext(input(src,"Choose an emote to display.") as text|null,1,MAX_MESSAGE_LEN)) - else - input = message - if(input) - message = "[src] [input]" - else - return - - - if (message) - log_emote("[name]/[key] : [message]") - - //Hearing gasp and such every five seconds is not good emotes were not global for a reason. - // Maybe some people are okay with that. - - for(var/mob/M in player_list) - if (!M.client) - continue //skip monkeys and leavers - if (istype(M, /mob/new_player)) - continue - if(findtext(message," snores.")) //Because we have so many sleeping people. - break - if(M.stat == 2 && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - - // Type 1 (Visual) emotes are sent to anyone in view of the item - if (m_type & 1) - var/list/can_see = get_mobs_in_view(1,src) //Allows silicon & mmi mobs carried around to see the emotes of the person carrying them around. - can_see |= viewers(src,null) - for (var/mob/O in can_see) - - if(O.status_flags & PASSEMOTES) - - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message(message, m_type) - - for(var/mob/living/M in O.contents) - M.show_message(message, m_type) - - O.show_message(message, m_type) - - // Type 2 (Audible) emotes are sent to anyone in hear range - // of the *LOCATION* -- this is important for pAIs to be heard - else if (m_type & 2) - for (var/mob/O in get_mobs_in_view(7,src)) - - if(O.status_flags & PASSEMOTES) - - for(var/obj/item/weapon/holder/H in O.contents) - H.show_message(message, m_type) - - for(var/mob/living/M in O.contents) - M.show_message(message, m_type) - - O.show_message(message, m_type) - -/mob/proc/emote_dead(var/message) - - if(client.prefs.muted & MUTE_DEADCHAT) - to_chat(src, "\red You cannot send deadchat emotes (muted).") - return - - if(!(client.prefs.toggles & CHAT_DEAD)) - to_chat(src, "\red You have deadchat muted.") - return - - if(!src.client.holder) - if(!config.dsay_allowed) - to_chat(src, "\red Deadchat is globally muted") - return - - - var/input - if(!message) - input = sanitize(copytext(input(src, "Choose an emote to display.") as text|null, 1, MAX_MESSAGE_LEN)) - else - input = message - - if(input) - message = "DEAD: [src] [message]" - else - return - - - if(message) - log_emote("Ghost/[src.key] : [message]") - - for(var/mob/M in player_list) - if(istype(M, /mob/new_player)) - continue - - if(check_rights(R_ADMIN|R_MOD, 0, M) && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to admins/mods - to_chat(M, message) - - else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on - M.show_message(message, 2) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 8d68373e3f4..bbc313e0421 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -28,6 +28,7 @@ W.forceMove(src) //TODO: move to equipped? l_hand = W W.layer = 20 //TODO: move to equipped? + W.plane = HUD_PLANE //TODO: move to equipped? W.equipped(src,slot_l_hand) if(pulling == W) stop_pulling() @@ -43,6 +44,7 @@ W.forceMove(src) r_hand = W W.layer = 20 + W.plane = HUD_PLANE W.equipped(src,slot_r_hand) if(pulling == W) stop_pulling() @@ -72,6 +74,7 @@ /mob/proc/put_in_hands(obj/item/W) W.forceMove(get_turf(src)) W.layer = initial(W.layer) + W.plane = initial(W.plane) W.dropped() /mob/proc/drop_item_v() //this is dumb. @@ -124,6 +127,7 @@ I.dropped(src) if(I) I.layer = initial(I.layer) + I.plane = initial(I.plane) return 1 diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index c88684c77c0..6abd4acd6fc 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -213,7 +213,7 @@ colour = "vox" key = "v" flags = RESTRICTED | WHITELISTED - syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","chi","cha","kah", \ + syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya", "yi", "chi","cha","kah", \ "SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA") /datum/language/vox/get_random_name() @@ -278,7 +278,7 @@ /datum/language/drask name = "Orluum" - desc = "The droning, vibrous language of the Drask. It sounds somewhat like whalesong" + desc = "The droning, vibrous language of the Drask. It sounds somewhat like whalesong." speech_verb = "drones" ask_verb = "hums" exclaim_verb = "rumbles" diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm deleted file mode 100644 index c20cc155f37..00000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ /dev/null @@ -1,115 +0,0 @@ -/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - -// if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' -// act = copytext(act,1,length(act)) //seriously who the fuck wrote this - var/muzzled = is_muzzled() - act = lowertext(act) - switch(act) - if("sign") - if(!restrained()) - var/num = null - if(text2num(param)) - num = "the number [text2num(param)]" - if(num) - message = "\The [src] signs [num]." - m_type = 1 - if ("burp") - if (!muzzled) - message = "\The [src] burps." - m_type = 2 - if ("deathgasp") - message = "\The [src] lets out a waning guttural screech, green blood bubbling from its maw..." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "\The [src] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "\The [src] whimpers." - m_type = 2 - if("roar") - if (!muzzled) - message = "\The [src] roars." - m_type = 2 - if("hiss") - if(!muzzled) - message = "\The [src] hisses." - m_type = 2 - if("tail") - message = "\The [src] waves its tail." - m_type = 1 - if("gasp") - message = "\The [src] gasps." - m_type = 2 - if("shiver") - message = "\The [src] shivers." - m_type = 2 - if("drool") - message = "\The [src] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "\The [src] scretches." - m_type = 2 - if("choke") - message = "\The [src] chokes." - m_type = 2 - if("moan") - message = "\The [src] moans!" - m_type = 2 - if("nod") - message = "\The [src] nods its head." - m_type = 1 - if("sit") - message = "\The [src] sits down." - m_type = 1 - if("sway") - message = "\The [src] sways around dizzily." - m_type = 1 - if("sulk") - message = "\The [src] sulks down sadly." - m_type = 1 - if("twitch") - message = "\The [src] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "\The [src] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "\The [src] rolls." - m_type = 1 - if("shake") - message = "\The [src] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "\The [src] gnarls and shows its teeth.." - m_type = 2 - if("jump") - message = "\The [src] jumps!" - m_type = 1 - if("collapse") - Paralyse(2) - message = "\The [src] collapses!" - m_type = 2 - if ("flip") - m_type = 1 - message = "\The [src] does a flip!" - src.SpinAnimation(5,1) - if("help") - to_chat(src, "burp, flip, deathgasp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper") - - if(!stat) - if (act == "roar") - playsound(src.loc, 'sound/voice/hiss5.ogg', 40, 1, 1) - if (act == "deathgasp") - playsound(src.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm deleted file mode 100644 index dc7a66f7018..00000000000 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ /dev/null @@ -1,126 +0,0 @@ -/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - var/muzzled = is_muzzled() - act = lowertext(act) - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) - to_chat(src, "\red You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if ("custom") - return custom_emote(m_type, message) - if("sign") - if (!src.restrained()) - message = text("The alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if ("burp") - if (!muzzled) - message = "[src] burps." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 -// if("roar") -// if (!muzzled) -// message = "The [src.name] roars." Commenting out since larva shouldn't roar /N -// m_type = 2 - if("tail") - message = "The [src.name] waves its tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods its head." - m_type = 1 -// if("sit") -// message = "The [src.name] sits down." //Larvan can't sit down, /N -// m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows its teeth.." - m_type = 2 - if("jump") - message = "The [src.name] jumps!" - m_type = 1 - if("hiss_") - message = "The [src.name] hisses softly." - m_type = 1 - if("collapse") - Paralyse(2) - message = text("[] collapses!", src) - m_type = 2 - if("help") - to_chat(src, "burp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper") - else - to_chat(src, text("Invalid Emote: []", act)) - if ((message && src.stat == 0)) - log_emote("[name]/[key] : [message]") - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - //Foreach goto(703) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - //Foreach goto(746) - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm deleted file mode 100644 index 16cf01e4266..00000000000 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ /dev/null @@ -1,51 +0,0 @@ -/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null) - if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes - return - - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - if(src.stat == DEAD) - return - act = lowertext(act) - switch(act) - - if ("alarm") - to_chat(src, "You sound an alarm.") - message = "\The [src] sounds an alarm." - m_type = 2 - if ("alert") - to_chat(src, "You let out a distressed noise.") - message = "\The [src] lets out a distressed noise." - m_type = 2 - if ("notice") - to_chat(src, "You play a loud tone.") - message = "\The [src] plays a loud tone." - m_type = 2 - if ("flash") - message = "The lights on \the [src] flash quickly." - m_type = 1 - if ("blink") - message = "\The [src] blinks." - m_type = 1 - if ("whistle") - to_chat(src, "You whistle.") - message = "\The [src] whistles." - m_type = 2 - if ("beep") - to_chat(src, "You beep.") - message = "\The [src] beeps." - m_type = 2 - if ("boop") - to_chat(src, "You boop.") - message = "\The [src] boops." - m_type = 2 - if ("help") - to_chat(src, "alarm, alert, notice, flash,blink, whistle, beep, boop") - - if(message && !stat) - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 9aed3244949..f9afba579fb 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -455,6 +455,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, for(var/obj/machinery/atmospherics/A in totalMembers) if(!A.pipe_image) A.pipe_image = image(A, A.loc, layer = 20, dir = A.dir) //the 20 puts it above Byond's darkness (not its opacity view) + A.pipe_image.plane = HUD_PLANE pipes_shown += A.pipe_image client.images += A.pipe_image @@ -902,6 +903,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, W.dropped(src) if (W) W.layer = initial(W.layer) + W.plane = initial(W.plane) if (legcuffed) var/obj/item/weapon/W = legcuffed legcuffed = null @@ -913,6 +915,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, W.dropped(src) if (W) W.layer = initial(W.layer) + W.plane = initial(W.plane) /mob/living/carbon/proc/slip(var/description, var/stun, var/weaken, var/tilesSlipped, var/walkSafely, var/slipAny) @@ -980,13 +983,15 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return 1 /mob/living/carbon/proc/forceFed(var/obj/item/weapon/reagent_containers/food/toEat, mob/user, fullness) - if (fullness <= (550 * (1 + overeatduration / 1000))) - visible_message("[user] attempts to force [src] to [toEat.apply_method] [toEat].") + if(fullness <= (550 * (1 + overeatduration / 1000))) + if(!toEat.instant_application) + visible_message("[user] attempts to force [src] to [toEat.apply_method] [toEat].") else visible_message("[user] cannot force anymore of [toEat] down [src]'s throat.") return 0 - if(!do_mob(user, src)) - return 0 + if(!toEat.instant_application) + if(!do_mob(user, src)) + return 0 forceFedAttackLog(toEat, user) visible_message("[user] forces [src] to [toEat.apply_method] [toEat].") return 1 diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index 13e8fe153ea..9dfa6efac89 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -49,6 +49,7 @@ target.l_hand = I I.loc = target I.layer = 20 + I.plane = HUD_PLANE I.add_fingerprint(target) src.update_inv_l_hand() src.update_inv_r_hand() diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 52488051f50..f3cd00463e2 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -243,7 +243,7 @@ return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) - if(s_tone == tone || !(species.bodyflags & HAS_SKIN_TONE)) + if(s_tone == tone || !((species.bodyflags & HAS_SKIN_TONE) || (species.bodyflags & HAS_ICON_SKIN_TONE))) return s_tone = tone diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index fce12362d73..5ac5d796897 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -118,10 +118,6 @@ callHook("death", list(src, gibbed)) - if(ticker && ticker.mode) - if(istype(ticker.mode,/datum/game_mode/heist)) - vox_kills++ //Bad vox. Shouldn't be killing humans. - if(ishuman(LAssailant)) var/mob/living/carbon/human/H=LAssailant if(H.mind) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm deleted file mode 100644 index a57764ed47a..00000000000 --- a/code/modules/mob/living/carbon/human/emote.dm +++ /dev/null @@ -1,889 +0,0 @@ -/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null,var/force) - - if (stat == DEAD) - return // No screaming bodies - - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - var/muzzled = is_muzzled() - if(sdisabilities & MUTE || silent) - muzzled = 1 - //var/m_type = 1 - - for (var/obj/item/weapon/implant/I in src) - if (I.implanted) - I.trigger(act, src) - - var/miming = 0 - if(mind) - miming = mind.miming - - //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] - var/on_CD = 0 - act = lowertext(act) - switch(act) - //Cooldown-inducing emotes - if("ping", "pings", "buzz", "buzzes", "beep", "beeps", "yes", "no", "buzz2") - if (species.name == "Machine") //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise. - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - else //Everyone else fails, skip the emote attempt - return - if("drone","drones","hum","hums","rumble","rumbles") - if (species.name == "Drask") //Only Drask can make whale noises - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - else - return - if("squish", "squishes") - var/found_slime_bodypart = 0 - - if(species.name == "Slime People") //Only Slime People can squish - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' - found_slime_bodypart = 1 - else - for(var/obj/item/organ/external/L in organs) // if your limbs are squishy you can squish too! - if(L.dna.species in list("Slime People")) - on_CD = handle_emote_CD() - found_slime_bodypart = 1 - break - - if(!found_slime_bodypart) //Everyone else fails, skip the emote attempt - return - if("scream", "screams") - on_CD = handle_emote_CD(50) //longer cooldown - if("fart", "farts", "flip", "flips", "snap", "snaps") - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - //Everything else, including typos of the above emotes - else - on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - - if(on_CD == 1) // Check if we need to suppress the emote attempt. - return // Suppress emote, you're still cooling off. - - switch(act) - if("me") //OKAY SO RANT TIME, THIS FUCKING HAS TO BE HERE OR A SHITLOAD OF THINGS BREAK - return custom_emote(m_type, message) //DO YOU KNOW WHY SHIT BREAKS? BECAUSE SO MUCH OLDCODE CALLS mob.emote("me",1,"whatever_the_fuck_it_wants_to_emote") - //WHO THE FUCK THOUGHT THAT WAS A GOOD FUCKING IDEA!?!? - - if("ping", "pings") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] pings at [param]." - else - message = "[src] pings." - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - m_type = 2 - - if("buzz2") - message = "[src] emits an irritated buzzing sound." - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) - m_type = 2 - - if("buzz", "buzzes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] buzzes at [param]." - else - message = "[src] buzzes." - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = 2 - - if("beep", "beeps") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] beeps at [param]." - else - message = "[src] beeps." - playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) - m_type = 2 - - if("drone", "drones", "hum", "hums", "rumble", "rumbles") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] drones at [param]." - else - message = "[src] rumbles." - playsound(src.loc, 'sound/voice/DraskTalk.ogg', 50, 0) - m_type = 2 - - if("squish", "squishes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] squishes at [param]." - else - message = "[src] squishes." - playsound(src.loc, 'sound/effects/slime_squish.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound. - m_type = 2 - - if("yes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits an affirmative blip at [param]." - else - message = "[src] emits an affirmative blip." - playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0) - m_type = 2 - - if("no") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits a negative blip at [param]." - else - message = "[src] emits a negative blip." - playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0) - m_type = 2 - - if("wag", "wags") - if(body_accessory) - if(body_accessory.try_restrictions(src)) - message = "[src] starts wagging \his tail." - start_tail_wagging(1) - - else if(species.bodyflags & TAIL_WAGGING) - if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) - message = "[src] starts wagging \his tail." - src.start_tail_wagging(1) - else - return - else - return - m_type = 1 - - if("swag", "swags") - if(species.bodyflags & TAIL_WAGGING || body_accessory) - message = "[src] stops wagging \his tail." - src.stop_tail_wagging(1) - else - return - m_type = 1 - - if ("airguitar") - if (!src.restrained()) - message = "[src] is strumming the air and headbanging like a safari chimp." - m_type = 1 - - if ("blink", "blinks") - message = "[src] blinks." - m_type = 1 - - if ("blink_r", "blinks_r") - message = "[src] blinks rapidly." - m_type = 1 - - if ("bow", "bows") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] bows to [param]." - else - message = "[src] bows." - m_type = 1 - - if ("salute", "salutes") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] salutes to [param]." - else - message = "[src] salutes." - m_type = 1 - - if ("choke", "chokes") - if(miming) - message = "[src] clutches \his throat desperately!" - m_type = 1 - else - if (!muzzled) - message = "[src] chokes!" - m_type = 2 - else - message = "[src] makes a strong noise." - m_type = 2 - - if ("burp", "burps") - if(miming) - message = "[src] opens their mouth rather obnoxiously." - m_type = 1 - else - if (!muzzled) - message = "[src] burps." - m_type = 2 - else - message = "[src] makes a peculiar noise." - m_type = 2 - if ("clap", "claps") - if (!src.restrained()) - message = "[src] claps." - m_type = 2 - if(miming) - m_type = 1 - if ("flap", "flaps") - if (!src.restrained()) - message = "[src] flaps \his wings." - m_type = 2 - if(miming) - m_type = 1 - - if ("flip", "flips") - m_type = 1 - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M == src) - M = null - - if(M) - if(lying || weakened) - message = "[src] flops and flails around on the floor." - else - message = "[src] flips in [M]'s general direction." - SpinAnimation(5,1) - else - if(lying || weakened) - message = "[src] flops and flails around on the floor." - else - var/obj/item/weapon/grab/G - if(istype(get_active_hand(), /obj/item/weapon/grab)) - G = get_active_hand() - if(G && G.affecting) - if(buckled || G.affecting.buckled) - return - var/turf/oldloc = loc - var/turf/newloc = G.affecting.loc - if(isturf(oldloc) && isturf(newloc)) - SpinAnimation(5,1) - forceMove(newloc) - G.affecting.forceMove(oldloc) - message = "[src] flips over [G.affecting]!" - else - message = "[src] does a flip!" - SpinAnimation(5,1) - - if ("aflap", "aflaps") - if (!src.restrained()) - message = "[src] flaps \his wings ANGRILY!" - m_type = 2 - if(miming) - m_type = 1 - - if ("drool", "drools") - message = "[src] drools." - m_type = 1 - - if ("eyebrow") - message = "[src] raises an eyebrow." - m_type = 1 - - if ("chuckle", "chuckles") - if(miming) - message = "[src] appears to chuckle." - m_type = 1 - else - if (!muzzled) - message = "[src] chuckles." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("twitch", "twitches") - message = "[src] twitches violently." - m_type = 1 - - if ("twitch_s", "twitches_s") - message = "[src] twitches." - m_type = 1 - - if ("faint", "faints") - message = "[src] faints." - if(src.sleeping) - return //Can't faint while asleep - src.sleeping += 1 - m_type = 1 - - if ("cough", "coughs") - if(miming) - message = "[src] appears to cough!" - m_type = 1 - else - if (!muzzled) - message = "[src] coughs!" - m_type = 2 - else - message = "[src] makes a strong noise." - m_type = 2 - - if ("frown", "frowns") - message = "[src] frowns." - m_type = 1 - - if ("nod", "nods") - message = "[src] nods." - m_type = 1 - - if ("blush", "blushes") - message = "[src] blushes." - m_type = 1 - - if ("wave", "waves") - message = "[src] waves." - m_type = 1 - - if ("quiver", "quivers") - message = "[src] quivers." - m_type = 1 - - if ("gasp", "gasps") - if(miming) - message = "[src] appears to be gasping!" - m_type = 1 - else - if (!muzzled) - message = "[src] gasps!" - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - if ("deathgasp", "deathgasps") - message = "[src] [species.death_message]" - m_type = 1 - - if ("giggle", "giggles") - if(miming) - message = "[src] giggles silently!" - m_type = 1 - else - if (!muzzled) - message = "[src] giggles." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("glare", "glares") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] glares at [param]." - else - message = "[src] glares." - m_type = 1 - - if ("stare", "stares") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] stares at [param]." - else - message = "[src] stares." - m_type = 1 - - if ("look", "looks") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - - if (!M) - param = null - - if (param) - message = "[src] looks at [param]." - else - message = "[src] looks." - m_type = 1 - - if ("grin", "grins") - message = "[src] grins." - m_type = 1 - - if ("cry", "cries") - if(miming) - message = "[src] cries." - m_type = 1 - else - if (!muzzled) - message = "[src] cries." - m_type = 2 - else - message = "[src] makes a weak noise. \He frowns." - m_type = 2 - - if ("sigh", "sighs") - if(miming) - message = "[src] sighs." - m_type = 1 - else - if (!muzzled) - message = "[src] sighs." - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - if ("laugh", "laughs") - if(miming) - message = "[src] acts out a laugh." - m_type = 1 - else - if (!muzzled) - message = "[src] laughs." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("mumble", "mumbles") - message = "[src] mumbles!" - m_type = 2 - if(miming) - m_type = 1 - - if ("grumble", "grumbles") - if(miming) - message = "[src] grumbles!" - m_type = 1 - if (!muzzled) - message = "[src] grumbles!" - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("groan", "groans") - if(miming) - message = "[src] appears to groan!" - m_type = 1 - else - if (!muzzled) - message = "[src] groans!" - m_type = 2 - else - message = "[src] makes a loud noise." - m_type = 2 - - if ("moan", "moans") - if(miming) - message = "[src] appears to moan!" - m_type = 1 - else - message = "[src] moans!" - m_type = 2 - - if ("johnny") - var/M - if (param) - M = param - if (!M) - param = null - else - if(miming) - message = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke." - m_type = 1 - else - message = "[src] says, \"[M], please. They had a family.\" [src.name] takes a drag from a cigarette and blows their name out in smoke." - m_type = 2 - - if ("point", "points") - if (!src.restrained()) - var/atom/M = null - if (param) - for (var/atom/A as mob|obj|turf in view()) - if (param == A.name) - M = A - break - - if (!M) - message = "[src] points." - else - pointed(M) - m_type = 1 - - if ("raise", "raises") - if (!src.restrained()) - message = "[src] raises a hand." - m_type = 1 - - if("shake", "shakes") - message = "[src] shakes \his head." - m_type = 1 - - if ("shrug", "shrugs") - message = "[src] shrugs." - m_type = 1 - - if ("signal", "signals") - if (!src.restrained()) - var/t1 = round(text2num(param)) - if (isnum(t1)) - if (t1 <= 5 && (!src.r_hand || !src.l_hand)) - message = "[src] raises [t1] finger\s." - else if (t1 <= 10 && (!src.r_hand && !src.l_hand)) - message = "[src] raises [t1] finger\s." - m_type = 1 - - if ("smile", "smiles") - message = "[src] smiles." - m_type = 1 - - if ("shiver", "shivers") - message = "[src] shivers." - m_type = 2 - if(miming) - m_type = 1 - - if ("pale", "pales") - message = "[src] goes pale for a second." - m_type = 1 - - if ("tremble", "trembles") - message = "[src] trembles." - m_type = 1 - - if ("sneeze", "sneezes") - if (miming) - message = "[src] sneezes." - m_type = 1 - else - if (!muzzled) - message = "[src] sneezes." - m_type = 2 - else - message = "[src] makes a strange noise." - m_type = 2 - - if ("sniff", "sniffs") - message = "[src] sniffs." - m_type = 2 - if(miming) - m_type = 1 - - if ("snore", "snores") - if (miming) - message = "[src] sleeps soundly." - m_type = 1 - else - if (!muzzled) - message = "[src] snores." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("whimper", "whimpers") - if (miming) - message = "[src] appears hurt." - m_type = 1 - else - if (!muzzled) - message = "[src] whimpers." - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - if ("wink", "winks") - message = "[src] winks." - m_type = 1 - - if ("yawn", "yawns") - if (!muzzled) - message = "[src] yawns." - m_type = 2 - if(miming) - m_type = 1 - - if ("collapse", "collapses") - Paralyse(2) - message = "[src] collapses!" - m_type = 2 - if(miming) - m_type = 1 - - if("hug", "hugs") - m_type = 1 - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M == src) - M = null - - if (M) - message = "[src] hugs [M]." - else - message = "[src] hugs \himself." - - if ("handshake") - m_type = 1 - if (!src.restrained() && !src.r_hand) - var/mob/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M == src) - M = null - - if (M) - if (M.canmove && !M.r_hand && !M.restrained()) - message = "[src] shakes hands with [M]." - else - message = "[src] holds out \his hand to [M]." - - if("dap", "daps") - m_type = 1 - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M) - message = "[src] gives daps to [M]." - else - message = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful." - - if("slap", "slaps") - m_type = 1 - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M) - message = "\red [src] slaps [M] across the face. Ouch!" - playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) - else - message = "\red [src] slaps \himself!" - playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) - src.adjustFireLoss(4) - - if ("scream", "screams") - if (miming) - message = "[src] acts out a scream!" - m_type = 1 - else - if (!muzzled) - message = "[src] [species.scream_verb]!" - m_type = 2 - if(gender == FEMALE) - playsound(src.loc, "[species.female_scream_sound]", 80, 1, 0, pitch = get_age_pitch()) - else - playsound(src.loc, "[species.male_scream_sound]", 80, 1, 0, pitch = get_age_pitch()) //default to male screams if no gender is present. - - else - message = "[src] makes a very loud noise." - m_type = 2 - - - if ("snap", "snaps") - if(prob(95)) - m_type = 2 - var/mob/living/carbon/human/H = src - var/obj/item/organ/external/L = H.get_organ("l_hand") - var/obj/item/organ/external/R = H.get_organ("r_hand") - var/left_hand_good = 0 - var/right_hand_good = 0 - if(L && (!(L.status & ORGAN_DESTROYED)) && (!(L.status & ORGAN_SPLINTED)) && (!(L.status & ORGAN_BROKEN))) - left_hand_good = 1 - if(R && (!(R.status & ORGAN_DESTROYED)) && (!(R.status & ORGAN_SPLINTED)) && (!(R.status & ORGAN_BROKEN))) - right_hand_good = 1 - - if (!left_hand_good && !right_hand_good) - to_chat(usr, "You need at least one hand in good working order to snap your fingers.") - return - - message = "[src] snaps \his fingers." - playsound(src.loc, 'sound/effects/fingersnap.ogg', 50, 1, -3) - else - message = "[src] snaps \his fingers right off!" - playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) - - - // Needed for M_TOXIC_FART - if("fart", "farts") - if(reagents.has_reagent("simethicone")) - return -// playsound(src.loc, 'sound/effects/fart.ogg', 50, 1, -3) //Admins still vote no to fun - if(locate(/obj/item/weapon/storage/bible) in get_turf(src)) - to_chat(viewers(src), "[src] farts on the Bible!") - to_chat(viewers(src), "A mysterious force smites [src]!") - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - src.gib() - else if(TOXIC_FARTS in mutations) - message = "[src] unleashes a [pick("horrible","terrible","foul","disgusting","awful")] fart." - else - message = "[src] [pick("passes wind","farts")]." - m_type = 2 - - var/turf/location = get_turf(src) - var/aoe_range=2 // Default - - // Process toxic farts first. - if(TOXIC_FARTS in mutations) - for(var/mob/M in range(location,aoe_range)) - if (M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT)) - continue - // Now, we don't have this: - //new /obj/effects/fart_cloud(T,L) - if (M == src) - continue - M.reagents.add_reagent("jenkem", 1) - - if ("help") - var/emotelist = "aflap(s), airguitar, blink(s), blink(s)_r, blush(es), bow(s)-(none)/mob, burp(s), choke(s), chuckle(s), clap(s), collapse(s), cough(s),cry, cries, custom, dap(s)(none)/mob," \ - + " deathgasp(s), drool(s), eyebrow,fart(s), faint(s), flap(s), flip(s), frown(s), gasp(s), giggle(s), glare(s)-(none)/mob, grin(s), groan(s), grumble(s), handshake-mob, hug(s)-(none)/mob," \ - + " glare(s)-(none)/mob, grin(s), johnny, laugh(s), look(s)-(none)/mob, moan(s), mumble(s), nod(s), pale(s), point(s)-atom, quiver(s), raise(s), salute(s)-(none)/mob, scream(s), shake(s)," \ - + " shiver(s), shrug(s), sigh(s), signal(s)-#1-10,slap(s)-(none)/mob, smile(s),snap(s), sneeze(s), sniff(s), snore(s), stare(s)-(none)/mob, swag(s), tremble(s), twitch(es), twitch(es)_s," \ - + " wag(s), wave(s), whimper(s), wink(s), yawn(s)" - if(species.name == "Machine") - emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob" - else if(species.name == "Slime People") - emotelist += "\nSlime people specific emotes :- squish(es)-(none)/mob" - to_chat(src, emotelist) - - else - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - - - - - - if(message) //Humans are special fucking snowflakes and have 735 lines of emotes, they get to handle their own emotes, not call the parent - log_emote("[name]/[key] : [message]") - - //Hearing gasp and such every five seconds is not good emotes were not global for a reason. - // Maybe some people are okay with that. - - for(var/mob/M in dead_mob_list) - if(!M.client || istype(M, /mob/new_player)) - continue //skip monkeys, leavers and new players - if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - switch(m_type) - if(1) - visible_message(message) - if(2) - audible_message(message) - -/mob/living/carbon/human/verb/pose() - set name = "Set Pose" - set desc = "Sets a description which will be shown when someone examines you." - set category = "IC" - - pose = sanitize(copytext(input(usr, "This is [src]. \He is...", "Pose", null) as text, 1, MAX_MESSAGE_LEN)) - -/mob/living/carbon/human/verb/set_flavor() - set name = "Set Flavour Text" - set desc = "Sets an extended description of your character's features." - set category = "IC" - - update_flavor_text() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index cb067591904..ed02823215f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1537,14 +1537,17 @@ if(species.base_color && default_colour) //Apply colour. - r_skin = hex2num(copytext(species.base_color,2,4)) - g_skin = hex2num(copytext(species.base_color,4,6)) - b_skin = hex2num(copytext(species.base_color,6,8)) + r_skin = hex2num(copytext(species.base_color, 2, 4)) + g_skin = hex2num(copytext(species.base_color, 4, 6)) + b_skin = hex2num(copytext(species.base_color, 6, 8)) else r_skin = 0 g_skin = 0 b_skin = 0 + if(!(species.bodyflags & HAS_SKIN_TONE)) + s_tone = 0 + species.create_organs(src) //Handle default hair/head accessories for created mobs. @@ -1556,6 +1559,32 @@ if(species.default_headacc) H.ha_style = species.default_headacc + if(species.default_hair_colour) + //Apply colour. + H.r_hair = hex2num(copytext(species.default_hair_colour, 2, 4)) + H.g_hair = hex2num(copytext(species.default_hair_colour, 4, 6)) + H.b_hair = hex2num(copytext(species.default_hair_colour, 6, 8)) + else + H.r_hair = 0 + H.g_hair = 0 + H.b_hair = 0 + if(species.default_fhair_colour) + H.r_facial = hex2num(copytext(species.default_fhair_colour, 2, 4)) + H.g_facial = hex2num(copytext(species.default_fhair_colour, 4, 6)) + H.b_facial = hex2num(copytext(species.default_fhair_colour, 6, 8)) + else + H.r_facial = 0 + H.g_facial = 0 + H.b_facial = 0 + if(species.default_headacc_colour) + H.r_headacc = hex2num(copytext(species.default_headacc_colour, 2, 4)) + H.g_headacc = hex2num(copytext(species.default_headacc_colour, 4, 6)) + H.b_headacc = hex2num(copytext(species.default_headacc_colour, 6, 8)) + else + H.r_headacc = 0 + H.g_headacc = 0 + H.b_headacc = 0 + if(!dna) dna = new /datum/dna(null) dna.species = species.name diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index f9d9ae27442..bde2c900636 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -218,6 +218,7 @@ W.loc = src W.equipped(src, slot) W.layer = 20 + W.plane = HUD_PLANE switch(slot) if(slot_back) @@ -260,6 +261,7 @@ O.loc = src r_ear = O O.layer = 20 + O.plane = HUD_PLANE update_inv_ears(redraw_mob) if(slot_r_ear) r_ear = W @@ -268,6 +270,7 @@ O.loc = src l_ear = O O.layer = 20 + O.plane = HUD_PLANE update_inv_ears(redraw_mob) if(slot_glasses) glasses = W diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 14585c8d972..d96dd018f2a 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -39,6 +39,7 @@ handle_pain() handle_heartbeat() handle_heartattack() + handle_drunk() species.handle_life(src) if(!client) @@ -730,6 +731,80 @@ return //TODO: DEFERRED +/mob/living/carbon/human/handle_drunk() + var/slur_start = 30 //12u ethanol, 30u whiskey FOR HUMANS + var/confused_start = 40 + var/brawl_start = 30 + var/blur_start = 75 + var/vomit_start = 60 + var/pass_out = 90 + var/spark_start = 50 //40u synthanol + var/collapse_start = 75 + var/braindamage_start = 120 + var/alcohol_strength = drunk + var/sober_str=!(SOBER in mutations)?1:2 + + if(drunk) + alcohol_strength/=sober_str + + var/obj/item/organ/internal/liver/L + if(!isSynthetic()) + L = get_int_organ(/obj/item/organ/internal/liver) + if(L) + alcohol_strength *= L.alcohol_intensity + else + alcohol_strength *= 5 + + if(alcohol_strength >= slur_start) //slurring + if (!slurring) slurring = 1 + slurring = drunk + if(alcohol_strength >= brawl_start) //the drunken martial art + if(!istype(martial_art, /datum/martial_art/drunk_brawling)) + var/datum/martial_art/drunk_brawling/F = new + F.teach(src,1) + if(alcohol_strength < brawl_start) //removing the art + if(istype(martial_art, /datum/martial_art/drunk_brawling)) + martial_art.remove(src) + if(alcohol_strength >= confused_start && prob(33)) //confused walking + if (!confused) confused = 1 + confused = max(confused+(3/sober_str),0) + if(alcohol_strength >= blur_start) //blurry eyes + eye_blurry = max(eye_blurry, 10/sober_str) + drowsyness = max(drowsyness, 0) + if(!isSynthetic()) //stuff only for non-synthetics + if(alcohol_strength >= vomit_start) //vomiting + if(prob(8)) + fakevomit() + if(alcohol_strength >= pass_out) + Paralyse(5 / sober_str) + drowsyness = max(drowsyness, 30/sober_str) + if (L) + L.take_damage(0.1, 1) + adjustToxLoss(0.1) + else //stuff only for synthetics + if(alcohol_strength >= spark_start && prob(25)) + var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + if(alcohol_strength >= collapse_start && prob(10)) + emote("collapse") + var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + if(alcohol_strength >= braindamage_start && prob(10)) + adjustBrainLoss(1) + + if(!has_booze()) + AdjustDrunk(-0.5) + return + +/mob/living/carbon/human/proc/has_booze() //checks if the human has ethanol or its subtypes inside + for(var/A in reagents.reagent_list) + var/datum/reagent/R = A + if(istype(R, /datum/reagent/ethanol)) + return 1 + return 0 + /mob/living/carbon/human/handle_regular_status_updates() if(status_flags & GODMODE) return 0 diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index f6a1e5e2088..ad0d5b18c61 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -121,8 +121,14 @@ //Default hair/headacc style vars. var/default_hair = "Bald" //Default hair style for newly created humans unless otherwise set. + var/default_hair_colour var/default_fhair = "Shaved" //Default facial hair style for newly created humans unless otherwise set. + var/default_fhair_colour var/default_headacc = "None" //Default head accessory style for newly created humans unless otherwise set. + var/default_headacc_colour + + //Defining lists of icon skin tones for species that have them. + var/list/icon_skin_tones = list() // Determines the organs that the species spawns with and var/list/has_organ = list( // which required-organ checks are conducted. @@ -372,6 +378,9 @@ grant_abilities(C) return +/datum/species/proc/updatespeciescolor(var/mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors. + return + /datum/species/proc/grant_abilities(var/mob/living/carbon/human/H) for(var/proc/ability in species_abilities) H.verbs += ability diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 65d100dc420..7f5daa824d5 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -59,6 +59,16 @@ default_hair = "Unathi Horns" butt_sprite = "unathi" + 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, + ) + 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) @@ -116,6 +126,16 @@ default_headacc = "Tajaran Ears" 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, + ) + 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) @@ -161,6 +181,16 @@ base_color = "#B43214" butt_sprite = "vulp" + 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, + ) + 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) @@ -221,8 +251,8 @@ /datum/species/vox name = "Vox" name_plural = "Vox" - icobase = 'icons/mob/human_races/r_vox.dmi' - deform = 'icons/mob/human_races/r_def_vox.dmi' + icobase = 'icons/mob/human_races/vox/r_vox.dmi' + deform = 'icons/mob/human_races/vox/r_def_vox.dmi' path = /mob/living/carbon/human/vox default_language = "Galactic Common" @@ -267,12 +297,13 @@ flags = NO_SCAN | IS_WHITELISTED clothing_flags = HAS_SOCKS dietflags = DIET_OMNI - bodyflags = HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED + bodyflags = HAS_ICON_SKIN_TONE | HAS_TAIL | TAIL_WAGGING | TAIL_OVERLAPPED 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 @@ -280,10 +311,19 @@ male_scream_sound = 'sound/voice/shriek1.ogg' female_scream_sound = 'sound/voice/shriek1.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, - "liver" = /obj/item/organ/internal/liver, + "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, @@ -327,12 +367,44 @@ if (H.internals) H.internals.icon_state = "internal1" -/* /datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - H.verbs += /mob/living/carbon/human/proc/leap - ..() */ + updatespeciescolor(H) + H.update_icons() + //H.verbs += /mob/living/carbon/human/proc/leap + ..() + +/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H) //Handling species-specific skin-tones for the Vox race. + if(H.species.name == "Vox") //Making sure we don't break Armalis. + switch(H.s_tone) + if(6) //Azure Vox. + icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' + tail = "voxtail_azu" + if(5) //Emerald Vox. + icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' + tail = "voxtail_emrl" + if(4) //Grey Vox. + icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' + tail = "voxtail_gry" + if(3) //Brown Vox. + icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' + tail = "voxtail_brn" + if(2) //Dark Green Vox. + icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi' + tail = "voxtail_dgrn" + else //Default Green Vox. + icobase = 'icons/mob/human_races/vox/r_vox.dmi' + deform = 'icons/mob/human_races/vox/r_def_vox.dmi' + tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone. + + H.update_dna() /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 ..() @@ -412,6 +484,16 @@ reagent_tag = PROCESS_ORG 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, + ) + allowed_consumed_mobs = list(/mob/living/simple_animal/diona) suicide_messages = list( @@ -616,6 +698,16 @@ 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, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, + ) + brute_mod = 1.25 //greys are fragile default_genes = list(REMOTE_TALK) @@ -838,4 +930,4 @@ spawn(100) if(H) H.update_hair() - H.update_fhair() \ No newline at end of file + H.update_fhair() diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 45bc15b1d51..628ea630555 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -212,6 +212,9 @@ var/global/list/damage_icon_parts = list() var/hulk = (HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) + if(species && species.bodyflags & HAS_ICON_SKIN_TONE) + species.updatespeciescolor(src) + //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. @@ -636,6 +639,7 @@ var/global/list/damage_icon_parts = list() thing.loc = loc // thing.dropped(src) // thing.layer = initial(thing.layer) + thing.plane = initial(thing.plane) if(update_icons) update_icons() /mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) @@ -1108,12 +1112,13 @@ var/global/list/damage_icon_parts = list() if(body_accessory) if(body_accessory.try_restrictions(src)) var/icon/accessory_s = new/icon("icon" = body_accessory.icon, "icon_state" = body_accessory.icon_state) - accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) + if(species.bodyflags & HAS_SKIN_COLOR) + accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) - if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... + if(species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/temp1 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(src.species.name in body_accessory.allowed_species) + if(species.name in body_accessory.allowed_species) var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay") temp1 = temp else @@ -1129,7 +1134,7 @@ var/global/list/damage_icon_parts = list() // Creates a blank icon, and copies accessory_s' north direction sprite into it // before passing that to the tail layer that overlays uniforms and such. var/icon/temp2 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(src.species.name in body_accessory.allowed_species) + if(species.name in body_accessory.allowed_species) var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay") temp2 = temp else @@ -1145,9 +1150,10 @@ var/global/list/damage_icon_parts = list() else if(species.tail && species.bodyflags & HAS_TAIL) //no tailless tajaran if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") - tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + if(species.bodyflags & HAS_SKIN_COLOR) + tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... + if(species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/temp1 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay") temp1.Insert(new/icon(tail_s,dir=SOUTH),dir=SOUTH) @@ -1177,13 +1183,14 @@ var/global/list/damage_icon_parts = list() if(body_accessory) var/icon/accessory_s = new/icon("icon" = body_accessory.get_animated_icon(), "icon_state" = body_accessory.get_animated_icon_state()) - accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) + if(species.bodyflags & HAS_SKIN_COLOR) + accessory_s.Blend(rgb(r_skin, g_skin, b_skin), body_accessory.blend_mode) - if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... + if(species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/temp1 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") if(body_accessory.allowed_species) - if(src.species.name in body_accessory.allowed_species) + if(species.name in body_accessory.allowed_species) var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay") temp1 = temp else @@ -1199,7 +1206,7 @@ var/global/list/damage_icon_parts = list() // Creates a blank icon, and copies accessory_s' north direction sprite into it // before passing that to the tail layer that overlays uniforms and such. var/icon/temp2 = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(src.species.name in body_accessory.allowed_species) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank + if(species.name in body_accessory.allowed_species) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank var/icon/temp = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "[species.tail]_delay") temp2 = temp else // Else if the user's species is not in the list of allowed species for the currently selected body accessory, this point must have been reached by admin-override. Use vulpkanin timings as default. @@ -1214,9 +1221,10 @@ var/global/list/damage_icon_parts = list() else if(species.tail && species.bodyflags & HAS_TAIL) var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]w_s") - tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + if(species.bodyflags & HAS_SKIN_COLOR) + tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - if(src.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... + if(species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/temp1 = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_delay") temp1.Insert(tailw_s,dir=SOUTH) diff --git a/code/modules/mob/living/carbon/slime/emote.dm b/code/modules/mob/living/carbon/slime/emote.dm deleted file mode 100644 index 8c290dc6094..00000000000 --- a/code/modules/mob/living/carbon/slime/emote.dm +++ /dev/null @@ -1,75 +0,0 @@ -/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null) - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - //param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - act = lowertext(act) - switch(act) //Alphabetical please - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) - to_chat(src, "\red You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - if("bounce") - message = "The [src.name] bounces in place." - m_type = 1 - - if ("custom") - return custom_emote(m_type, message) - - if("jiggle") - message = "The [src.name] jiggles!" - m_type = 1 - - if("light") - message = "The [src.name] lights up for a bit, then stops." - m_type = 1 - - if("moan") - message = "The [src.name] moans." - m_type = 2 - - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - - if("twitch") - message = "The [src.name] twitches." - m_type = 1 - - if("vibrate") - message = "The [src.name] vibrates!" - m_type = 1 - - if ("help") //This is an exception - to_chat(src, "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate") - - else - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - if ((message && src.stat == 0)) - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - //Foreach goto(703) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - //Foreach goto(746) - return \ No newline at end of file diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 85526945b54..82f865621da 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -114,6 +114,7 @@ handle_paralysed() handle_sleeping() handle_slowed() + handle_drunk() /mob/living/proc/handle_stunned() @@ -168,6 +169,11 @@ slowed = max(slowed-1, 0) return slowed +/mob/living/proc/handle_drunk() + if(drunk) + AdjustDrunk(-1) + return drunk + /mob/living/proc/handle_disabilities() //Eyes if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own @@ -323,4 +329,4 @@ if(client) var/client/C = client for(var/mob/living/carbon/human/H in view(src, world.view)) - C.images += H.hud_list[NATIONS_HUD] \ No newline at end of file + C.images += H.hud_list[NATIONS_HUD] diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index c6d0d8e3ee0..85eea65bbab 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -296,34 +296,6 @@ proc/get_radio_key_from_channel(var/channel) /mob/living/proc/GetVoice() return name -/mob/living/emote(var/act, var/type, var/message) //emote code is terrible, this is so that anything that isn't - if(stat) return 0 //already snowflaked to shit can call the parent and handle emoting sanely - - if(..(act, type, message)) - return 1 - - if(act && type && message) //parent call - log_emote("[name]/[key] : [message]") - - for(var/mob/M in dead_mob_list) - if(!M.client || istype(M, /mob/new_player)) - continue //skip monkeys, leavers and new players //who the hell knows why new players are in the dead mob list - - if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - switch(type) - if(1) //Visible - visible_message(message) - return 1 - if(2) //Audible - audible_message(message) - return 1 - - else //everything else failed, emote is probably invalid - if(act == "help") return //except help, because help is handled individually - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - /mob/living/whisper(message as text) message = trim_strip_html_properly(message) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm deleted file mode 100644 index 233df91eb55..00000000000 --- a/code/modules/mob/living/silicon/emote.dm +++ /dev/null @@ -1,127 +0,0 @@ -/mob/living/silicon/emote(var/act, var/m_type=1, var/message = null) - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] - var/on_CD = 0 - act = lowertext(act) - switch(act) - //Cooldown-inducing emotes - if("scream", "screams") - on_CD = handle_emote_CD(50) //longer cooldown - if("ping","pings","buzz","buzzs","buzzes","beep","beeps","yes","no", "buzz2") - //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - //Everything else, including typos of the above emotes - else - on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - - if(on_CD == 1) // Check if we need to suppress the emote attempt. - return // Suppress emote, you're still cooling off. - //--FalseIncarnate - - switch(act) - if("ping","pings") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] pings at [param]." - else - message = "[src] pings." - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - m_type = 2 - - if("buzz","buzzs","buzzes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] buzzes at [param]." - else - message = "[src] buzzes." - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = 2 - - if("beep","beeps") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] beeps at [param]." - else - message = "[src] beeps." - playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) - m_type = 2 - - if("yes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits an affirmative blip at [param]." - else - message = "[src] emits an affirmative blip." - playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0) - m_type = 2 - - if("no") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits a negative blip at [param]." - else - message = "[src] emits a negative blip." - playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0) - m_type = 2 - - if("scream", "screams") - message = "[src] screams!" - playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0) - m_type = 2 - - if("buzz2") - message = "[src] emits an irritated buzzing sound." - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) - m_type = 2 - - - if("help") - to_chat(src, "yes, no, beep, ping, buzz, scream, buzz2") - - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm deleted file mode 100644 index a418c0972d5..00000000000 --- a/code/modules/mob/living/silicon/pai/emote.dm +++ /dev/null @@ -1,2 +0,0 @@ -/mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null) - ..(act, m_type, message) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm deleted file mode 100644 index 36c61910e6d..00000000000 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ /dev/null @@ -1,163 +0,0 @@ -/mob/living/silicon/robot/emote(var/act, var/m_type=1, var/message = null) - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] - var/on_CD = 0 - act = lowertext(act) - switch(act) - //Cooldown-inducing emotes - if("law","flip","flips","halt") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - //Everything else, including typos of the above emotes - else - on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - - if(on_CD == 1) // Check if we need to suppress the emote attempt. - return // Suppress emote, you're still cooling off. - //--FalseIncarnate - - switch(act) - - if ("salute","salutes") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] salutes to [param]." - else - message = "[src] salutes." - m_type = 1 - if ("bow","bows") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] bows to [param]." - else - message = "[src] bows." - m_type = 1 - - if ("clap","claps") - if (!src.restrained()) - message = "[src] claps." - m_type = 2 - if ("flap","flaps") - if (!src.restrained()) - message = "[src] flaps its wings." - m_type = 2 - - if ("aflap","aflaps") - if (!src.restrained()) - message = "[src] flaps its wings ANGRILY!" - m_type = 2 - - if ("twitch") - message = "[src] twitches violently." - m_type = 1 - - if ("twitch_s","twitches") - message = "[src] twitches." - m_type = 1 - - if ("nod","nods") - message = "[src] nods." - m_type = 1 - - if ("deathgasp") - message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." - m_type = 1 - - if ("glare","glares") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] glares at [param]." - else - message = "[src] glares." - - if ("stare","stares") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] stares at [param]." - else - message = "[src] stares." - - if ("look","looks") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - - if (!M) - param = null - - if (param) - message = "[src] looks at [param]." - else - message = "[src] looks." - m_type = 1 - - - if("law") - if (istype(module,/obj/item/weapon/robot_module/security)) - message = "[src] shows its legal authorization barcode." - - playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0) - m_type = 2 - else - to_chat(src, "You are not THE LAW, pal.") - - if("halt") - if (istype(module,/obj/item/weapon/robot_module/security)) - message = "[src]'s speakers skreech, \"Halt! Security!\"." - - playsound(src.loc, 'sound/voice/halt.ogg', 50, 0) - m_type = 2 - else - to_chat(src, "You are not security.") - - if ("flip","flips") - m_type = 1 - message = "[src] does a flip!" - src.SpinAnimation(5,1) - - if ("help") - to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitches, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look,\n law, halt") - - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 9b2f5d1c7c1..7e824eeb279 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -56,6 +56,7 @@ O.mouse_opacity = initial(O.mouse_opacity) module_state_1 = O O.layer = 20 + O.plane = HUD_PLANE O.screen_loc = inv1.screen_loc contents += O if(istype(module_state_1,/obj/item/borg/sight)) @@ -64,6 +65,7 @@ O.mouse_opacity = initial(O.mouse_opacity) module_state_2 = O O.layer = 20 + O.plane = HUD_PLANE O.screen_loc = inv2.screen_loc contents += O if(istype(module_state_2,/obj/item/borg/sight)) @@ -72,6 +74,7 @@ O.mouse_opacity = initial(O.mouse_opacity) module_state_3 = O O.layer = 20 + O.plane = HUD_PLANE O.screen_loc = inv3.screen_loc contents += O if(istype(module_state_3,/obj/item/borg/sight)) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index a546e164901..94ae02a56ce 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -128,13 +128,6 @@ return return 1 -/mob/living/silicon/ai/emote(var/act, var/type, var/message) - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.hologram && T.master == src) //Is the AI using a holopad? - src.holopad_emote(message) - else //Emote normally, then. - ..() - #undef IS_AI #undef IS_ROBOT #undef IS_PAI diff --git a/code/modules/mob/living/simple_animal/bot/emote.dm b/code/modules/mob/living/simple_animal/bot/emote.dm deleted file mode 100644 index 0c8b591f069..00000000000 --- a/code/modules/mob/living/simple_animal/bot/emote.dm +++ /dev/null @@ -1,120 +0,0 @@ -/mob/living/simple_animal/bot/emote(var/act, var/m_type=1, var/message = null) - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] - var/on_CD = 0 - act = lowertext(act) - switch(act) - //Cooldown-inducing emotes - if("scream", "screams") - on_CD = handle_emote_CD(50) //longer cooldown - if("ping","buzz","beep","yes","no") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. - on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm - //Everything else, including typos of the above emotes - else - on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - - if(on_CD == 1) // Check if we need to suppress the emote attempt. - return // Suppress emote, you're still cooling off. - //--FalseIncarnate - - switch(act) - if("ping") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] pings at [param]." - else - message = "[src] pings." - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - m_type = 2 - - if("buzz") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] buzzes at [param]." - else - message = "[src] buzzes." - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = 2 - - if("beep") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] beeps at [param]." - else - message = "[src] beeps." - playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) - m_type = 2 - - if("yes") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits an affirmative blip at [param]." - else - message = "[src] emits an affirmative blip." - playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0) - m_type = 2 - - if("no") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] emits a negative blip at [param]." - else - message = "[src] emits a negative blip." - playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0) - m_type = 2 - - if("scream", "screams") - message = "[src] screams!" - playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0) - m_type = 2 - - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm index f62176ee926..125061f9275 100644 --- a/code/modules/mob/living/simple_animal/friendly/diona.dm +++ b/code/modules/mob/living/simple_animal/friendly/diona.dm @@ -243,31 +243,9 @@ /mob/living/simple_animal/diona/put_in_hands(obj/item/W) W.loc = get_turf(src) W.layer = initial(W.layer) + W.plane = initial(W.plane) W.dropped() /mob/living/simple_animal/diona/put_in_active_hand(obj/item/W) to_chat(src, "You don't have any hands!") return - -/mob/living/simple_animal/diona/emote(var/act, var/m_type=1, var/message = null) - if(stat) - return - - var/on_CD = 0 - act = lowertext(act) - switch(act) - if("chirp") - on_CD = handle_emote_CD() - else - on_CD = 0 - - if(on_CD == 1) - return - - switch(act) //IMPORTANT: Emotes MUST NOT CONFLICT anywhere along the chain. - if("chirp") - message = "\The [src] chirps!" - m_type = 2 //audible - playsound(src, 'sound/misc/nymphchirp.ogg', 40, 1, 1) - - ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index ef048b351fd..faf0cc0f9a3 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -260,21 +260,23 @@ if(target == start) return - var/obj/item/projectile/A = new projectiletype(src.loc) - playsound(user, projectilesound, 100, 1) - if(!A) - return - - A.current = target - A.firer = src - A.yo = target:y - start:y - A.xo = target:x - start:x - if(AIStatus == AI_OFF)//Don't want mindless mobs to have their movement screwed up firing in space - newtonian_move(get_dir(target, user)) - A.original = target - spawn( 0 ) + if(casingtype) + var/obj/item/ammo_casing/casing = new casingtype + playsound(src, projectilesound, 100, 1) + casing.fire(target, src, zone_override = ran_zone()) + casing.loc = loc + else + var/obj/item/projectile/A = new projectiletype(loc) + playsound(user, projectilesound, 100, 1) + A.current = target + A.firer = src + A.yo = target:y - start:y + A.xo = target:x - start:x + if(AIStatus == AI_OFF)//Don't want mindless mobs to have their movement screwed up firing in space + newtonian_move(get_dir(target, user)) + A.original = target A.fire() - return + return A /mob/living/simple_animal/hostile/proc/DestroySurroundings() if(environment_smash) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index e5ee97a70ef..f14d1bf649a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -1,7 +1,3 @@ -// -// Abstract Class -// - /mob/living/simple_animal/hostile/mimic name = "crate" desc = "A rectangular steel crate." @@ -39,7 +35,7 @@ /mob/living/simple_animal/hostile/mimic/death() ..() - visible_message("\red [src] stops moving!") + visible_message("[src] stops moving!") ghostize() qdel(src) @@ -52,16 +48,9 @@ adjustBruteLoss(50) ..(severity) -// -// Crate Mimic -// - - // Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. /mob/living/simple_animal/hostile/mimic/crate - attacktext = "bites" - stop_automated_movement = 1 wander = 0 var/attempt_open = 0 @@ -112,7 +101,6 @@ icon_state = initial(icon_state) /mob/living/simple_animal/hostile/mimic/crate/death() - var/obj/structure/closet/crate/C = new(get_turf(src)) // Put loot in crate for(var/obj/O in src) @@ -127,22 +115,18 @@ L.Weaken(2) L.visible_message("\the [src] knocks down \the [L]!") -// -// Copy Mimic -// - -var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window, /obj/item/projectile/magic/animate) +var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window) /mob/living/simple_animal/hostile/mimic/copy - health = 100 maxHealth = 100 var/mob/living/creator = null // the creator var/destroy_objects = 0 var/knockdown_people = 0 + var/image/googly_eyes = null gold_core_spawnable = CHEM_MOB_SPAWN_INVALID -/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0) +/mob/living/simple_animal/hostile/mimic/copy/New(loc, obj/copy, mob/living/creator, destroy_original = 0) ..(loc) CopyObject(copy, creator, destroy_original) @@ -158,7 +142,6 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca ..() /mob/living/simple_animal/hostile/mimic/copy/ListTargets() - // Return a list of targets that isn't the creator . = ..() return . - creator @@ -173,10 +156,8 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca return 1 return 0 -/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/creator, var/destroy_original = 0) - +/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(var/obj/O, var/mob/living/user, var/destroy_original = 0) if(destroy_original || CheckObject(O)) - O.loc = src name = O.name desc = O.desc @@ -184,7 +165,8 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca icon_state = O.icon_state icon_living = icon_state overlays = O.overlays - + googly_eyes = image('icons/mob/mob.dmi',"googly_eyes") + overlays += googly_eyes if(istype(O, /obj/structure) || istype(O, /obj/machinery)) health = (anchored * 50) + 50 destroy_objects = 1 @@ -202,10 +184,9 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca move_to_delay = 2 * I.w_class + 1 if(istype(O, /obj/item/device)) is_electronic = 1 - maxHealth = health - if(creator) - src.creator = creator + if(user) + creator = user faction += "\ref[creator]" // very unique if(destroy_original) qdel(O) @@ -226,9 +207,9 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca C.visible_message("\The [src] knocks down \the [C]!", \ "\The [src] knocks you down!") -// -// Machine Mimics (Made by Malf AI) -// +/mob/living/simple_animal/hostile/mimic/copy/Aggro() + ..() + googly_eyes.dir = get_dir(src,target) /mob/living/simple_animal/hostile/mimic/copy/machine speak = list("HUMANS ARE IMPERFECT!", "YOU SHALL BE ASSIMILATED!", "YOU ARE HARMING YOURSELF", "You have been deemed hazardous. Will you comply?", \ @@ -242,4 +223,77 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca var/mob/living/silicon/robot/R = the_target if(R.connected_ai == creator) // Only attack robots that aren't synced to our creator AI. return 0 - return ..() \ No newline at end of file + return ..() + +/mob/living/simple_animal/hostile/mimic/copy/ranged + var/obj/item/weapon/gun/TrueGun = null + var/obj/item/weapon/gun/magic/Zapstick + var/obj/item/weapon/gun/projectile/Pewgun + var/obj/item/weapon/gun/energy/Zapgun + +/mob/living/simple_animal/hostile/mimic/copy/ranged/CopyObject(obj/O, mob/living/creator, destroy_original = 0) + if(..()) + emote_see = list("aims menacingly") + environment_smash = 0 //needed? seems weird for them to do so + ranged = 1 + retreat_distance = 1 //just enough to shoot + minimum_distance = 6 + var/obj/item/weapon/gun/G = O + melee_damage_upper = G.force + melee_damage_lower = G.force - max(0, (G.force / 2)) + move_to_delay = 2 * G.w_class + 1 + projectilesound = G.fire_sound + TrueGun = G + if(istype(G, /obj/item/weapon/gun/magic)) + Zapstick = G + var/obj/item/ammo_casing/magic/M = Zapstick.ammo_type + projectiletype = initial(M.projectile_type) + if(istype(G, /obj/item/weapon/gun/projectile)) + Pewgun = G + var/obj/item/ammo_box/magazine/M = Pewgun.mag_type + casingtype = initial(M.ammo_type) + if(istype(G, /obj/item/weapon/gun/energy)) + Zapgun = G + var/selectfiresetting = Zapgun.select + var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[selectfiresetting] + projectiletype = initial(E.projectile_type) + +/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(the_target) + if(Zapgun) + if(Zapgun.power_supply) + var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select] + if(Zapgun.power_supply.charge >= shot.e_cost) + Zapgun.power_supply.use(shot.e_cost) + Zapgun.update_icon() + ..() + else if(Zapstick) + if(Zapstick.charges) + Zapstick.charges-- + Zapstick.update_icon() + ..() + else if(Pewgun) + if(Pewgun.chambered) + if(Pewgun.chambered.BB) + qdel(Pewgun.chambered.BB) + Pewgun.chambered.BB = null //because qdel takes too long, ensures icon update + Pewgun.chambered.update_icon() + ..() + else + visible_message("The [src] clears a jam!") + Pewgun.chambered.loc = loc //rip revolver immersions, blame shotgun snowflake procs + Pewgun.chambered = null + if(Pewgun.magazine && Pewgun.magazine.stored_ammo.len) + Pewgun.chambered = Pewgun.magazine.get_round(0) + Pewgun.chambered.loc = Pewgun + Pewgun.update_icon() + else if(Pewgun.magazine && Pewgun.magazine.stored_ammo.len) //only true for pumpguns i think + Pewgun.chambered = Pewgun.magazine.get_round(0) + Pewgun.chambered.loc = Pewgun + visible_message("The [src] cocks itself!") + else + ranged = 0 //BANZAIIII + retreat_distance = 0 + minimum_distance = 1 + return + icon_state = TrueGun.icon_state + icon_living = TrueGun.icon_state diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index 148eeeef9a7..0126dd5c704 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -32,8 +32,6 @@ ranged = 1 retreat_distance = 5 minimum_distance = 5 - projectiletype = /obj/item/projectile/bullet - projectilesound = 'sound/weapons/Gunshot.ogg' casingtype = /obj/item/ammo_casing/a357 loot = list(/obj/effect/landmark/mobcorpse/russian/ranged, /obj/item/weapon/gun/projectile/revolver/mateba) @@ -45,4 +43,4 @@ /mob/living/simple_animal/hostile/russian/death() ..() qdel(src) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 5546547046d..32bdf5fc772 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -88,8 +88,6 @@ icon_state = "syndicateranged" icon_living = "syndicateranged" casingtype = /obj/item/ammo_casing/c45 - projectilesound = 'sound/weapons/Gunshot_smg.ogg' - projectiletype = /obj/item/projectile/bullet/midbullet2 loot = list(/obj/effect/landmark/mobcorpse/syndicatesoldier, /obj/item/weapon/gun/projectile/automatic/c20r) /mob/living/simple_animal/hostile/syndicate/ranged/space @@ -130,4 +128,4 @@ ..() visible_message("\red [src] is smashed into pieces!") qdel(src) - return \ No newline at end of file + return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8c33a17e829..ead6f0df27c 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -12,6 +12,8 @@ for(var/mob/dead/observer/M in following_mobs) M.following = null following_mobs = null + if(buckled) + buckled.unbuckle_mob() return ..() /mob/New() @@ -21,6 +23,7 @@ else living_mob_list += src prepare_huds() + emoteHandler = new /datum/emoteHandler(src) ..() /atom/proc/prepare_huds() @@ -1095,6 +1098,9 @@ var/list/slot_equipment_priority = list( \ /mob/proc/Dizzy(amount) dizziness = max(dizziness, amount, 0) +/mob/proc/AdjustDrunk(amount) + drunk = max(drunk + amount, 0) + /mob/proc/Stun(amount) SetStunned(max(stunned, amount)) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index bc09aa11a1b..13d5d7c976e 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -63,6 +63,7 @@ var/ajourn = 0 var/druggy = 0 //Carbon var/confused = 0 //Carbon + var/drunk = 0 var/antitoxs = null var/plasma = null var/sleeping = 0 //Carbon @@ -233,3 +234,5 @@ var/datum/vision_override/vision_type = null //Vision override datum. var/list/permanent_huds = list() + + var/datum/emoteHandler/emoteHandler \ No newline at end of file diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index fee4897f375..e9ee311db76 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -23,6 +23,7 @@ var/dancing //determines if assailant and affecting keep looking at each other. Basically a wrestling position layer = 21 + plane = HUD_PLANE item_state = "nothing" icon = 'icons/mob/screen_gen.dmi' w_class = 5.0 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index f961055ca56..f752b1f4409 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -24,7 +24,8 @@ /mob/new_player/proc/new_player_panel_proc() - var/output = "

Setup Character

" + var/real_name = client.prefs.real_name + var/output = "

Setup Character
[real_name]

" if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) if(!ready) output += "

Declare Ready

" diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 63567b0399c..0632e0af5e8 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -199,13 +199,25 @@ var/icon/icobase var/datum/species/current_species = all_species[species] + //Icon-based species colour. + var/coloured_tail if(current_species) - icobase = current_species.icobase + if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. + var/mob/living/carbon/human/H = new + H.species = current_species + H.s_tone = s_tone + H.species.updatespeciescolor(H) + + icobase = H.species.icobase + if(H.species.bodyflags & HAS_TAIL) + coloured_tail = H.species.tail + else + icobase = current_species.icobase else icobase = 'icons/mob/human_races/r_human.dmi' var/fat="" - if(disabilities&DISABILITY_FLAG_FAT && current_species.flags & CAN_BE_FAT) + if(disabilities & DISABILITY_FLAG_FAT && current_species.flags & CAN_BE_FAT) fat="_fat" preview_icon = new /icon(icobase, "torso_[g][fat]") preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) @@ -222,7 +234,10 @@ tail_icon_state = accessory.icon_state else tail_icon = "icons/effects/species.dmi" - tail_icon_state = "[current_species.tail]_s" + if(coloured_tail) + tail_icon_state = "[coloured_tail]_s" + else + tail_icon_state = "[current_species.tail]_s" var/icon/temp = new /icon("icon" = tail_icon, "icon_state" = tail_icon_state) preview_icon.Blend(temp, ICON_OVERLAY) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 93797b5bb17..3ade5970d03 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1017,7 +1017,6 @@ icon_state = "vox_beard" species_allowed = list("Vox") - //Vulpkanin vulp_blaze diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index e3e8d4620be..70d1e72205a 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -27,17 +27,14 @@ set_typing_indicator(0) usr.say(message) -/mob/verb/me_verb(message as text) + +/mob/verb/me_verb() set name = "Me" - set category = "IC" + set category = "Emotes" - message = strip_html_properly(message) + if(emoteHandler) + return emoteHandler.runEmote("me") - set_typing_indicator(0) - if(use_me) - custom_emote(usr.emote_type, message) - else - usr.emote(message) /mob/proc/say_dead(var/message) if(!(client && client.holder)) @@ -98,8 +95,11 @@ /mob/proc/emote(var/act, var/type, var/message) - if(act == "me") - return custom_emote(type, message) + + act = lowertext(act) + return emoteHandler.runEmote(act, message, type) + + /mob/proc/get_ear() // returns an atom representing a location on the map from which this @@ -144,3 +144,6 @@ return L return null + +/mob/proc/custom_emote(var/m_type=0, var/message = null) + return emoteHandler.runEmote("me", message, m_type) \ No newline at end of file diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 583b68b3dc6..55027a90852 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -38,9 +38,27 @@ return 1 if(href_list["skin_tone"]) if(can_change_skin_tone()) - var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null - if(isnum(new_s_tone) && can_still_topic(state)) - new_s_tone = 35 - max(min( round(new_s_tone), 220),1) + var/new_s_tone = null + if(owner.species.bodyflags & HAS_SKIN_TONE) + new_s_tone = input(usr, "Choose your character's skin tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null + if(isnum(new_s_tone) && can_still_topic(state)) + new_s_tone = 35 - max(min(round(new_s_tone), 220),1) + else if(owner.species.bodyflags & HAS_ICON_SKIN_TONE) + var/const/MAX_LINE_ENTRIES = 4 + var/prompt = "Choose your character's skin tone: 1-[owner.species.icon_skin_tones.len]\n(" + for(var/i = 1; i <= owner.species.icon_skin_tones.len; i++) + if(i > MAX_LINE_ENTRIES && !((i - 1) % MAX_LINE_ENTRIES)) + prompt += "\n" + prompt += "[i] = [owner.species.icon_skin_tones[i]]" + if(i != owner.species.icon_skin_tones.len) + prompt += ", " + prompt += ")" + + new_s_tone = input(usr, prompt, "Skin Tone", owner.s_tone) as num|null + if(isnum(new_s_tone) && can_still_topic(state)) + new_s_tone = max(min(round(new_s_tone), owner.species.icon_skin_tones.len), 1) + + if(new_s_tone) return owner.change_skin_tone(new_s_tone) if(href_list["skin_color"]) if(can_change_skin_color()) @@ -209,7 +227,7 @@ return owner && (flags & flag) /datum/nano_module/appearance_changer/proc/can_change_skin_tone() - return owner && (flags & APPEARANCE_SKIN) && (owner.species.bodyflags & HAS_SKIN_TONE) + return owner && (flags & APPEARANCE_SKIN) && ((owner.species.bodyflags & HAS_SKIN_TONE) || (owner.species.bodyflags & HAS_ICON_SKIN_TONE)) /datum/nano_module/appearance_changer/proc/can_change_skin_color() return owner && (flags & APPEARANCE_SKIN) && (owner.species.bodyflags & HAS_SKIN_COLOR) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index bf847a06c0a..4ebd93adc07 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -398,12 +398,14 @@ h_user.unEquip(src) B.loc = h_user B.layer = 20 + B.plane = HUD_PLANE h_user.l_store = B h_user.update_inv_pockets() else if (h_user.r_store == src) h_user.unEquip(src) B.loc = h_user B.layer = 20 + B.plane = HUD_PLANE h_user.r_store = B h_user.update_inv_pockets() else if (h_user.head == src) diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index a99efb09294..0cd00015af4 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -204,6 +204,7 @@ for(var/obj/O in src) O.loc = usr.loc O.layer = initial(O.layer) + O.plane = initial(O.plane) O.add_fingerprint(usr) usr.unEquip(src) qdel(src) diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 5dd8f2e36ea..dd15f904614 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -113,6 +113,7 @@ var/global/list/rad_collectors = list() return Z.loc = get_turf(src) Z.layer = initial(Z.layer) + Z.plane = initial(Z.plane) src.P = null if(active) toggle_power() diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index f47a4db719b..26dce25ead2 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -31,9 +31,9 @@ icon_state = "[initial(icon_state)][BB ? "-live" : ""]" desc = "[initial(desc)][BB ? "" : " This one is spent"]" -/obj/item/ammo_casing/proc/newshot() //For energy weapons, shotgun shells and wands (!). +/obj/item/ammo_casing/proc/newshot(params) //For energy weapons, shotgun shells and wands (!). if (!BB) - BB = new projectile_type(src) + BB = new projectile_type(src, params) return /obj/item/ammo_casing/attackby(obj/item/I as obj, mob/user as mob, params) diff --git a/code/modules/projectiles/ammunition/energy.dm b/code/modules/projectiles/ammunition/energy.dm index d7f26ff3919..7ed6fd4d9ed 100644 --- a/code/modules/projectiles/ammunition/energy.dm +++ b/code/modules/projectiles/ammunition/energy.dm @@ -104,14 +104,16 @@ /obj/item/ammo_casing/energy/temp projectile_type = /obj/item/projectile/temp - var/temperature = 300 e_cost = 100 fire_sound = 'sound/weapons/pulse3.ogg' -/obj/item/ammo_casing/energy/temp/newshot() +/obj/item/ammo_casing/energy/temp/New() ..() - var/obj/item/projectile/temp/T = BB - T.temperature = temperature + BB = null + +/obj/item/ammo_casing/energy/temp/newshot(shot_temp, shot_cost) + e_cost = shot_cost + ..(shot_temp) /obj/item/ammo_casing/energy/meteor projectile_type = /obj/item/projectile/meteor @@ -225,7 +227,21 @@ select_name = "teleport beam" var/teleport_target -/obj/item/ammo_casing/energy/teleport/newshot() +/obj/item/ammo_casing/energy/teleport/New() + ..() + BB = null + +/obj/item/ammo_casing/energy/teleport/newshot(teleport_target) + ..() + +/obj/item/ammo_casing/energy/mimic + projectile_type = /obj/item/projectile/mimic + fire_sound = 'sound/weapons/bite.ogg' + select_name = "gun mimic" + +/obj/item/ammo_casing/energy/mimic/New() + ..() + BB = null + +/obj/item/ammo_casing/energy/mimic/newshot(mimic_type) ..() - var/obj/item/projectile/energy/teleport/T = BB - T.teleport_target = teleport_target diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f86bfff5abb..74a4bcd8ba6 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -161,7 +161,7 @@ return 0 return 1 -obj/item/weapon/gun/proc/newshot() +obj/item/weapon/gun/proc/newshot(params) return /obj/item/weapon/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm index a6bc11ad83e..de217a9715d 100644 --- a/code/modules/projectiles/guns/alien.dm +++ b/code/modules/projectiles/guns/alien.dm @@ -80,7 +80,7 @@ recoil = 1 force = 10 ammo_type = list(/obj/item/ammo_casing/energy/sonic) - cell_type = "/obj/item/weapon/stock_parts/cell/super" + cell_type = /obj/item/weapon/stock_parts/cell/super restricted_species = list("Vox Armalis") /obj/item/weapon/gun/energy/noisecannon/update_icon() diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 24a200915f0..76e86d74699 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -80,13 +80,13 @@ var/obj/item/ammo_casing/energy/shot = ammo_type[select] return power_supply.charge >= shot.e_cost -/obj/item/weapon/gun/energy/newshot() +/obj/item/weapon/gun/energy/newshot(params) if (!ammo_type || !power_supply) return var/obj/item/ammo_casing/energy/shot = ammo_type[select] if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell... chambered = shot //...prepare a new shot based on the current ammo type selected - chambered.newshot() + chambered.newshot(params) return /obj/item/weapon/gun/energy/process_chamber() diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index 3ffa3b59bbb..c155cfb9dff 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -8,7 +8,7 @@ flags = CONDUCT slot_flags = SLOT_BACK ammo_type = list(/obj/item/ammo_casing/energy/laser/pulse, /obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser) - cell_type = "/obj/item/weapon/stock_parts/cell/pulse" + cell_type = /obj/item/weapon/stock_parts/cell/pulse /obj/item/weapon/gun/energy/pulse/emp_act(severity) return @@ -29,7 +29,7 @@ slot_flags = SLOT_BELT icon_state = "pulse_carbine" item_state = "pulse" - cell_type = "/obj/item/weapon/stock_parts/cell/pulse/carbine" + cell_type = /obj/item/weapon/stock_parts/cell/pulse/carbine can_flashlight = 1 flight_x_offset = 18 flight_y_offset = 12 @@ -41,7 +41,7 @@ slot_flags = SLOT_BELT icon_state = "pulse_pistol" item_state = "gun" - cell_type = "/obj/item/weapon/stock_parts/cell/pulse/pistol" + cell_type = /obj/item/weapon/stock_parts/cell/pulse/pistol can_charge = 0 /obj/item/weapon/gun/energy/pulse/pistol/isHandgun() @@ -50,7 +50,7 @@ /obj/item/weapon/gun/energy/pulse/destroyer name = "pulse destroyer" desc = "A heavy-duty, pulse-based energy weapon." - cell_type = "/obj/item/weapon/stock_parts/cell/infinite" + cell_type = /obj/item/weapon/stock_parts/cell/infinite ammo_type = list(/obj/item/ammo_casing/energy/laser/pulse) /obj/item/weapon/gun/energy/pulse/destroyer/attack_self(mob/living/user) @@ -66,7 +66,7 @@ desc = "A compact pulse core in a classic handgun frame for Nanotrasen officers. It's not the size of the gun, it's the size of the hole it puts through people." icon_state = "m1911" item_state = "gun" - cell_type = "/obj/item/weapon/stock_parts/cell/infinite" + cell_type = /obj/item/weapon/stock_parts/cell/infinite /obj/item/weapon/gun/energy/pulse/pistol/m1911/isHandgun() return 1 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 49dbc2bf670..3c4766fd58b 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -62,7 +62,7 @@ item_state = "c20r" w_class = 4 ammo_type = list(/obj/item/ammo_casing/energy/meteor) - cell_type = "/obj/item/weapon/stock_parts/cell/potato" + cell_type = /obj/item/weapon/stock_parts/cell/potato clumsy_check = 0 //Admin spawn only, might as well let clowns use it. selfcharge = 1 @@ -324,7 +324,7 @@ desc = "A machinegun that fires 3d-printed flachettes slowly regenerated using a cyborg's internal power source." icon_state = "l6closed0" icon = 'icons/obj/guns/projectile.dmi' - cell_type = "/obj/item/weapon/stock_parts/cell/secborg" + cell_type = /obj/item/weapon/stock_parts/cell/secborg ammo_type = list(/obj/item/ammo_casing/energy/c3dbullet) can_charge = 0 @@ -368,6 +368,7 @@ icon_state = "disabler" ammo_type = list(/obj/item/ammo_casing/energy/clown) clumsy_check = 0 + ammo_x_offset = 3 /obj/item/weapon/gun/energy/toxgun name = "plasma pistol" @@ -406,7 +407,7 @@ origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2" ammo_type = list(/obj/item/ammo_casing/energy/temp) - cell_type = "/obj/item/weapon/stock_parts/cell" + cell_type = /obj/item/weapon/stock_parts/cell var/powercost = "" var/powercostcolor = "" @@ -425,11 +426,7 @@ return ..() /obj/item/weapon/gun/energy/temperature/newshot() - ..() - var/obj/item/ammo_casing/energy/temp/T = chambered - if(T) - T.temperature = temperature - T.e_cost = e_cost + ..(temperature, e_cost) /obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) user.set_machine(src) @@ -572,3 +569,16 @@ if(2000 to 3000) overlays += "200" if(1000 to 2002) overlays += "100" if(-INFINITY to 1000) overlays += "0" + +/obj/item/weapon/gun/energy/mimicgun + name = "mimic gun" + desc = "A self-defense weapon that exhausts organic targets, weakening them until they collapse. Why does this one have teeth?" + icon_state = "disabler" + ammo_type = list(/obj/item/ammo_casing/energy/mimic) + clumsy_check = 0 //Admin spawn only, might as well let clowns use it. + selfcharge = 1 + ammo_x_offset = 3 + var/mimic_type = /obj/item/weapon/gun/projectile/automatic/pistol //Setting this to the mimicgun type does exactly what you think it will. + +/obj/item/weapon/gun/energy/mimicgun/newshot() + ..(mimic_type) diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 6fdbe55c171..9728a9442e1 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -5,7 +5,7 @@ item_state = null //so the human update icon uses the icon_state instead. ammo_type = list(/obj/item/ammo_casing/energy/electrode) ammo_x_offset = 3 - cell_type = "/obj/item/weapon/stock_parts/cell/crap" + cell_type = /obj/item/weapon/stock_parts/cell/crap /obj/item/weapon/gun/energy/taser/mounted name = "mounted taser gun" @@ -16,7 +16,7 @@ name = "taser gun" desc = "A small, low capacity gun used for non-lethal takedowns." icon_state = "taser" - cell_type = "/obj/item/weapon/stock_parts/cell/secborg" + cell_type = /obj/item/weapon/stock_parts/cell/secborg /obj/item/weapon/gun/energy/disabler/cyborg/newshot() ..() diff --git a/code/modules/projectiles/guns/energy/telegun.dm b/code/modules/projectiles/guns/energy/telegun.dm index 23dd6455a3e..e8a882d7c80 100644 --- a/code/modules/projectiles/guns/energy/telegun.dm +++ b/code/modules/projectiles/guns/energy/telegun.dm @@ -6,7 +6,7 @@ icon_state = "telegun" item_state = "ionrifle" origin_tech = "combat=6;materials=7;powerstorage=5;bluespace=5;syndicate=4" - cell_type = "/obj/item/weapon/stock_parts/cell/crap" + cell_type = /obj/item/weapon/stock_parts/cell/crap ammo_type = list(/obj/item/ammo_casing/energy/teleport) shaded_charge = 1 var/teleport_target = null @@ -38,6 +38,4 @@ teleport_target = L[desc] /obj/item/weapon/gun/energy/telegun/newshot() - ..() - var/obj/item/ammo_casing/energy/teleport/T = chambered - T.teleport_target = teleport_target + ..(teleport_target) diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index 870ae85bc63..0c7f54bb21a 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -36,9 +36,9 @@ /obj/item/weapon/gun/magic/can_shoot() return charges -/obj/item/weapon/gun/magic/newshot() +/obj/item/weapon/gun/magic/newshot(params) if (charges && chambered) - chambered.newshot() + chambered.newshot(params) return /obj/item/weapon/gun/magic/process_chamber() diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 1d1f6dc93a8..d91fd3898f7 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -12,6 +12,7 @@ icon_state = "pulse1_bl" damage_type = BURN //OXY does not kill IPCs damage = 50000 + nodamage = 0 /obj/item/projectile/magic/fireball name = "bolt of fireball" @@ -254,7 +255,10 @@ proc/wabbajack(mob/living/M) qdel(src) else var/obj/O = change - new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer) + if(istype(O, /obj/item/weapon/gun)) + new /mob/living/simple_animal/hostile/mimic/copy/ranged(O.loc, O, firer) + else + new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer) else if(istype(change, /mob/living/simple_animal/hostile/mimic/copy)) // Change our allegiance! var/mob/living/simple_animal/hostile/mimic/copy/C = change diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 0d0eba709ff..53527ef326e 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -50,42 +50,44 @@ damage_type = BURN nodamage = 1 flag = "energy" - var/temperature = null + var/temperature = 300 pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE -/obj/item/projectile/temp/New() - spawn(1) - switch(temperature) - if(501 to INFINITY) - name = "searing beam" //if emagged - icon_state = "temp_8" - if(400 to 500) - name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2 - icon_state = "temp_7" - if(360 to 400) - name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1 - icon_state = "temp_6" - if(335 to 360) - name = "warm beam" //temp at which players get notified of their high body temp - icon_state = "temp_5" - if(295 to 335) - name = "ambient beam" - icon_state = "temp_4" - if(260 to 295) - name = "cool beam" //temp at which players get notified of their low body temp - icon_state = "temp_3" - if(200 to 260) - name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1 - icon_state = "temp_2" - if(120 to 260) - name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2 - icon_state = "temp_1" - if(-INFINITY to 120) - name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3 - icon_state = "temp_0" - else - name = "temperature beam"//failsafe - icon_state = "temp_4" +/obj/item/projectile/temp/New(loc, shot_temp) + ..(loc) + if(shot_temp) + temperature = shot_temp + switch(temperature) + if(501 to INFINITY) + name = "searing beam" //if emagged + icon_state = "temp_8" + if(400 to 500) + name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2 + icon_state = "temp_7" + if(360 to 400) + name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1 + icon_state = "temp_6" + if(335 to 360) + name = "warm beam" //temp at which players get notified of their high body temp + icon_state = "temp_5" + if(295 to 335) + name = "ambient beam" + icon_state = "temp_4" + if(260 to 295) + name = "cool beam" //temp at which players get notified of their low body temp + icon_state = "temp_3" + if(200 to 260) + name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1 + icon_state = "temp_2" + if(120 to 260) + name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2 + icon_state = "temp_1" + if(-INFINITY to 120) + name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3 + icon_state = "temp_0" + else + name = "temperature beam"//failsafe + icon_state = "temp_4" ..() @@ -342,6 +344,11 @@ obj/item/projectile/kinetic/New() nodamage = 1 var/teleport_target = null +/obj/item/projectile/energy/teleport/New(loc, tele_target) + ..(loc) + if(tele_target) + teleport_target = tele_target + /obj/item/projectile/energy/teleport/on_hit(var/atom/target, var/blocked = 0) if(isliving(target)) if(teleport_target) @@ -382,3 +389,31 @@ obj/item/projectile/kinetic/New() var/throwdir = get_dir(firer,target) T.throw_at(get_edge_target_turf(target, throwdir),10,10) return 1 + +/obj/item/projectile/mimic + name = "googly-eyed gun" + hitsound = 'sound/weapons/genhit1.ogg' + damage = 0 + nodamage = 1 + damage_type = BURN + flag = "melee" + var/obj/item/weapon/gun/stored_gun + +/obj/item/projectile/mimic/New(loc, mimic_type) + ..(loc) + if(mimic_type) + stored_gun = new mimic_type(src) + icon = stored_gun.icon + icon_state = stored_gun.icon_state + overlays = stored_gun.overlays + SpinAnimation(20, -1) + +/obj/item/projectile/mimic/on_hit(atom/target) + ..() + var/turf/T = get_turf(src) + var/obj/item/weapon/gun/G = stored_gun + stored_gun = null + G.forceMove(T) + var/mob/living/simple_animal/hostile/mimic/copy/ranged/R = new /mob/living/simple_animal/hostile/mimic/copy/ranged(T, G, firer) + if(ismob(target)) + R.target = target diff --git a/code/modules/reagents/newchem/drinks.dm b/code/modules/reagents/newchem/drinks.dm index c09b1a06fba..a9912f8722b 100644 --- a/code/modules/reagents/newchem/drinks.dm +++ b/code/modules/reagents/newchem/drinks.dm @@ -36,9 +36,6 @@ id = "applejack" description = "A highly concentrated alcoholic beverage made by repeatedly freezing cider and removing the ice." color = "#997A00" - slur_start = 30 - brawl_start = 40 - confused_start = 100 alcohol_perc = 0.4 /datum/chemical_reaction/applejack @@ -120,14 +117,7 @@ color = "#1BB1FF" process_flags = ORGANIC | SYNTHETIC metabolization_rate = 0.4 - vomit_start = INFINITY // - blur_start = INFINITY // - pass_out = INFINITY //INFINITY, so that IPCs don't puke and stuff - var/spark_start = 50 //amount absorbed after which mob starts sparking - var/collapse_start = 80 //amount absorbed after wich mob starts sparking and collapsing (DOUBLE THE SPARKS, DOUBLE THE FUN) - var/braindamage_start = 250 //amount absorbed after which mob starts taking a small amount of brain damage - - + alcohol_perc = 0.5 /datum/chemical_reaction/synthanol name = "Synthanol" @@ -139,26 +129,7 @@ mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' /datum/reagent/ethanol/synthanol/on_mob_life(var/mob/living/M as mob, var/alien) - - var/d = 0 - // make all the beverages work together - for(var/datum/reagent/ethanol/synthanol/A in holder.reagent_list) - if(isnum(A.current_cycle)) d += A.current_cycle * A.alcohol_perc - - if(M.isSynthetic()) //works normally on synthetics - if(d >= spark_start && prob(25)) - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, M) - s.start() - if(d >= collapse_start && prob(10)) - M.emote("collapse") - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, M) - s.start() - if(d >= braindamage_start && prob(10)) - M.adjustBrainLoss(1) - - else + if(!M.isSynthetic()) holder.remove_reagent(id, 3.6) //gets removed from organics very fast if(prob(25)) holder.remove_reagent(id, 15) @@ -179,7 +150,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "An oily substance that an IPC could technically consider a 'drink'." reagent_state = LIQUID color = "#363636" - alcohol_perc = 0.5 + alcohol_perc = 0.25 /datum/chemical_reaction/synthanol/robottears name = "Robot Tears" @@ -195,7 +166,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "A fruit drink meant only for synthetics, however that works." reagent_state = LIQUID color = "#adb21f" - alcohol_perc = 0.3 + alcohol_perc = 0.2 /datum/chemical_reaction/synthanol/trinary name = "Trinary" @@ -211,7 +182,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "A drink containing some organic ingredients, but meant only for synthetics." reagent_state = LIQUID color = "#5b3210" - alcohol_perc = 0.5 + alcohol_perc = 0.25 /datum/chemical_reaction/synthanol/servo name = "Servo" @@ -227,7 +198,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "A potent mix of alcohol and synthanol. Will only work on synthetics." reagent_state = LIQUID color = "#e7ae04" - alcohol_perc = 0.2 + alcohol_perc = 0.15 /datum/chemical_reaction/synthanol/uplink name = "Uplink" @@ -242,7 +213,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "The classic drink adjusted for a robot's tastes." reagent_state = LIQUID color = "#7204e7" - alcohol_perc = 0.5 + alcohol_perc = 0.25 /datum/chemical_reaction/synthanol/synthnsoda name = "Synth 'n Soda" @@ -257,7 +228,7 @@ datum/reagent/ethanol/synthanol/reaction_mob(var/mob/M, var/method=TOUCH, var/vo description = "Someone mixed wine and alcohol for robots. Hope you're proud of yourself." reagent_state = LIQUID color = "#d004e7" - alcohol_perc = 0.5 + alcohol_perc = 0.25 /datum/chemical_reaction/synthanol/synthignon name = "Synthignon" diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm index 33f04d5e6a8..a1e990ec51e 100644 --- a/code/modules/reagents/newchem/medicine.dm +++ b/code/modules/reagents/newchem/medicine.dm @@ -774,6 +774,7 @@ datum/reagent/antihol datum/reagent/antihol/on_mob_life(var/mob/living/M as mob) M.slurring = 0 + M.AdjustDrunk(-4) M.reagents.remove_all_type(/datum/reagent/ethanol, 8, 0, 1) if(M.toxloss <= 25) M.adjustToxLoss(-2.0) @@ -1059,4 +1060,4 @@ datum/reagent/medicine/syndicate_nanites/on_mob_life(mob/living/M) M.adjustBrainLoss(-15*REM) M.adjustCloneLoss(-3*REM) ..() - return \ No newline at end of file + return diff --git a/code/modules/reagents/newchem/patch.dm b/code/modules/reagents/newchem/patch.dm index a7aae47d8de..793b6f8ae6f 100644 --- a/code/modules/reagents/newchem/patch.dm +++ b/code/modules/reagents/newchem/patch.dm @@ -10,37 +10,42 @@ apply_method = "apply" transfer_efficiency = 0.5 //patches aren't as effective at getting chemicals into the bloodstream. -/obj/item/weapon/reagent_containers/food/pill/patch/New() - ..() - icon_state = "bandaid" - /obj/item/weapon/reagent_containers/food/pill/patch/afterattack(obj/target, mob/user , proximity) return // thanks inheritance again /obj/item/weapon/reagent_containers/food/pill/patch/styptic name = "healing patch" desc = "Helps with brute injuries." - New() - ..() - reagents.add_reagent("styptic_powder", 40) + icon_state = "bandaid_brute" + instant_application = 1 + +/obj/item/weapon/reagent_containers/food/pill/patch/styptic/New() + ..() + reagents.add_reagent("styptic_powder", 40) /obj/item/weapon/reagent_containers/food/pill/patch/silver_sulf name = "burn patch" desc = "Helps with burn injuries." - New() - ..() - reagents.add_reagent("silver_sulfadiazine", 40) + icon_state = "bandaid_burn" + instant_application = 1 + +/obj/item/weapon/reagent_containers/food/pill/patch/silver_sulf/New() + ..() + reagents.add_reagent("silver_sulfadiazine", 40) /obj/item/weapon/reagent_containers/food/pill/patch/synthflesh name = "syntheflesh patch" desc = "Helps with burn injuries." - New() - ..() - reagents.add_reagent("synthflesh", 20) + instant_application = 1 + +/obj/item/weapon/reagent_containers/food/pill/patch/synthflesh/New() + ..() + reagents.add_reagent("synthflesh", 20) /obj/item/weapon/reagent_containers/food/pill/patch/nicotine name = "nicotine patch" desc = "Helps temporarily curb the cravings of nicotine dependency." - New() - ..() - reagents.add_reagent("nicotine", 20) \ No newline at end of file + +/obj/item/weapon/reagent_containers/food/pill/patch/nicotine/New() + ..() + reagents.add_reagent("nicotine", 20) \ No newline at end of file diff --git a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_drink.dm b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_drink.dm index c394af15a4e..10b5ff13344 100644 --- a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_drink.dm +++ b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_drink.dm @@ -156,8 +156,8 @@ name = "Cuba Libre" id = "cubalibre" result = "cubalibre" - required_reagents = list("rum" = 2, "cola" = 1) - result_amount = 3 + required_reagents = list("rum" = 2, "cola" = 2, "limejuice" = 1) + result_amount = 5 mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' /datum/chemical_reaction/mojito @@ -675,4 +675,4 @@ result = "rewriter" required_reagents = list("spacemountainwind" = 1, "coffee" = 1) result_amount = 2 - mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' \ No newline at end of file + mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' diff --git a/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm b/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm index 82d46d60519..a40345ffaac 100644 --- a/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm +++ b/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm @@ -7,64 +7,13 @@ nutriment_factor = 0 //So alcohol can fill you up! If they want to. color = "#404030" // rgb: 64, 64, 48 can_grow_in_plants = 0 //Alcoholic drinks won't be grown in plants (would "water down" random seed chems too much) - var/datum/martial_art/drunk_brawling/F = new var/dizzy_adj = 3 - var/slurr_adj = 3 - var/confused_adj = 2 - var/slur_start = 20 //amount absorbed after which mob starts slurring - var/brawl_start = 25 //amount absorbed after which mob switches to drunken brawling as a fighting style - var/confused_start = 30 //amount absorbed after which mob starts confusing directions - var/vomit_start = 45 //amount absorbed after which mob starts vomitting - var/blur_start = 70 //amount absorbed after which mob starts getting blurred vision - var/pass_out = 90 //amount absorbed after which mob starts passing out var/alcohol_perc = 1 //percentage of ethanol in a beverage 0.0 - 1.0 /datum/reagent/ethanol/on_mob_life(var/mob/living/M as mob, var/alien) - // Sobering multiplier. - // Sober block makes it more difficult to get drunk - var/sober_str=!(SOBER in M.mutations)?1:2 M.nutrition += nutriment_factor - - var/d = 0 - // make all the beverages work together - for(var/datum/reagent/ethanol/A in holder.reagent_list) - if(isnum(A.current_cycle)) d += A.current_cycle * A.alcohol_perc - - d/=sober_str - - var/obj/item/organ/internal/liver/L - if(ishuman(M) && !M.isSynthetic()) - var/mob/living/carbon/human/H = M - L = H.get_int_organ(/obj/item/organ/internal/liver) - d *= L ? L.alcohol_intensity : 5 - - M.dizziness += dizzy_adj. - if(d >= slur_start && d < pass_out) - if (!M.slurring) M.slurring = 1 - M.slurring += slurr_adj/sober_str - if(d >= brawl_start && ishuman(M)) - var/mob/living/carbon/human/H = M - F.teach(H,1) - if(src.volume < 3) - if(H.martial_art == F) - F.remove(H) - if(d >= confused_start && prob(33)) - if (!M.confused) M.confused = 1 - M.confused = max(M.confused+(confused_adj/sober_str),0) - if(d >= blur_start) - M.eye_blurry = max(M.eye_blurry, 10/sober_str) - M.drowsyness = max(M.drowsyness, 0) - if(d >= vomit_start) - if(prob(8)) - M.fakevomit() - if(d >= pass_out) - M.Paralyse(20 / sober_str) - M.drowsyness = max(M.drowsyness, 30/sober_str) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if (L) - L.take_damage(0.1, 1) - H.adjustToxLoss(0.1) + M.AdjustDrunk(alcohol_perc) + M.dizziness += dizzy_adj ..() return @@ -97,7 +46,7 @@ description = "An alcoholic beverage made from malted grains, hops, yeast, and water." nutriment_factor = 2 * FOOD_METABOLISM color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/beer/on_mob_life(var/mob/living/M as mob) ..() @@ -109,7 +58,7 @@ id = "cider" description = "An alcoholic beverage derived from apples." color = "#174116" - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/whiskey name = "Whiskey" @@ -174,7 +123,7 @@ id = "mojito" description = "If it's good enough for Spesscuba, it's good enough for you." color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/vodka name = "Vodka" @@ -226,8 +175,6 @@ description = "An unbelievably strong and potent variety of Cider." color = "#CF3811" dizzy_adj = 20 - slurr_adj = 20 - confused_adj = 3 alcohol_perc = 1 //because that's a thing it's supposed to do, I guess /datum/reagent/ethanol/ale @@ -265,7 +212,7 @@ description = "This appears to be beer mixed with milk. Disgusting." reagent_state = LIQUID color = "#895C4C" // rgb: 137, 92, 76 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/atomicbomb name = "Atomic Bomb" @@ -429,7 +376,7 @@ description = "Beer and Ale, brought together in a delicious mix. Intended for true men only." reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/longislandicedtea name = "Long Island Iced Tea" @@ -517,7 +464,7 @@ description = "Barefoot and pregnant" reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/snowwhite name = "Snow White" @@ -525,7 +472,7 @@ description = "A cold refreshment" reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/demonsblood name = "Demons Blood" @@ -534,7 +481,6 @@ reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 dizzy_adj = 10 - slurr_adj = 10 alcohol_perc = 0.4 /datum/reagent/ethanol/vodkatonic @@ -544,7 +490,6 @@ reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 dizzy_adj = 4 - slurr_adj = 3 alcohol_perc = 0.3 /datum/reagent/ethanol/ginfizz @@ -554,7 +499,6 @@ reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 dizzy_adj = 4 - slurr_adj = 3 alcohol_perc = 0.4 /datum/reagent/ethanol/bahama_mama @@ -563,7 +507,7 @@ description = "Tropic cocktail." reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/singulo name = "Singulo" @@ -572,7 +516,6 @@ reagent_state = LIQUID color = "#2E6671" // rgb: 46, 102, 113 dizzy_adj = 15 - slurr_adj = 15 alcohol_perc = 0.7 /datum/reagent/ethanol/sbiten @@ -603,7 +546,7 @@ description = "The true Viking drink! Even though it has a strange red color." reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/mead name = "Mead" @@ -611,7 +554,7 @@ description = "A Vikings drink, though a cheap one." reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/iced_beer name = "Iced Beer" @@ -619,7 +562,7 @@ description = "A beer which is so cold the air around it freezes." reagent_state = LIQUID color = "#664300" // rgb: 102, 67, 0 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/iced_beer/on_mob_life(var/mob/living/M as mob) ..() @@ -685,16 +628,10 @@ /datum/reagent/ethanol/neurotoxin/on_mob_life(var/mob/living/M as mob) M.weakened = max(M.weakened, 3) - M.dizziness +=6 - if(current_cycle >= 15 && current_cycle <45) - if (!M.slurring) - M.slurring = 1 - M.slurring += 3 - else if(current_cycle >= 45 && prob(50) && current_cycle <55) - M.confused = max(M.confused+3,0) - else if(current_cycle >=55) + dizzy_adj = 6 + if(current_cycle >=55) M.druggy = max(M.druggy, 55) - else if(current_cycle >=200) + if(current_cycle >=200) M.adjustToxLoss(2) ..() return @@ -739,7 +676,7 @@ description = "The surprise is, it's green!" reagent_state = LIQUID color = "#2E6671" // rgb: 46, 102, 113 - alcohol_perc = 0.1 + alcohol_perc = 0.2 /datum/reagent/ethanol/driestmartini name = "Driest Martini" @@ -754,8 +691,6 @@ if(current_cycle >= 55 && current_cycle <115) if (!M.stuttering) M.stuttering = 1 M.stuttering += 10 - else if(current_cycle >= 115 && prob(33)) - M.confused = max(M.confused+15,15) ..() return diff --git a/code/modules/reagents/reagent_containers/food.dm b/code/modules/reagents/reagent_containers/food.dm index 8caaa5ff653..50a3ecd1a1d 100644 --- a/code/modules/reagents/reagent_containers/food.dm +++ b/code/modules/reagents/reagent_containers/food.dm @@ -10,6 +10,7 @@ var/apply_type = INGEST var/apply_method = "swallow" var/transfer_efficiency = 1.0 + var/instant_application = 0 //if we want to bypass the forcedfeed delay /obj/item/weapon/reagent_containers/food/New() ..() diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index e1fb06f1be7..2b53bfb2e6d 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -183,6 +183,15 @@ ..() reagents.add_reagent("sodiumchloride", 20) +/obj/item/weapon/reagent_containers/food/condiment/saltshaker/suicide_act(mob/user) + user.visible_message("[user] begins to swap forms with the salt shaker! It looks like \he's trying to commit suicide.") + var/newname = "[name]" + name = "[user.name]" + user.name = newname + user.real_name = newname + desc = "Salt. From dead crew, presumably." + return TOXLOSS + /obj/item/weapon/reagent_containers/food/condiment/peppermill name = "pepper mill" desc = "Often used to flavor food or make people sneeze." diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 332375dae8d..610abd27950 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -248,6 +248,12 @@ else trans = src.reagents.trans_to(target, amount_per_transfer_from_this) to_chat(user, "\blue You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.") + if(istype(target, /obj/item/weapon/reagent_containers/food/pill/patch)) + var/obj/item/weapon/reagent_containers/food/pill/patch/P = target + if(P.instant_application) + to_chat(user, "You break the medical seal on the [P]!") + P.instant_application = 0 + if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT) mode = SYRINGE_DRAW update_icon() diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 89a73e31715..06dbba8d62e 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -49,6 +49,7 @@ other types of metals and chemistry for reagents). var/category = null //Primarily used for Mech Fabricators, but can be used for anything var/list/reagents = list() //List of reagents. Format: "id" = amount. var/maxstack = 1 + var/lathe_time_factor = 1 //How many times faster than normal is this to build on the protolathe //A proc to calculate the reliability of a design based on tech levels and innate modifiers. //Input: A list of /datum/tech; Output: The new reliabilty. diff --git a/code/modules/research/designs/stock_parts_designs.dm b/code/modules/research/designs/stock_parts_designs.dm index 81182661384..a1be7ffcf7a 100644 --- a/code/modules/research/designs/stock_parts_designs.dm +++ b/code/modules/research/designs/stock_parts_designs.dm @@ -11,6 +11,7 @@ materials = list(MAT_METAL = 50, MAT_GLASS = 50) build_path = /obj/item/weapon/stock_parts/capacitor category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/basic_sensor name = "Basic Scanning Module" @@ -21,6 +22,7 @@ materials = list(MAT_METAL = 50, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/scanning_module category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/micro_mani name = "Micro Manipulator" @@ -31,6 +33,7 @@ materials = list(MAT_METAL = 30) build_path = /obj/item/weapon/stock_parts/manipulator category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/basic_micro_laser name = "Basic Micro-Laser" @@ -41,6 +44,7 @@ materials = list(MAT_METAL = 10, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/micro_laser category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/basic_matter_bin name = "Basic Matter Bin" @@ -51,6 +55,7 @@ materials = list(MAT_METAL = 80) build_path = /obj/item/weapon/stock_parts/matter_bin category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/adv_capacitor name = "Advanced Capacitor" @@ -61,6 +66,7 @@ materials = list(MAT_METAL = 50, MAT_GLASS = 50) build_path = /obj/item/weapon/stock_parts/capacitor/adv category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/adv_sensor name = "Advanced Scanning Module" @@ -71,6 +77,7 @@ materials = list(MAT_METAL = 50, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/scanning_module/adv category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/nano_mani name = "Nano Manipulator" @@ -81,6 +88,7 @@ materials = list(MAT_METAL = 30) build_path = /obj/item/weapon/stock_parts/manipulator/nano category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/high_micro_laser name = "High-Power Micro-Laser" @@ -91,6 +99,7 @@ materials = list(MAT_METAL = 10, MAT_GLASS = 20) build_path = /obj/item/weapon/stock_parts/micro_laser/high category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/adv_matter_bin name = "Advanced Matter Bin" @@ -101,6 +110,7 @@ materials = list(MAT_METAL = 80) build_path = /obj/item/weapon/stock_parts/matter_bin/adv category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/super_capacitor name = "Super Capacitor" @@ -112,6 +122,7 @@ materials = list(MAT_METAL = 50, MAT_GLASS = 50, MAT_GOLD = 20) build_path = /obj/item/weapon/stock_parts/capacitor/super category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/phasic_sensor name = "Phasic Scanning Module" @@ -123,6 +134,7 @@ reliability = 72 build_path = /obj/item/weapon/stock_parts/scanning_module/phasic category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/pico_mani name = "Pico Manipulator" @@ -134,6 +146,7 @@ reliability = 73 build_path = /obj/item/weapon/stock_parts/manipulator/pico category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/ultra_micro_laser name = "Ultra-High-Power Micro-Laser" @@ -145,6 +158,7 @@ reliability = 70 build_path = /obj/item/weapon/stock_parts/micro_laser/ultra category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/super_matter_bin name = "Super Matter Bin" @@ -156,6 +170,7 @@ reliability = 75 build_path = /obj/item/weapon/stock_parts/matter_bin/super category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/quadratic_capacitor name = "Quadratic Capacitor" @@ -167,6 +182,7 @@ materials = list(MAT_METAL = 100, MAT_GLASS = 100, MAT_DIAMOND = 40) build_path = /obj/item/weapon/stock_parts/capacitor/quadratic category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/triphasic_scanning name = "Triphasic Scanning Module" @@ -178,6 +194,7 @@ reliability = 72 build_path = /obj/item/weapon/stock_parts/scanning_module/triphasic category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/femto_mani name = "Femto Manipulator" @@ -189,6 +206,7 @@ reliability = 73 build_path = /obj/item/weapon/stock_parts/manipulator/femto category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/quadultra_micro_laser name = "Quad-Ultra Micro-Laser" @@ -200,6 +218,7 @@ reliability = 70 build_path = /obj/item/weapon/stock_parts/micro_laser/quadultra category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/bluespace_matter_bin name = "Bluespace Matter Bin" @@ -211,6 +230,7 @@ reliability = 75 build_path = /obj/item/weapon/stock_parts/matter_bin/bluespace category = list("Stock Parts") + lathe_time_factor = 5 /datum/design/RPED name = "Rapid Part Exchange Device" @@ -240,4 +260,5 @@ build_type = PROTOLATHE materials = list(MAT_METAL = 4000, MAT_PLASMA = 4000) build_path = /obj/item/stack/sheet/mineral/abductor - category = list("Stock Parts") \ No newline at end of file + category = list("Stock Parts") + lathe_time_factor = 5 \ No newline at end of file diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 64ad0c962fc..f44e96ae78b 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -128,7 +128,7 @@ //WT550 Mags /datum/design/mag_oldsmg - name = "WT-550 Auto Gun Magazine (4.6×30mm)" + name = "WT-550 Auto Gun Magazine (4.6x30mm)" desc = "A 20 round magazine for the out of date security WT-550 Auto Rifle" id = "mag_oldsmg" req_tech = list("combat" = 1, "materials" = 1) @@ -138,21 +138,21 @@ category = list("Weapons") /datum/design/mag_oldsmg/ap_mag - name = "WT-550 Auto Gun Armour Piercing Magazine (4.6×30mm AP)" + name = "WT-550 Auto Gun Armour Piercing Magazine (4.6x30mm AP)" desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle" id = "mag_oldsmg_ap" materials = list(MAT_METAL = 6000, MAT_SILVER = 600) build_path = /obj/item/ammo_box/magazine/wt550m9/wtap /datum/design/mag_oldsmg/ic_mag - name = "WT-550 Auto Gun Incendiary Magazine (4.6×30mm IC)" + name = "WT-550 Auto Gun Incendiary Magazine (4.6x30mm IC)" desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle" id = "mag_oldsmg_ic" materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_GLASS = 1000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtic /datum/design/mag_oldsmg/tx_mag - name = "WT-550 Auto Gun Urnaium Magazine (4.6×30mm TX)" + name = "WT-550 Auto Gun Urnaium Magazine (4.6x30mm TX)" desc = "A 20 round urnaium tipped magazine for the out of date security WT-550 Auto Rifle" id = "mag_oldsmg_tx" materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_URANIUM = 2000) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 3c8b89ea2a0..cff54b3bd32 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -41,7 +41,7 @@ Note: Must be placed west/left of and R&D console to function. component_parts += new /obj/item/weapon/stock_parts/manipulator(null) component_parts += new /obj/item/weapon/reagent_containers/glass/beaker/large(null) component_parts += new /obj/item/weapon/reagent_containers/glass/beaker/large(null) - materials = new(src, list(MAT_METAL=1, MAT_GLASS=1, MAT_SILVER=1, MAT_GOLD=1, MAT_DIAMOND=1, MAT_PLASMA=1, MAT_URANIUM=1, MAT_BANANIUM=1)) + materials = new(src, list(MAT_METAL=1, MAT_GLASS=1, MAT_SILVER=1, MAT_GOLD=1, MAT_DIAMOND=1, MAT_PLASMA=1, MAT_URANIUM=1, MAT_BANANIUM=1, MAT_TRANQUILLITE=1)) RefreshParts() reagents.my_atom = src diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 9e8b29f94c1..2fdb61a706f 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -46,6 +46,11 @@ won't update every console in existence) but it's more of a hassle to do. Also, var/obj/machinery/r_n_d/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter var/screen = 1.0 //Which screen is currently showing. + + var/menu = 0 // Current menu. + var/submenu = 0 + var/wait_message = 0 + var/id = 0 //ID of the computer (for server restrictions). var/sync = 1 //If sync = 0, it doesn't show up on Server Control Console @@ -173,7 +178,7 @@ proc/CallMaterialName(ID) to_chat(user, "You add the disk to the machine!") else if(!(linked_destroy && linked_destroy.busy) && !(linked_lathe && linked_lathe.busy) && !(linked_imprinter && linked_imprinter.busy)) ..() - src.updateUsrDialog() + nanomanager.update_uis(src) return /obj/machinery/computer/rdconsole/emag_act(user as mob) @@ -195,17 +200,36 @@ proc/CallMaterialName(ID) usr.set_machine(src) if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. var/temp_screen = text2num(href_list["menu"]) - screen = temp_screen + menu = temp_screen + if(href_list["submenu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. + var/temp_screen = text2num(href_list["submenu"]) + submenu = temp_screen if(href_list["category"]) - selected_category = href_list["category"] + var/compare + + matching_designs.Cut() + + if(menu == 4) + compare = PROTOLATHE + else + compare = IMPRINTER + + for(var/datum/design/D in files.known_designs) + if(!(D.build_type & compare)) + continue + if(href_list["category"] in D.category) + matching_designs.Add(D) + submenu = 1 + + selected_category = "Viewing Category [href_list["category"]]" else if(href_list["updt_tech"]) //Update the research holder with information from the technology disk. - screen = 0.0 + wait_message = "Updating Database...." spawn(50) - screen = 1.2 + wait_message = 0 files.AddTech2Known(t_disk.stored) - updateUsrDialog() + nanomanager.update_uis(src) griefProtection() //Update centcom too else if(href_list["clear_tech"]) //Erase data on the technology disk. @@ -216,21 +240,23 @@ proc/CallMaterialName(ID) if(t_disk) t_disk.loc = src.loc t_disk = null - screen = 1.0 + menu = 0 + submenu = 0 else if(href_list["copy_tech"]) //Copy some technology data from the research holder to the disk. for(var/datum/tech/T in files.known_tech) if(href_list["copy_tech_ID"] == T.id) t_disk.stored = T break - screen = 1.2 + menu = 2 + submenu = 0 else if(href_list["updt_design"]) //Updates the research holder with design data from the design disk. - screen = 0.0 + wait_message = "Updating Database...." spawn(50) - screen = 1.4 + wait_message = 0 files.AddDesign2Known(d_disk.blueprint) - updateUsrDialog() + nanomanager.update_uis(src) griefProtection() //Update centcom too else if(href_list["clear_design"]) //Erases data on the design disk. @@ -241,7 +267,8 @@ proc/CallMaterialName(ID) if(d_disk) d_disk.loc = src.loc d_disk = null - screen = 1.0 + menu = 0 + submenu = 0 else if(href_list["copy_design"]) //Copy design data from the research holder to the design disk. for(var/datum/design/D in files.known_designs) @@ -259,7 +286,8 @@ proc/CallMaterialName(ID) D.category |= "Imported" d_disk.blueprint = D break - screen = 1.4 + menu = 2 + submenu = 0 else if(href_list["eject_item"]) //Eject the item inside the destructive analyzer. if(linked_destroy) @@ -270,20 +298,20 @@ proc/CallMaterialName(ID) linked_destroy.loaded_item.loc = linked_destroy.loc linked_destroy.loaded_item = null linked_destroy.icon_state = "d_analyzer" - screen = 2.1 + menu = 3 else if(href_list["maxresearch"]) //Eject the item inside the destructive analyzer. if(!check_rights(R_ADMIN)) return - screen = 0.0 + wait_message = "Updating Database...." if(alert("Are you sure you want to maximize research levels?","Confirmation","Yes","No")=="No") return log_admin("[key_name(usr)] has maximized the research levels.") message_admins("[key_name_admin(usr)] has maximized the research levels.") spawn(30) Maximize() - screen = 1.0 - updateUsrDialog() + wait_message = "" + nanomanager.update_uis(src) griefProtection() //Update centcomm too else if(href_list["deconstruct"]) //Deconstruct the item in the destructive analyzer and update the research holder. @@ -294,8 +322,8 @@ proc/CallMaterialName(ID) var/choice = input("Proceeding will destroy loaded item.") in list("Proceed", "Cancel") if(choice == "Cancel" || !linked_destroy) return linked_destroy.busy = 1 - screen = 0.1 - updateUsrDialog() + wait_message = "Processing and Updating Database..." + nanomanager.update_uis(src) flick("d_analyzer_process", linked_destroy) spawn(24) if(linked_destroy) @@ -303,7 +331,9 @@ proc/CallMaterialName(ID) if(!linked_destroy.hacked) if(!linked_destroy.loaded_item) to_chat(usr, "The destructive analyzer appears to be empty.") - screen = 1.0 + wait_message = 0 + menu = 0 + submenu = 0 return if((linked_destroy.loaded_item.reliability >= 99 - (linked_destroy.decon_mod * 3)) || linked_destroy.loaded_item.crit_fail) var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) @@ -311,15 +341,21 @@ proc/CallMaterialName(ID) if(prob(linked_destroy.loaded_item.reliability)) //If deconstructed item is not reliable enough its just being wasted, else it is pocessed files.UpdateTech(T, temp_tech[T]) //Check if deconstructed item has research levels higher/same/one less than current ones files.UpdateDesigns(linked_destroy.loaded_item, temp_tech, src) //If if such reseach type found all the known designs are checked for having this research type in them - screen = 1.0 //If design have it it gains some reliability + wait_message = 0 //If design have it it gains some reliability + menu = 0 + submenu = 0 else //Same design always gain quality - screen = 2.3 //Crit fail gives the same design a lot of reliability, like really a lot + wait_message = 0 //Crit fail gives the same design a lot of reliability, like really a lot + menu = 2 + submenu = 0 if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any. for(var/material in linked_destroy.loaded_item.materials) linked_lathe.materials.insert_amount(min((linked_lathe.materials.max_amount - linked_lathe.materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material) linked_destroy.loaded_item = null else - screen = 1.0 + wait_message = 0 + menu = 0 + submenu = 0 for(var/obj/I in linked_destroy.contents) for(var/mob/M in I.contents) M.death() @@ -336,10 +372,10 @@ proc/CallMaterialName(ID) qdel(I) linked_destroy.icon_state = "d_analyzer" use_power(250) - updateUsrDialog() + nanomanager.update_uis(src) else if(href_list["sync"]) //Sync the research holder with all the R&D consoles in the game that aren't sync protected. - screen = 0.0 + wait_message = "Updating Database...." if(!sync) to_chat(usr, "You must connect to the network first!") else @@ -366,8 +402,8 @@ proc/CallMaterialName(ID) server_processed = 1 if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed) S.produce_heat(100) - screen = 1.6 - updateUsrDialog() + wait_message = 0 + nanomanager.update_uis(src) else if(href_list["togglesync"]) //Prevents the console from being synced by other consoles. Can still send data. sync = !sync @@ -388,12 +424,11 @@ proc/CallMaterialName(ID) if(being_built) var/power = 2000 var/amount=text2num(href_list["amount"]) - var/old_screen = screen amount = max(1, min(10, amount)) for(var/M in being_built.materials) power += round(being_built.materials[M] * amount / 5) power = max(2000, power) - screen = 0.3 + wait_message = "Constructing Prototype. Please Wait..." if(linked_lathe.busy) g2g = 0 var/key = usr.key //so we don't lose the info during the spawn delay @@ -431,6 +466,9 @@ proc/CallMaterialName(ID) var/P = being_built.build_path //lets save these values before the spawn() just in case. Nobody likes runtimes. var/O = being_built.locked + + coeff *= being_built.lathe_time_factor + spawn(32*amount/coeff) if(g2g) //And if we only fail the material requirements, we still spend time and power for(var/i = 0, iAccess denied.") return 1 - interact(user) - -/obj/machinery/computer/rdconsole/interact(mob/user) + ui_interact(user) +/obj/machinery/computer/rdconsole/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) - var/dat = "" + var/data = list() + files.RefreshResearch() - switch(screen) //A quick check to make sure you get the right screen when a device is disconnected. - if(2 to 2.9) - if(screen == 2.3) - ; - else if(linked_destroy == null) - screen = 2.0 - else if(linked_destroy.loaded_item == null) - screen = 2.1 - else - screen = 2.2 - if(3 to 3.9) - if(linked_lathe == null) - screen = 3.0 - if(4 to 4.9) - if(linked_imprinter == null) - screen = 4.0 - - switch(screen) - - //////////////////////R&D CONSOLE SCREENS////////////////// - if(0.0) dat += "
Updating Database....
" - - if(0.1) dat += "
Processing and Updating Database...
" - - if(0.3) - dat += "
Constructing Prototype. Please Wait...
" - - if(0.4) - dat += "
Imprinting Circuit. Please Wait...
" - - if(1.0) //Main Menu - dat += "
" - dat += "

Main Menu:


" - dat += "Current Research Levels
" - if(t_disk) - dat += "Disk Operations
" - else if(d_disk) - dat += "Disk Operations
" - else - dat += "Disk Operations
" - if(linked_destroy) - dat += "Destructive Analyzer Menu
" - else - dat += "Destructive Analyzer Menu
" - if(linked_lathe) - dat += "Protolathe Construction Menu
" - else - dat += "Protolathe Construction Menu
" - if(linked_imprinter) - dat += "Circuit Construction Menu
" - else - dat += "Circuit Construction Menu
" - dat += "Settings" - dat += "
" - - if(1.1) //Research viewer - dat += "Main Menu" - dat += "

Current Research Levels:


" + + data["menu"] = menu + data["submenu"] = submenu + data["wait_message"] = wait_message + data["src_ref"] = "\ref[src]" + + data["linked_destroy"] = linked_destroy ? 1 : 0 + data["linked_lathe"] = linked_lathe ? 1 : 0 + data["linked_imprinter"] = linked_imprinter ? 1 : 0 + data["sync"] = sync + data["admin"] = check_rights(R_ADMIN,0) + data["disk_type"] = d_disk ? 2 : (t_disk ? 1 : 0) + data["category"] = selected_category + + if(menu == 1) + var/list/tech_levels = list() + data["tech_levels"] = tech_levels + for(var/datum/tech/T in files.known_tech) + if(T.level <= 0) + continue + var/list/this_tech_list = list() + this_tech_list["name"] = T.name + this_tech_list["level"] = T.level + this_tech_list["desc"] = T.desc + tech_levels[++tech_levels.len] = this_tech_list + + if(menu == 2) + + if(t_disk != null && t_disk.stored != null && submenu == 0) //Technology Disk Menu + var/list/disk_data = list() + data["disk_data"] = disk_data + disk_data["name"] = t_disk.stored.name + disk_data["level"] = t_disk.stored.level + disk_data["desc"] = t_disk.stored.desc + + if(t_disk != null && submenu == 1) + var/list/to_copy = list() + data["to_copy"] = to_copy for(var/datum/tech/T in files.known_tech) + var/list/item = list() + to_copy[++to_copy.len] = item if(T.level <= 0) continue - dat += "[T.name]
" - dat += "* Level: [T.level]
" - dat += "* Summary: [T.desc]
" - dat += "
" - - if(1.2) //Technology Disk Menu - - dat += "Main Menu
" - dat += "
Technology Data Disk Contents:

" - if(t_disk.stored == null) - dat += "The disk has no data stored on it.
" - dat += "Operations: " - dat += "Load Tech to Disk" - else - dat += "Name: [t_disk.stored.name]
" - dat += "Level: [t_disk.stored.level]
" - dat += "Description: [t_disk.stored.desc]" - dat += "Operations: " - dat += "Upload to Database" - dat += "Clear Disk" - dat += "Eject Disk" - - if(1.3) //Technology Disk submenu - dat += "Main Menu" - dat += "Return to Disk Operations
" - dat += "

Load Technology to Disk:


" - for(var/datum/tech/T in files.known_tech) - if(T.level <= 0) - continue - dat += "[T.name] " - dat += "Copy to Disk
" - dat += "
" - - if(1.4) //Design Disk menu. - dat += "Main Menu
" - if(d_disk.blueprint == null) - dat += "The disk has no data stored on it.
" - dat += "Operations: " - dat += "Load Design to Disk" - else - dat += "Name: [d_disk.blueprint.name]
" - dat += "Level: [d_disk.blueprint.reliability]
" - var/b_type = d_disk.blueprint.build_type - if(b_type) - dat += "Lathe Types:
" - if(b_type & IMPRINTER) dat += "Circuit Imprinter
" - if(b_type & PROTOLATHE) dat += "Proto-lathe
" - if(b_type & AUTOLATHE) dat += "Auto-lathe
" - if(b_type & MECHFAB) dat += "Mech Fabricator
" - dat += "Required Materials:
" - for(var/M in d_disk.blueprint.materials) - if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]
" - else dat += "* [M] x [d_disk.blueprint.materials[M]]
" - dat += "Operations: " - dat += "Upload to Database" - dat += "Clear Disk" - dat += "Eject Disk" - - if(1.5) //Technology disk submenu - dat += "Main Menu" - dat += "Return to Disk Operations
" - dat += "

Load Design to Disk:


" + item["name"] = T.name + item["id"] = T.id + + if(d_disk != null && d_disk.blueprint != null && submenu == 0) + var/list/disk_data = list() + data["disk_data"] = disk_data + disk_data["name"] = d_disk.blueprint.name + disk_data["reliability"] = d_disk.blueprint.reliability + var/b_type = d_disk.blueprint.build_type + var/list/lathe_types = list() + disk_data["lathe_types"] = lathe_types + if(b_type) + if(b_type & IMPRINTER) lathe_types += "Circuit Imprinter" + if(b_type & PROTOLATHE) lathe_types += "Protolathe" + if(b_type & AUTOLATHE) lathe_types += "Autolathe" + if(b_type & MECHFAB) lathe_types += "Mech Fabricator" + if(b_type & PODFAB) lathe_types += "Spacepod Fabricator" + var/list/materials = list() + disk_data["materials"] = materials + for(var/M in d_disk.blueprint.materials) + var/list/material = list() + materials[++materials.len] = material + material["name"] = CallMaterialName(M) + material["amount"] = d_disk.blueprint.materials[M] + + if(d_disk != null && submenu == 1) + var/list/to_copy = list() + data["to_copy"] = to_copy for(var/datum/design/D in files.known_designs) - dat += "[D.name] " - dat += "Copy to Disk
" - dat += "
" - - if(1.6) //R&D console settings - dat += "Main Menu
" - dat += "

R&D Console Setting:


" - if(sync) - dat += "Sync Database with Network
" - dat += "Connect to Research Network
" - dat += "Disconnect from Research Network
" - else - dat += "Sync Database with Network
" - dat += "Connect to Research Network
" - dat += "Disconnect from Research Network
" - dat += "Device Linkage Menu
" - if(check_rights(R_ADMIN,0)) - dat += "\[ADMIN\] Maximize Research Levels
" - dat += "Reset R&D Database
" - - if(1.7) //R&D device linkage - dat += "Main Menu" - dat += "Settings Menu
" - dat += "

R&D Console Device Linkage Menu:


" - dat += "Re-sync with Nearby Devices

" - dat += "

Linked Devices:


" - if(linked_destroy) - dat += "* Destructive Analyzer Disconnect
" - else - dat += "* No Destructive Analyzer Linked
" - if(linked_lathe) - dat += "* Protolathe Disconnect
" - else - dat += "* No Protolathe Linked
" - if(linked_imprinter) - dat += "* Circuit Imprinter Disconnect
" - else - dat += "* No Circuit Imprinter Linked
" - dat += "
" - - ////////////////////DESTRUCTIVE ANALYZER SCREENS//////////////////////////// - if(2.0) - dat += "Main Menu" - dat += "
NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE
" - - if(2.1) - dat += "Main Menu" - dat += "
No Item Loaded. Standing-by...
" - - if(2.2) - dat += "Main Menu
" - dat += "

Deconstruction Menu


" - dat += "Name: [linked_destroy.loaded_item.name]
" - dat += "Reliability: [linked_destroy.loaded_item.reliability]
" - dat += "Origin Tech:
" - var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) - for(var/T in temp_tech) - dat += "* [CallTechName(T)] [temp_tech[T]]" - for(var/datum/tech/F in files.known_tech) - if(F.name == CallTechName(T)) - dat += " (Current: [F.level])" - break - dat += "
" - dat += "
Options: " - dat += "Deconstruct Item" - dat += "Eject Item" - if(2.3) - dat += "Main Menu" - dat += "
Item is neither reliable enough or broken enough to learn from.
" - - /////////////////////PROTOLATHE SCREENS///////////////////////// - if(3.0) - dat += "Main Menu
" - dat += "
NO PROTOLATHE LINKED TO CONSOLE
" - - if(3.1) - dat += "Main Menu " - dat += "Material Storage" - dat += "Chemical Storage
" - dat += "

Protolathe Menu:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" - dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" - - dat += "
\ - \ - \ - \ - \ - \ -

" - - dat += list_categories(linked_lathe.categories, 3.15) - - //Grouping designs by categories, to improve readability - if(3.15) - dat += "Main Menu" - dat += "Protolathe Menu" - dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" - dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" - - for(var/datum/design/D in files.known_designs) - if(!(selected_category in D.category)|| !(D.build_type & PROTOLATHE)) - continue - var/temp_material - var/c = 50 - var/t - for(var/M in D.materials) - t = linked_lathe.check_mat(D, M) - temp_material += " | " - if (t < 1) - temp_material += "[D.materials[M]] [CallMaterialName(M)]" - else - temp_material += " [D.materials[M]] [CallMaterialName(M)]" - c = min(c,t) - - - for(var/R in D.reagents) - t = linked_lathe.check_mat(D, R) - temp_material += " | " - if (t < 1) - temp_material += "[D.reagents[R]] [CallMaterialName(R)]" - else - temp_material += " [D.reagents[R]] [CallMaterialName(R)]" - c = min(c,t) - - if (c >= 1) - dat += "[D.name]" - if(c >= 5) - dat += "x5" - if(c >= 10) - dat += "x10" - dat += "[temp_material]" - else - dat += "[D.name][temp_material]" - if(D.locked) - dat += " | LOCKED" - dat += "
" - dat += "
" - - if(3.17) //Display search result - dat += "Main Menu" - dat += "Protolathe Menu" - dat += "

Search results:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" - dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" + var/list/item = list() + to_copy[++to_copy.len] = item + item["name"] = D.name + item["id"] = D.id + if(menu == 3 && linked_destroy && linked_destroy.loaded_item) + var/list/loaded_item_list = list() + data["loaded_item"] = loaded_item_list + loaded_item_list["name"] = linked_destroy.loaded_item.name + loaded_item_list["reliability"] = linked_destroy.loaded_item.reliability + var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) + var/list/tech_list = list() + loaded_item_list["origin_tech"] = tech_list + for(var/T in temp_tech) + var/list/tech_item = list() + tech_list[++tech_list.len] = tech_item + tech_item["name"] = CallTechName(T) + tech_item["object_level"] = temp_tech[T] + for(var/datum/tech/F in files.known_tech) + if(F.name == CallTechName(T)) + tech_item["current_level"] = F.level + break + + if(menu == 4 && linked_lathe) + data["total_materials"] = linked_lathe.materials.total_amount + data["max_materials"] = linked_lathe.materials.max_amount + data["total_chemicals"] = linked_lathe.reagents.total_volume + data["max_chemicals"] = linked_lathe.reagents.maximum_volume + data["categories"] = linked_lathe.categories + if(submenu == 1) + var/list/designs_list = list() + data["matching_designs"] = designs_list for(var/datum/design/D in matching_designs) - var/temp_material + var/list/design_list = list() + designs_list[++designs_list.len] = design_list + var/list/materials_list = list() + design_list["materials"] = materials_list + design_list["id"] = D.id + design_list["name"] = sanitize(D.name) var/c = 50 - var/t for(var/M in D.materials) - t = linked_lathe.check_mat(D, M) - temp_material += " | " - if (t < 1) - temp_material += "[D.materials[M]] [CallMaterialName(M)]" + var/list/material_list = list() + materials_list[++materials_list.len] = material_list + material_list["name"] = CallMaterialName(M) + material_list["amount"] = D.materials[M] + var/t = linked_lathe.check_mat(D, M) + + if(t < 1) + material_list["is_red"] = 1 else - temp_material += " [D.materials[M]] [CallMaterialName(M)]" - c = min(c,t) + material_list["is_red"] = 0 + c = min(c, t) for(var/R in D.reagents) - t = linked_lathe.check_mat(D, R) - temp_material += " | " - if (t < 1) - temp_material += "[D.reagents[R]] [CallMaterialName(R)]" + var/list/material_list = list() + materials_list[++materials_list.len] = material_list + material_list["name"] = CallMaterialName(R) + material_list["amount"] = D.reagents[R] + var/t = linked_lathe.check_mat(D, R) + + if(t < 1) + material_list["is_red"] = 1 else - temp_material += " [D.reagents[R]] [CallMaterialName(R)]" - c = min(c,t) - - if (c >= 1) - dat += "[D.name]" - if(c >= 5) - dat += "x5" - if(c >= 10) - dat += "x10" - dat += "[temp_material]" - else - dat += "[D.name][temp_material]" - dat += "
" - dat += "
" - - if(3.2) //Protolathe Material Storage Sub-menu - dat += "Main Menu" - dat += "Protolathe Menu
" - dat += "

Material Storage:



" - //Metal - var/m_amount = linked_lathe.materials.amount(MAT_METAL) - dat += "* [m_amount] of Metal, [round(m_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(m_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(m_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(m_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Glass - var/g_amount = linked_lathe.materials.amount(MAT_GLASS) - dat += "* [g_amount] of Glass, [round(g_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(g_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(g_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(g_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Gold - var/gold_amount = linked_lathe.materials.amount(MAT_GOLD) - dat += "* [gold_amount] of Gold, [round(gold_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(gold_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(gold_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(gold_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Silver - var/silver_amount = linked_lathe.materials.amount(MAT_SILVER) - dat += "* [silver_amount] of Silver, [round(silver_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(silver_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(silver_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(silver_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Plasma - var/plasma_amount = linked_lathe.materials.amount(MAT_PLASMA) - dat += "* [plasma_amount] of Solid Plasma, [round(plasma_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(plasma_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(plasma_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(plasma_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Uranium - var/uranium_amount = linked_lathe.materials.amount(MAT_URANIUM) - dat += "* [uranium_amount] of Uranium, [round(uranium_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(uranium_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(uranium_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(uranium_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Diamond - var/diamond_amount = linked_lathe.materials.amount(MAT_DIAMOND) - dat += "* [diamond_amount] of Diamond, [round(diamond_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(diamond_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(diamond_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(diamond_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Bananium - var/bananium_amount = linked_lathe.materials.amount(MAT_BANANIUM) - dat += "* [bananium_amount] of Bananium, [round(bananium_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(bananium_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(bananium_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(bananium_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Tranquillite - var/tranquillite_amount = linked_lathe.materials.amount(MAT_TRANQUILLITE) - dat += "* [tranquillite_amount] of Tranquillite, [round(tranquillite_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(tranquillite_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(tranquillite_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(tranquillite_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - - if(3.3) - dat += "Main Menu" - dat += "Protolathe Menu" - dat += "Disposal All Chemicals in Storage
" - dat += "

Chemical Storage:



" + material_list["is_red"] = 0 + c = min(c, t) + design_list["can_build"] = c + if(submenu == 2) + var/list/materials_list = list() + data["loaded_materials"] = materials_list + materials_list[++materials_list.len] = list("name" = "Metal", "id" = MAT_METAL, "amount" = linked_lathe.materials.amount(MAT_METAL)) + materials_list[++materials_list.len] = list("name" = "Glass", "id" = MAT_GLASS, "amount" = linked_lathe.materials.amount(MAT_GLASS)) + materials_list[++materials_list.len] = list("name" = "Gold", "id" = MAT_GOLD, "amount" = linked_lathe.materials.amount(MAT_GOLD)) + materials_list[++materials_list.len] = list("name" = "Silver", "id" = MAT_SILVER, "amount" = linked_lathe.materials.amount(MAT_SILVER)) + materials_list[++materials_list.len] = list("name" = "Plasma", "id" = MAT_PLASMA, "amount" = linked_lathe.materials.amount(MAT_PLASMA)) + materials_list[++materials_list.len] = list("name" = "Uranium", "id" = MAT_URANIUM, "amount" = linked_lathe.materials.amount(MAT_URANIUM)) + materials_list[++materials_list.len] = list("name" = "Diamond", "id" = MAT_DIAMOND, "amount" = linked_lathe.materials.amount(MAT_DIAMOND)) + materials_list[++materials_list.len] = list("name" = "Bananium", "id" = MAT_BANANIUM, "amount" = linked_lathe.materials.amount(MAT_BANANIUM)) + materials_list[++materials_list.len] = list("name" = "Tranquillite", "id" = MAT_TRANQUILLITE, "amount" = linked_lathe.materials.amount(MAT_TRANQUILLITE)) + if(submenu == 3) + var/list/loaded_chemicals = list() + data["loaded_chemicals"] = loaded_chemicals for(var/datum/reagent/R in linked_lathe.reagents.reagent_list) - dat += "[R.name]: [R.volume]" - dat += "Purge
" - - ///////////////////CIRCUIT IMPRINTER SCREENS//////////////////// - if(4.0) - dat += "Main Menu
" - dat += "
NO CIRCUIT IMPRINTER LINKED TO CONSOLE
" - - if(4.1) - dat += "Main Menu" - dat += "Material Storage" - dat += "Chemical Storage
" - dat += "

Circuit Imprinter Menu:


" - dat += "Material Amount: [linked_imprinter.TotalMaterials()]
" - dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" - - dat += "
\ - \ - \ - \ - \ - \ -

" - - dat += list_categories(linked_imprinter.categories, 4.15) - - if(4.15) - dat += "Main Menu" - dat += "Circuit Imprinter Menu" - dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_imprinter.TotalMaterials()]
" - dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" - - var/coeff = linked_imprinter.efficiency_coeff - for(var/datum/design/D in files.known_designs) - if(!(selected_category in D.category) || !(D.build_type & IMPRINTER)) - continue - var/temp_materials - var/check_materials = 1 - for(var/M in D.materials) - temp_materials += " | " - if (!linked_imprinter.check_mat(D, M)) - check_materials = 0 - temp_materials += " [D.materials[M]/coeff] [CallMaterialName(M)]" - else - temp_materials += " [D.materials[M]/coeff] [CallMaterialName(M)]" - if (check_materials) - dat += "[D.name][temp_materials]
" - else - dat += "[D.name][temp_materials]
" - if(D.locked) - dat += " | LOCKED" - dat += "
" - - if(4.17) - dat += "Main Menu" - dat += "Circuit Imprinter Menu" - dat += "

Search results:


" - dat += "Material Amount: [linked_imprinter.TotalMaterials()]
" - dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" - + var/list/loaded_chemical = list() + loaded_chemicals[++loaded_chemicals.len] = loaded_chemical + loaded_chemical["name"] = R.name + loaded_chemical["volume"] = R.volume + loaded_chemical["id"] = R.id + + if(menu == 5 && linked_imprinter) + data["total_materials"] = linked_imprinter.TotalMaterials() + data["total_chemicals"] = linked_imprinter.reagents.total_volume + data["categories"] = linked_imprinter.categories + if(submenu == 1) + var/list/designs_list = list() + data["matching_designs"] = designs_list var/coeff = linked_imprinter.efficiency_coeff for(var/datum/design/D in matching_designs) - var/temp_materials + var/list/design_list = list() + designs_list[++designs_list.len] = design_list + var/list/materials_list = list() + design_list["materials"] = materials_list + design_list["id"] = D.id + design_list["name"] = sanitize(D.name) var/check_materials = 1 for(var/M in D.materials) - temp_materials += " | " + var/list/material_list = list() + materials_list[++materials_list.len] = material_list + material_list["name"] = CallMaterialName(M) + material_list["amount"] = D.materials[M] / coeff if (!linked_imprinter.check_mat(D, M)) check_materials = 0 - temp_materials += " [D.materials[M]/coeff] [CallMaterialName(M)]" + material_list["is_red"] = 1 else - temp_materials += " [D.materials[M]/coeff] [CallMaterialName(M)]" - if (check_materials) - dat += "[D.name][temp_materials]
" - else - dat += "[D.name][temp_materials]
" - dat += "
" - - if(4.2) - dat += "Main Menu" - dat += "Imprinter Menu" - dat += "Disposal All Chemicals in Storage
" - dat += "

Chemical Storage:



" + material_list["is_red"] = 0 + design_list["can_build"] = check_materials + if(submenu == 2) + var/list/materials_list = list() + data["loaded_materials"] = materials_list + materials_list[++materials_list.len] = list("name" = "Glass", "id" = MAT_GLASS, "amount" = linked_imprinter.g_amount) + materials_list[++materials_list.len] = list("name" = "Gold", "id" = MAT_GOLD, "amount" = linked_imprinter.gold_amount) + materials_list[++materials_list.len] = list("name" = "Diamond", "id" = MAT_DIAMOND, "amount" = linked_imprinter.diamond_amount) + if(submenu == 3) + var/list/loaded_chemicals = list() + data["loaded_chemicals"] = loaded_chemicals for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list) - dat += "[R.name]: [R.volume]" - dat += "Purge
" - - if(4.3) - dat += "Main Menu" - dat += "Circuit Imprinter Menu
" - dat += "

Material Storage:



" - //Glass - dat += "* [linked_imprinter.g_amount] glass, [round(linked_imprinter.g_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(linked_imprinter.g_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(linked_imprinter.g_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(linked_imprinter.g_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Gold - dat += "* [linked_imprinter.gold_amount] gold, [round(linked_imprinter.gold_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(linked_imprinter.gold_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(linked_imprinter.gold_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(linked_imprinter.gold_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - //Diamond - dat += "* [linked_imprinter.diamond_amount] diamond, [round(linked_imprinter.diamond_amount / MINERAL_MATERIAL_AMOUNT,0.1)] sheets: " - if(linked_imprinter.diamond_amount >= MINERAL_MATERIAL_AMOUNT) - dat += "Eject " - dat += "C " - if(linked_imprinter.diamond_amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " - if(linked_imprinter.diamond_amount >= MINERAL_MATERIAL_AMOUNT) dat += "All" - dat += "
" - - var/datum/browser/popup = new(user, "rndconsole", name, 700, 550) - popup.set_content(dat) - popup.open() - return + var/list/loaded_chemical = list() + loaded_chemicals[++loaded_chemicals.len] = loaded_chemical + loaded_chemical["name"] = R.name + loaded_chemical["volume"] = R.volume + loaded_chemical["id"] = R.id + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "r_n_d.tmpl", src.name, 800, 550) + ui.set_initial_data(data) + ui.open() //helper proc, which return a table containing categories /obj/machinery/computer/rdconsole/proc/list_categories(var/list/categories, var/menu_num as num) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index f34b727c354..de551e94b75 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -202,7 +202,8 @@ to_chat(user, "You offer [src] sentience potion to [SM]...") being_used = 1 - var/list/candidates = pollCandidates("Do you want to play as [SM.name]?", ROLE_SENTIENT, 0, 100) + var/ghostmsg = "Play as [SM.name], pet of [user.name]?" + var/list/candidates = pollCandidates(ghostmsg, ROLE_SENTIENT, 0, 100) if(!src) return diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 2d5b0acb8ed..586d9945c56 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -135,7 +135,7 @@ var/turf_type = /turf/space var/area_type = /area/space - + var/lock_shuttle_doors = 0 /obj/docking_port/stationary/register() @@ -167,7 +167,7 @@ /obj/docking_port/stationary/transit name = "In Transit" turf_type = /turf/space/transit - + lock_shuttle_doors = 1 /obj/docking_port/stationary/transit/register() @@ -775,6 +775,12 @@ shuttleId = "admin" possible_destinations = "admin_home;admin_away" +/obj/machinery/computer/shuttle/sst + name = "Syndicate Strike Time Shuttle Console" + desc = "Used to call and send the SST shuttle." + shuttleId = "sst" + possible_destinations = "sst_home;sst_away" + var/global/trade_dock_timelimit = 0 var/global/trade_dockrequest_timelimit = 0 @@ -790,7 +796,7 @@ var/global/trade_dockrequest_timelimit = 0 possible_destinations = possible_destinations_dock else possible_destinations = possible_destinations_nodock - + docking_request = (world.time > trade_dockrequest_timelimit && world.time > trade_dock_timelimit) ..(user) diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index d0245c224d9..c5d19ac2509 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -29,7 +29,7 @@ var/disfigured = 0 var/cannot_amputate var/cannot_break - var/s_tone + var/s_tone = null var/list/s_col = null // If this is instantiated, it should be a list of length 3 var/list/wounds = list() var/list/child_icons = list() diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index 0488d768adf..bd57c059d41 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -14,32 +14,33 @@ var/global/list/limb_icon_cache = list() overlays += organ.mob_icon child_icons += organ.mob_icon -/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) +/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/H) if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color return - if(species && human.species && species.name != human.species.name) + if(species && H.species && species.name != H.species.name) return - if(dna.unique_enzymes != human.dna.unique_enzymes) // This isn't MY arm - sync_colour_to_dna() - return - if(!isnull(human.s_tone) && (human.species.bodyflags & HAS_SKIN_TONE)) + if(dna.unique_enzymes != H.dna.unique_enzymes) // This isn't MY arm + if(!(H.species.bodyflags & HAS_ICON_SKIN_TONE)) + sync_colour_to_dna() + return + if(!isnull(H.s_tone) && ((H.species.bodyflags & HAS_SKIN_TONE) || (H.species.bodyflags & HAS_ICON_SKIN_TONE))) s_col = null - s_tone = human.s_tone - if(human.species.bodyflags & HAS_SKIN_COLOR) + s_tone = H.s_tone + if(H.species.bodyflags & HAS_SKIN_COLOR) s_tone = null - s_col = list(human.r_skin, human.g_skin, human.b_skin) + s_col = list(H.r_skin, H.g_skin, H.b_skin) /obj/item/organ/external/proc/sync_colour_to_dna() if(status & ORGAN_ROBOT) return - if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE)) + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && ((species.bodyflags & HAS_SKIN_TONE) || (species.bodyflags & HAS_ICON_SKIN_TONE))) s_col = null s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) if(species.flags & HAS_SKIN_COLOR) s_tone = null s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) -/obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human) +/obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/H) ..() var/obj/item/organ/internal/eyes/eyes = owner.get_int_organ(/obj/item/organ/internal/eyes)//owner.internal_organs_by_name["eyes"] if(eyes) eyes.update_colour() diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 57e2934dbb4..f4a47c595cb 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -81,7 +81,7 @@ return ..() /obj/item/organ/internal/proc/prepare_eat() - if(robotic) + if(status == ORGAN_ROBOT) return //no eating cybernetic implants! var/obj/item/weapon/reagent_containers/food/snacks/organ/S = new S.name = name diff --git a/code/modules/surgery/organs/robolimbs.dm b/code/modules/surgery/organs/robolimbs.dm index 0229ee80cae..c3d7f1c3828 100644 --- a/code/modules/surgery/organs/robolimbs.dm +++ b/code/modules/surgery/organs/robolimbs.dm @@ -1,5 +1,4 @@ var/global/list/all_robolimbs = list() -var/global/list/robolimb_data = list() var/global/list/chargen_robolimbs = list() var/global/datum/robolimb/basic_robolimb @@ -20,7 +19,7 @@ var/global/datum/robolimb/basic_robolimb var/unavailable_at_chargen // If set, not available at chargen. var/is_monitor // If set, limb is a monitor and should be getting monitor styles. var/has_subtypes = 2 // If null, object is a model. If 1, object is a brand (that serves as the default model) with child models. If 2, object is a brand that has no child models and thus also serves as the model.. - var/parts = list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand") //Defines what parts said brand can replace on a body. + var/parts = list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand") // Defines what parts said brand can replace on a body. /datum/robolimb/bishop company = "Bishop Cybernetics" diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm index 5d2bf63035b..9cf0a1020cc 100644 --- a/code/modules/surgery/organs/subtypes/diona.dm +++ b/code/modules/surgery/organs/subtypes/diona.dm @@ -169,6 +169,7 @@ icon = 'icons/mob/alien.dmi' icon_state = "claw" slot = "liver" + alcohol_intensity = 0.5 //TODO:Make absorb light on insert. diff --git a/code/modules/surgery/organs/subtypes/drask.dm b/code/modules/surgery/organs/subtypes/drask.dm index 3e9b37cebe8..e76f557088e 100644 --- a/code/modules/surgery/organs/subtypes/drask.dm +++ b/code/modules/surgery/organs/subtypes/drask.dm @@ -31,6 +31,7 @@ organ_tag = "kidneys" parent_organ = "groin" slot = "kidneys" + alcohol_intensity = 0.8 /obj/item/organ/internal/brain/drask name = "brain" @@ -49,4 +50,4 @@ organ_tag = "eyes" parent_organ = "head" slot = "eyes" - desc = "Drask eyes. They look even stranger disembodied" \ No newline at end of file + desc = "Drask eyes. They look even stranger disembodied" diff --git a/code/modules/surgery/organs/subtypes/grey.dm b/code/modules/surgery/organs/subtypes/grey.dm new file mode 100644 index 00000000000..45798486d4f --- /dev/null +++ b/code/modules/surgery/organs/subtypes/grey.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/grey + alcohol_intensity = 1.6 diff --git a/code/modules/surgery/organs/subtypes/kidan.dm b/code/modules/surgery/organs/subtypes/kidan.dm new file mode 100644 index 00000000000..2866e3904fb --- /dev/null +++ b/code/modules/surgery/organs/subtypes/kidan.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/kidan + alcohol_intensity = 0.5 diff --git a/code/modules/surgery/organs/subtypes/skrell.dm b/code/modules/surgery/organs/subtypes/skrell.dm index faf58b7a3ef..78c43c3a370 100644 --- a/code/modules/surgery/organs/subtypes/skrell.dm +++ b/code/modules/surgery/organs/subtypes/skrell.dm @@ -1,2 +1,2 @@ /obj/item/organ/internal/liver/skrell - alcohol_intensity = 5 \ No newline at end of file + alcohol_intensity = 4 diff --git a/code/modules/surgery/organs/subtypes/tajaran.dm b/code/modules/surgery/organs/subtypes/tajaran.dm new file mode 100644 index 00000000000..462c94be822 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/tajaran.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/tajaran + alcohol_intensity = 1.4 diff --git a/code/modules/surgery/organs/subtypes/unathi.dm b/code/modules/surgery/organs/subtypes/unathi.dm new file mode 100644 index 00000000000..5f204ab1750 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/unathi.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/unathi + alcohol_intensity = 0.8 diff --git a/code/modules/surgery/organs/subtypes/vox.dm b/code/modules/surgery/organs/subtypes/vox.dm new file mode 100644 index 00000000000..c5e86640364 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/vox.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/vox + alcohol_intensity = 1.6 diff --git a/code/modules/surgery/organs/subtypes/vulpkanin.dm b/code/modules/surgery/organs/subtypes/vulpkanin.dm new file mode 100644 index 00000000000..30b8d51f667 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/vulpkanin.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/vulpkanin + alcohol_intensity = 1.4 diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index f8051575b05..8e3ff02b091 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -264,6 +264,9 @@ playsound(S, 'sound/effects/bang.ogg', 50, 1) return 0 user.visible_message("[user] shines light onto the tumor in [target]'s head!", "You cleanse the contamination from [target]'s brain!") + if(target.vision_type) //Turns off their darksight if it's still active. + to_chat(target, "Your eyes are suddenly wrought with immense pain as your darksight is forcibly dismissed!") + target.vision_type = null ticker.mode.remove_thrall(target.mind, 0) target.visible_message("A strange black mass falls from [target]'s head!") new /obj/item/organ/internal/shadowtumor(get_turf(target)) diff --git a/code/modules/telesci/telesci_computer.dm b/code/modules/telesci/telesci_computer.dm index 2640b61bd33..b542f968516 100644 --- a/code/modules/telesci/telesci_computer.dm +++ b/code/modules/telesci/telesci_computer.dm @@ -24,7 +24,7 @@ // Based on the power used var/teleport_cooldown = 0 // every index requires a bluespace crystal - var/list/power_options = list(5, 10, 20, 25, 30, 40, 50, 80, 100) + var/list/power_options = list(5, 10, 20, 25, 30, 40, 50, 80) var/teleporting = 0 var/starting_crystals = 0 var/max_crystals = 4 @@ -396,4 +396,4 @@ teles_left = rand(30, 40) //angle_off = rand(-25, 25) power_off = rand(-4, 0) - rotation_off = rand(-10, 10) \ No newline at end of file + rotation_off = rand(-10, 10) diff --git a/html/changelog.html b/html/changelog.html index 56ad627eb86..b29fcaa7de1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,68 @@ -->
+

19 June 2016

+

DaveTheHeadcrab updated:

+
    +
  • Defibs now must be used within 3 minutes of death.
  • +
  • Combat defibs now induce heart attack when you stun with them (Emagged defibs have a 10^ chance to do this)
  • +
+

Fox McCloud updated:

+
    +
  • Adds in the ability to make latex glove balloons (cable coil+latex glove)
  • +
  • Fixes latex gloves not having an in-hand icon for the left hand
  • +
  • Telephones will now ring when activated in-hand
  • +
  • Force on telephones removed
  • +
  • The break room privacy shutters now apply to all windows in the medical break room and not just the ones out front
  • +
  • His Grace grants massive stamina regeneration
  • +
  • pre-made styptic, silver sulfadiazine, and synth flesh patches now apply instantly
  • +
  • Styptic and Burn patches now have unique icons
  • +
  • Partially fixes graffiti so it's actually visible
  • +
+

FreeStylaLT updated:

+
    +
  • changed its to it's in lockbox description
  • +
  • changed \red to formatting
  • +
  • changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to 1 TC
  • +
+

KasparoVy updated:

+
    +
  • Secure briefcase now has the same flags, hitsounds, attack verbs, throw speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins now.
  • +
  • Dethralling a Shadowling thrall that has darksight activated clears their darksight.
  • +
+

LittleBigKid2000 updated:

+
    +
  • The vox raider's base is now filled with nitrogen instead of regular dusty air.
  • +
+

TheDZD updated:

+
    +
  • Teaches camera assemblies the meaning of the word "respect" (for NODROP items).
  • +
  • Sates the insatiable hunger that orange shoes once had for secborg cuffs.
  • +
  • Cryodorms will no longer kick you to lobby if you have logged off when they despawn your body, they will now always ghost you.
  • +
  • The defense values on the riot armor helmet is now identical to those on the riot armor suit.
  • +
  • Knight armor (including the chaplain's crusader armor) now has a slowdown of 1 instead of no slowdown.
  • +
+

Twinmold updated:

+
    +
  • Fixes being able to eat cybernetic implants so you cannot eat them/force feed them to people.
  • +
  • Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability to insta-kill IPCs/incapacitate those with mechanical hearts.
  • +
  • Lowers amount of confusion given from Revenants from 50 to 20 per Defile.
  • +
  • Sets a maximum confused amount from the Revenant's Defile ability (now 30).
  • +
  • Makes Syndicate Bombs show a more accurate time remaining until detonation.
  • +
+

monster860 updated:

+
    +
  • Makes stock parts build 5x faster
  • +
  • Adds a last-second loop-back sort pipe so that items with a mail tag don't end up on the disposals conveyer, and get flushed right back around. This enables an item to be sent from anywhere on the station to anywhere else on the station without going through the disposals conveyer.
  • +
  • Fixes a bug where drones can get stuck if they have their destination set to the RD office. This also fixes the bug where attempting to send a package from the test lab always ends up in the RD office.
  • +
+

tkdrg, Delimusca, Aranclanos, TheDZD updated:

+
    +
  • Gun mimics (including wand, staff, projectile guns, and energy guns) created by the staff of animation will shoot things.
  • +
  • Mimics created by the staff of animation now have googly eyes.
  • +
  • Fixes the disturbing lack of death caused by wand of death projectiles.
  • +
+

12 June 2016

CrAzYPiLoT updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 0c1163ec003..3cc2cf1b582 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1760,3 +1760,67 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: removes atmos tech SOP from supply SOP - bugfix: Fixes defibing people without a heart - bugfix: Fixes defib saying it didn't work stopping a heart attack when they do +2016-06-19: + DaveTheHeadcrab: + - tweak: Defibs now must be used within 3 minutes of death. + - tweak: Combat defibs now induce heart attack when you stun with them (Emagged + defibs have a 10^ chance to do this) + Fox McCloud: + - rscadd: Adds in the ability to make latex glove balloons (cable coil+latex glove) + - bugfix: Fixes latex gloves not having an in-hand icon for the left hand + - rscadd: Telephones will now ring when activated in-hand + - tweak: Force on telephones removed + - tweak: The break room privacy shutters now apply to all windows in the medical + break room and not just the ones out front + - tweak: His Grace grants massive stamina regeneration + - tweak: pre-made styptic, silver sulfadiazine, and synth flesh patches now apply + instantly + - tweak: Styptic and Burn patches now have unique icons + - bugfix: Partially fixes graffiti so it's actually visible + FreeStylaLT: + - spellcheck: changed its to it's in lockbox description + - bugfix: changed \red to formatting + - tweak: changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to + 1 TC + KasparoVy: + - bugfix: Secure briefcase now has the same flags, hitsounds, attack verbs, throw + speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins + now. + - bugfix: Dethralling a Shadowling thrall that has darksight activated clears their + darksight. + LittleBigKid2000: + - bugfix: The vox raider's base is now filled with nitrogen instead of regular dusty + air. + TheDZD: + - bugfix: Teaches camera assemblies the meaning of the word "respect" (for NODROP + items). + - bugfix: Sates the insatiable hunger that orange shoes once had for secborg cuffs. + - rscdel: Cryodorms will no longer kick you to lobby if you have logged off when + they despawn your body, they will now always ghost you. + - tweak: The defense values on the riot armor helmet is now identical to those on + the riot armor suit. + - tweak: Knight armor (including the chaplain's crusader armor) now has a slowdown + of 1 instead of no slowdown. + Twinmold: + - bugfix: Fixes being able to eat cybernetic implants so you cannot eat them/force + feed them to people. + - tweak: Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability + to insta-kill IPCs/incapacitate those with mechanical hearts. + - tweak: Lowers amount of confusion given from Revenants from 50 to 20 per Defile. + - bugfix: Sets a maximum confused amount from the Revenant's Defile ability (now + 30). + - bugfix: Makes Syndicate Bombs show a more accurate time remaining until detonation. + monster860: + - tweak: Makes stock parts build 5x faster + - tweak: Adds a last-second loop-back sort pipe so that items with a mail tag don't + end up on the disposals conveyer, and get flushed right back around. This enables + an item to be sent from anywhere on the station to anywhere else on the station + without going through the disposals conveyer. + - bugfix: Fixes a bug where drones can get stuck if they have their destination + set to the RD office. This also fixes the bug where attempting to send a package + from the test lab always ends up in the RD office. + tkdrg, Delimusca, Aranclanos, TheDZD: + - rscadd: Gun mimics (including wand, staff, projectile guns, and energy guns) created + by the staff of animation will shoot things. + - rscadd: Mimics created by the staff of animation now have googly eyes. + - bugfix: Fixes the disturbing lack of death caused by wand of death projectiles. diff --git a/html/changelogs/AutoChangeLog-pr-4349.yml b/html/changelogs/AutoChangeLog-pr-4349.yml new file mode 100644 index 00000000000..239734732a7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4349.yml @@ -0,0 +1,11 @@ +author: VampyrBytes +delete-after: True +changes: + - rscadd: "Emotes can now be accessed through verbs as well as say *" + - rscdel: "Emotes accessed through say * no longer take parameters after a -" + - rscadd: "Emotes now take parameters through input boxes" + - rscadd: "Emotes now have support for blind and deaf characters" + - rscadd: "Emotes now personalise messages" + - tweak: "Flip can now be targeted with or without a grab" + - tweak: "All emotes that are affected by being muzzled now make the user make some kind of noise" + - bugfix: "monkeys now have access to all the emotes that the npc tries to perform" diff --git a/html/changelogs/AutoChangeLog-pr-4540.yml b/html/changelogs/AutoChangeLog-pr-4540.yml new file mode 100644 index 00000000000..846c1cd5dad --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4540.yml @@ -0,0 +1,4 @@ +author: CrAzYPiLoT +delete-after: True +changes: + - tweak: "Replaced the current recycler sound with a new one." diff --git a/html/changelogs/AutoChangeLog-pr-4610.yml b/html/changelogs/AutoChangeLog-pr-4610.yml new file mode 100644 index 00000000000..7fcbe80c073 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4610.yml @@ -0,0 +1,4 @@ +author: monster860 +delete-after: True +changes: + - tweak: "UI now gets it's own plane" diff --git a/html/changelogs/AutoChangeLog-pr-4614.yml b/html/changelogs/AutoChangeLog-pr-4614.yml new file mode 100644 index 00000000000..9a35d948fde --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4614.yml @@ -0,0 +1,12 @@ +author: KasparoVy +delete-after: True +changes: + - rscadd: "Adds Yi to Vox-pidgin syllables. (Port from VG.)" + - rscadd: "Adds framework for icon-based skin tones. (Port from VG.)" + - rscadd: "Adds Vox-compatibility for all remaining eyewear." + - rscadd: "Raiders now get a random skin tone and eye colour on spawn." + - rscadd: "Species default hair, facial hair and head-accessory colours can now be defined." + - rscadd: "Newly created Vox mobs will spawn with the same hair colour as they used to have pre-greyscaling." + - bugfix: "Noir vision will no longer grey out the HUD. (Port from VG.)" + - bugfix: "Tails will not be coloured if the person's species doesn't have skin colour." + - bugfix: "Vox hair (head and facial) have been greyscaled and can now be customized by the full colour range." diff --git a/html/changelogs/AutoChangeLog-pr-4624.yml b/html/changelogs/AutoChangeLog-pr-4624.yml new file mode 100644 index 00000000000..bf50776cc49 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4624.yml @@ -0,0 +1,6 @@ +author: monster860 +delete-after: True +changes: + - tweak: "RnD console now uses NanoUI! Sweet!" + - bugfix: "Fixes tranquillite being outside the box in the materials list. Mimes are supposed to be trapped inside a box, not outside one." + - tweak: "Replaces the weird unicode \"x\" character in some design names with the actual letter \"x\" so that it doesn't fuck up NanoUI" diff --git a/html/changelogs/AutoChangeLog-pr-4647.yml b/html/changelogs/AutoChangeLog-pr-4647.yml new file mode 100644 index 00000000000..07fb3d6d360 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4647.yml @@ -0,0 +1,6 @@ +author: FlattestGuitar +delete-after: True +changes: + - tweak: "changes some alcohol values, the weaker ones are no longer as weak" + - tweak: "refactored alcohol, you can now take short breaks between sips and still pass out in a gentlemanly manner" + - tweak: "different species have different levels of alcohol resistance, check in with your bartender for more information" diff --git a/html/changelogs/AutoChangeLog-pr-4654.yml b/html/changelogs/AutoChangeLog-pr-4654.yml deleted file mode 100644 index 26232f3d166..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4654.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: TheDZD -delete-after: True -changes: - - bugfix: "Teaches camera assemblies the meaning of the word \"respect\" (for NODROP items)." - - bugfix: "Sates the insatiable hunger that orange shoes once had for secborg cuffs." diff --git a/html/changelogs/AutoChangeLog-pr-4679.yml b/html/changelogs/AutoChangeLog-pr-4679.yml new file mode 100644 index 00000000000..bd4120a7a63 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4679.yml @@ -0,0 +1,5 @@ +author: Krausus +delete-after: True +changes: + - rscadd: "Added a custom runtime error handler." + - rscadd: "Added an in-game runtime viewer." diff --git a/html/changelogs/AutoChangeLog-pr-4687.yml b/html/changelogs/AutoChangeLog-pr-4687.yml new file mode 100644 index 00000000000..08b65ca541c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4687.yml @@ -0,0 +1,5 @@ +author: Fox McCloud +delete-after: True +changes: + - rscadd: "Warden starts off with a pair of Krav Maga Gloves" + - rscadd: "New Steal objective: steal the warden's krav maga gloves" diff --git a/html/changelogs/AutoChangeLog-pr-4699.yml b/html/changelogs/AutoChangeLog-pr-4699.yml new file mode 100644 index 00000000000..2bb156747d6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4699.yml @@ -0,0 +1,6 @@ +author: TheDZD +delete-after: True +changes: + - rscadd: "Adds an adminbuse gun that fires gun mimics, you can varedit the gun's `mimic_type` var to any gun path, and it'll fire that gun as mimics. By default it fires stetchkin pistol mimics." + - bugfix: "Fixes minor issues caused by some guns having text paths for power cells." + - bugfix: "Fixes some runtimes and inconsistencies with the telegun and temperature gun." diff --git a/html/changelogs/AutoChangeLog-pr-4703.yml b/html/changelogs/AutoChangeLog-pr-4703.yml new file mode 100644 index 00000000000..a1100322a8a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4703.yml @@ -0,0 +1,5 @@ +author: Fox McCloud +delete-after: True +changes: + - rscadd: "Clonepods will automatically suck in nearby meat" + - rscadd: "Slime processors will automatically suck in nearby dead slimes" diff --git a/html/changelogs/AutoChangeLog-pr-4704.yml b/html/changelogs/AutoChangeLog-pr-4704.yml new file mode 100644 index 00000000000..bbe89cfebb2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4704.yml @@ -0,0 +1,4 @@ +author: TheDZD +delete-after: True +changes: + - tweak: "The Tesla engine has acquired a grudge for lockers, and will now smite any in its path." diff --git a/html/changelogs/AutoChangeLog-pr-4718.yml b/html/changelogs/AutoChangeLog-pr-4718.yml new file mode 100644 index 00000000000..3ceac3d474a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4718.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - bugfix: "Actually fixes vamp chaplains" diff --git a/icons/effects/crayondecal.dmi b/icons/effects/crayondecal.dmi index 07ba85239d4..47d670d5149 100644 Binary files a/icons/effects/crayondecal.dmi and b/icons/effects/crayondecal.dmi differ diff --git a/icons/effects/species.dmi b/icons/effects/species.dmi index 7096b2d360a..ee3da07c3c5 100644 Binary files a/icons/effects/species.dmi and b/icons/effects/species.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index a53d468804d..0012ecc2d06 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_races/r_def_vox.dmi b/icons/mob/human_races/vox/r_def_vox.dmi similarity index 100% rename from icons/mob/human_races/r_def_vox.dmi rename to icons/mob/human_races/vox/r_def_vox.dmi diff --git a/icons/mob/human_races/vox/r_def_voxazu.dmi b/icons/mob/human_races/vox/r_def_voxazu.dmi new file mode 100644 index 00000000000..2799b046c8f Binary files /dev/null and b/icons/mob/human_races/vox/r_def_voxazu.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxbrn.dmi b/icons/mob/human_races/vox/r_def_voxbrn.dmi new file mode 100644 index 00000000000..291687f0961 Binary files /dev/null and b/icons/mob/human_races/vox/r_def_voxbrn.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxdgrn.dmi b/icons/mob/human_races/vox/r_def_voxdgrn.dmi new file mode 100644 index 00000000000..f78ec512bcb Binary files /dev/null and b/icons/mob/human_races/vox/r_def_voxdgrn.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxemrl.dmi b/icons/mob/human_races/vox/r_def_voxemrl.dmi new file mode 100644 index 00000000000..fcc33f42b7c Binary files /dev/null and b/icons/mob/human_races/vox/r_def_voxemrl.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxgry.dmi b/icons/mob/human_races/vox/r_def_voxgry.dmi new file mode 100644 index 00000000000..0e774b50780 Binary files /dev/null and b/icons/mob/human_races/vox/r_def_voxgry.dmi differ diff --git a/icons/mob/human_races/r_vox.dmi b/icons/mob/human_races/vox/r_vox.dmi similarity index 100% rename from icons/mob/human_races/r_vox.dmi rename to icons/mob/human_races/vox/r_vox.dmi diff --git a/icons/mob/human_races/vox/r_voxazu.dmi b/icons/mob/human_races/vox/r_voxazu.dmi new file mode 100644 index 00000000000..2799b046c8f Binary files /dev/null and b/icons/mob/human_races/vox/r_voxazu.dmi differ diff --git a/icons/mob/human_races/vox/r_voxbrn.dmi b/icons/mob/human_races/vox/r_voxbrn.dmi new file mode 100644 index 00000000000..291687f0961 Binary files /dev/null and b/icons/mob/human_races/vox/r_voxbrn.dmi differ diff --git a/icons/mob/human_races/vox/r_voxdgrn.dmi b/icons/mob/human_races/vox/r_voxdgrn.dmi new file mode 100644 index 00000000000..f78ec512bcb Binary files /dev/null and b/icons/mob/human_races/vox/r_voxdgrn.dmi differ diff --git a/icons/mob/human_races/vox/r_voxemrl.dmi b/icons/mob/human_races/vox/r_voxemrl.dmi new file mode 100644 index 00000000000..fcc33f42b7c Binary files /dev/null and b/icons/mob/human_races/vox/r_voxemrl.dmi differ diff --git a/icons/mob/human_races/vox/r_voxgry.dmi b/icons/mob/human_races/vox/r_voxgry.dmi new file mode 100644 index 00000000000..0e774b50780 Binary files /dev/null and b/icons/mob/human_races/vox/r_voxgry.dmi differ diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi index 27acdc6a156..763e2f0710c 100644 Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index bc74db7c722..685e6b2977b 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/species/drask/helmet.dmi b/icons/mob/species/drask/helmet.dmi index 0fdd257f0d9..df3929ddd08 100644 Binary files a/icons/mob/species/drask/helmet.dmi and b/icons/mob/species/drask/helmet.dmi differ diff --git a/icons/mob/species/vox/eyes.dmi b/icons/mob/species/vox/eyes.dmi index 32753f85d13..f761fb361a7 100644 Binary files a/icons/mob/species/vox/eyes.dmi and b/icons/mob/species/vox/eyes.dmi differ diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi index fd3fea468d4..f80312633f0 100644 Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 589b2654211..e162c42a531 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 54ed8f57927..ccf3bad52b5 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 6b2732f13ed..7893396874b 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/nano/templates/r_n_d.tmpl b/nano/templates/r_n_d.tmpl new file mode 100644 index 00000000000..5d29c399550 --- /dev/null +++ b/nano/templates/r_n_d.tmpl @@ -0,0 +1,260 @@ +{{if data.menu > 0 && !data.wait_message}} +
    + {{:helper.link('Main Menu', 'reply', {'menu': 0, 'submenu': 0})}} + {{if data.submenu > 0}} + {{if data.menu == 2}} + {{:helper.link('Disk Operations Menu', 'reply', {'submenu': 0})}} + {{else data.menu == 4}} + {{:helper.link('Protolathe Menu', 'reply', {'submenu': 0})}} + {{else data.menu == 5}} + {{:helper.link('Circuit Imprinter Menu', 'reply', {'submenu': 0})}} + {{else data.menu == 6}} + {{:helper.link('Settings Menu', 'reply', {'submenu': 0})}} + {{/if}} + {{else data.menu == 4 || data.menu == 5}} + {{:helper.link('Material Storage', 'arrow-up', {'submenu': 2})}} + {{:helper.link('Chemical Storage', 'arrow-up', {'submenu': 3})}} + {{/if}} +
    +{{/if}} +
    + {{if data.wait_message}} + {{:data.wait_message}} + {{else data.menu == 0}} +

    Main Menu:

    +
    {{:helper.link('Current Research Levels', 'folder-open', {'menu': 1, 'submenu': 0})}}
    +
    {{:helper.link('Disk Operations', 'save', {'menu': 2, 'submenu': 0}, data.disk_type ? null : 'disabled')}}
    +
    {{:helper.link('Destructive Analyzer Menu', 'chain-broken', {'menu': 3, 'submenu': 0}, data.linked_destroy ? null : 'disabled')}}
    +
    {{:helper.link('Protolathe Menu', 'print', {'menu': 4, 'submenu': 0}, data.linked_lathe ? null : 'disabled')}}
    +
    {{:helper.link('Circuit Imprinter Menu', 'print', {'menu': 5, 'submenu': 0}, data.linked_imprinter ? null : 'disabled')}}
    +
    {{:helper.link('Settings', 'gear', {'menu': 6, 'submenu': 0})}}
    + {{else data.menu == 1}} +

    Current Research Levels:

    + {{for data.tech_levels}} + {{if index > 0}} +
    + {{/if}} +
    {{:value.name}}
    +
    * Level: {{:value.level}}
    +
    * Summary: {{:value.desc}}
    + {{/for}} + {{else data.menu == 2 && data.disk_type}} + {{if data.submenu == 0}} +

    Data Disk Contents:

    + {{if data.disk_data}} + {{if data.disk_type == 1}} +
    Name: {{:data.disk_data.name}}
    +
    Level: {{:data.disk_data.level}}
    +
    Description: {{:data.disk_data.desc}}
    + {{:helper.link('Upload to Database', 'arrow-up', {'updt_tech': 1})}} + {{:helper.link('Clear Disk', 'trash', {'clear_tech': 1})}} + {{else}} +
    Name: {{:data.disk_data.name}}
    +
    Reliability: {{:data.disk_data.reliability}}
    +
    + {{for data.disk_data.lathe_types}} + {{if index == 0}} + Lathe Types: + {{else}} + , + {{/if}} + {{:value}} + {{/for}} +
    +
    Required Materials:
    + {{for data.disk_data.materials}} +
    {{:value.name}} x {{:value.amount}}
    + {{/for}} + {{:helper.link('Upload to Database', 'arrow-up', {'updt_design': 1})}} + {{:helper.link('Clear Disk', 'trash', {'clear_design': 1})}} + {{/if}} + {{else}} +
    This disk is empty.
    + {{:helper.link(data.disk_type == 1 ? 'Load Tech to Disk' : 'Load Design to Disk', 'arrow-down', {'submenu': 1})}} + {{/if}} + {{:helper.link('Eject Disk', 'eject', data.disk_type == 1 ? {'eject_tech': 1} : {'eject_design': 1})}} + {{else data.submenu == 1}} + {{for data.to_copy}} +
    +
    {{:value.name}}
    + {{:helper.link('Copy to Disk', 'arrow-down', data.disk_type == 1 ? {'copy_tech': 1, 'copy_tech_ID': value.id} : {'copy_design': 1, 'copy_design_ID': value.id})}} +
    + {{/for}} + {{/if}} + {{else data.menu == 3 && !data.linked_destroy}} + NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE + {{else data.menu == 4 && !data.linked_lathe}} + NO PROTOLATHE LINKED TO CONSOLE + {{else data.menu == 5 && !data.linked_imprinter}} + NO CIRCUIT IMPRITER LINKED TO CONSOLE + {{else data.menu == 3}} + {{if !data.loaded_item}} + No item loaded. Standing by... + {{else}} +

    Deconstruction Menu:

    +
    Name: {{:data.loaded_item.name}}
    +
    Reliability: {{:data.loaded_item.reliability}}
    +

    Origin Tech:

    + {{for data.loaded_item.origin_tech}} +
    +
    * {{:value.name}}:
    +
    + {{:value.object_level}} + {{if value.current_level}} + (Current: {{:value.current_level}}) + {{/if}} +
    +
    + {{/for}} +

    Options:

    + {{:helper.link('Deconstruct Item', 'chain-broken', {'deconstruct': 1})}} + {{:helper.link('Eject Item', 'eject', {'eject_item': 1})}} + {{/if}} + {{else data.menu == 4 || data.menu == 5}} + {{if data.submenu == 0}} +

    {{:(data.menu == 4 ? 'Protolathe' : 'Circuit Imprinter')}} Menu:

    + {{else data.submenu == 1}} +

    {{:data.category}}:

    + {{else data.submenu == 2}} +

    Material Storage:

    + {{else data.submenu == 3}} +

    Chemical Storage:

    + {{/if}} + + {{if data.submenu < 2}} +
    + + + {{if data.max_materials}} + + {{/if}} + + + + {{if data.max_chemicals}} + + {{/if}} + +
    Material Amount:{{:data.total_materials}} / {{:data.max_materials}}
    Chemical Amount:{{:data.total_chemicals}} / {{:data.max_chemicals}}
    + {{/if}} + + {{if data.submenu == 0}} +
    + + + + +
    + +
    + + {{for data.categories}} + {{if (index & 1) == 0 && index != 0}} + + {{/if}} + + {{/for}} +
    {{:helper.link(value, 'arrow-right', {'category': value})}}
    + {{else data.submenu == 1}} + + {{for data.matching_designs}} + + + + + + + {{/for}} +
    {{:helper.link(value.name, 'print', data.menu == 4 ? {'build': value.id, 'amount': 1} : {'imprint': value.id}, value.can_build ? null : 'disabled')}}{{if value.can_build >= 5}} + {{:helper.link('x5', null, data.menu == 4 ? {'build': value.id, 'amount': 5} : {'imprint': value.id})}} + {{/if}}{{if value.can_build >= 10}} + {{:helper.link('x10', null, data.menu == 4 ? {'build': value.id, 'amount': 10} : {'imprint': value.id})}} + {{/if}} + {{for value.materials : material : i}} + | + {{if material.is_red}} + + {{/if}} + {{:material.amount}} {{:material.name}} + {{if material.is_red}} + + {{/if}} + {{/for}} +
    + {{else data.submenu == 2}} + {{for data.loaded_materials}} +
    +
    * {{:value.amount}} of {{:value.name}}
    ({{:Math.round((value.amount / 2000) * 10) / 10}} sheets)
    + {{if value.amount >= 2000}} + {{if data.menu == 4}} + {{:helper.link('1x', 'eject', {'lathe_ejectsheet': value.id, 'lathe_ejectsheet_amt': 1})}} + {{:helper.link('C', 'eject', {'lathe_ejectsheet': value.id, 'lathe_ejectsheet_amt': 'custom'})}} + {{if value.amount >= 2000*5}} + {{:helper.link('5x', 'eject', {'lathe_ejectsheet': value.id, 'lathe_ejectsheet_amt': 5})}} + {{/if}} + {{:helper.link('All', 'eject', {'lathe_ejectsheet': value.id, 'lathe_ejectsheet_amt': 50})}} + {{else}} + {{:helper.link('1x', 'eject', {'imprinter_ejectsheet': value.id, 'imprinter_ejectsheet_amt': 1})}} + {{:helper.link('C', 'eject', {'imprinter_ejectsheet': value.id, 'imprinter_ejectsheet_amt': 'custom'})}} + {{if value.amount >= 2000*5}} + {{:helper.link('5x', 'eject', {'imprinter_ejectsheet': value.id, 'imprinter_ejectsheet_amt': 5})}} + {{/if}} + {{:helper.link('All', 'eject', {'imprinter_ejectsheet': value.id, 'imprinter_ejectsheet_amt': 50})}} + {{/if}} + {{/if}} +
    + {{/for}} + {{else data.submenu == 3}} +
    + + {{:helper.link('Purge All', 'trash', data.menu == 4 ? {'disposeallP': 1} : {'disposeallI' : 1})}} +
    + {{for data.loaded_chemicals}} +
    +
    * {{:value.volume}} of {{:value.name}}
    + {{:helper.link('Purge', 'trash', data.menu == 4 ? {'disposeP': value.id} : {'disposeI': value.id})}} +
    + {{/for}} + {{/if}} + {{else data.menu == 6}} + {{if data.submenu == 0}} +

    Settings:

    +
    {{:helper.link('Sync Database with Network', 'refresh', {'sync': 1}, data.sync ? null : 'disabled')}}
    +
    {{:helper.link('Connect to Research Network', 'plug', {'togglesync': 1}, data.sync ? 'selected' : null)}}
    +
    {{:helper.link('Disconnect from Research Network', 'chain-broken', {'togglesync': 1}, data.sync ? null : 'selected')}}
    +
    {{:helper.link('Device Linkage Menu', 'chain', {'menu': 6, 'submenu': 1})}}
    + {{if data.admin}} +
    {{:helper.link('[ADMIN] Maximize Research Levels', 'exclamation', {'maxresearch': 1})}}
    + {{/if}} +
    {{:helper.link('Reset Database', 'trash-o', {'reset': 1})}}
    + {{else data.submenu == 1}} +

    Device Linkage Menu:

    +
    {{:helper.link('Re-sync with Nearby Devices', 'chain', {'find_device': 1})}}
    +

    Linked Devices:

    +
    + {{if data.linked_destroy}} +
    * Destructive Analyzer
    + {{:helper.link('Unlink', 'chain-broken', {'disconnect': 'destroy'})}} + {{else}} +
    * No Destructive Analyzer Linked
    + {{/if}} +
    +
    + {{if data.linked_lathe}} +
    * Protolathe
    + {{:helper.link('Unlink', 'chain-broken', {'disconnect': 'lathe'})}} + {{else}} +
    * No Protolathe Linked
    + {{/if}} +
    +
    + {{if data.linked_imprinter}} +
    * Circuit Imprinter
    + {{:helper.link('Unlink', 'chain-broken', {'disconnect': 'imprinter'})}} + {{else}} +
    * No Circuit Imprinter Linked
    + {{/if}} +
    + {{/if}} + {{/if}} +
    \ No newline at end of file diff --git a/paradise.dme b/paradise.dme index 2d0879202ba..6ce4eda7ad8 100644 --- a/paradise.dme +++ b/paradise.dme @@ -20,6 +20,7 @@ #include "code\__DEFINES\bots.dm" #include "code\__DEFINES\clothing.dm" #include "code\__DEFINES\combat.dm" +#include "code\__DEFINES\error_handler.dm" #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\game.dm" #include "code\__DEFINES\genetics.dm" @@ -263,6 +264,9 @@ #include "code\datums\diseases\advance\symptoms\weakness.dm" #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" +#include "code\datums\Emote_system\emote.dm" +#include "code\datums\Emote_system\emote_handler.dm" +#include "code\datums\Emote_system\emotes.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\global_iterator.dm" @@ -1240,6 +1244,8 @@ #include "code\modules\economy\Job_Departments.dm" #include "code\modules\economy\POS.dm" #include "code\modules\economy\utils.dm" +#include "code\modules\error_handler\error_handler.dm" +#include "code\modules\error_handler\error_viewer.dm" #include "code\modules\events\abductor.dm" #include "code\modules\events\alien_infestation.dm" #include "code\modules\events\anomaly.dm" @@ -1397,7 +1403,6 @@ #include "code\modules\mining\laborcamp\laborstacker.dm" #include "code\modules\mob\abilities.dm" #include "code\modules\mob\death.dm" -#include "code\modules\mob\emote.dm" #include "code\modules\mob\hear_say.dm" #include "code\modules\mob\holder.dm" #include "code\modules\mob\inventory.dm" @@ -1449,7 +1454,6 @@ #include "code\modules\mob\living\carbon\alien\login.dm" #include "code\modules\mob\living\carbon\alien\logout.dm" #include "code\modules\mob\living\carbon\alien\humanoid\alien_powers.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\emote.dm" #include "code\modules\mob\living\carbon\alien\humanoid\empress.dm" #include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm" #include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm" @@ -1461,7 +1465,6 @@ #include "code\modules\mob\living\carbon\alien\humanoid\caste\hunter.dm" #include "code\modules\mob\living\carbon\alien\humanoid\caste\sentinel.dm" #include "code\modules\mob\living\carbon\alien\larva\death.dm" -#include "code\modules\mob\living\carbon\alien\larva\emote.dm" #include "code\modules\mob\living\carbon\alien\larva\inventory.dm" #include "code\modules\mob\living\carbon\alien\larva\larva.dm" #include "code\modules\mob\living\carbon\alien\larva\life.dm" @@ -1472,7 +1475,6 @@ #include "code\modules\mob\living\carbon\brain\brain.dm" #include "code\modules\mob\living\carbon\brain\brain_item.dm" #include "code\modules\mob\living\carbon\brain\death.dm" -#include "code\modules\mob\living\carbon\brain\emote.dm" #include "code\modules\mob\living\carbon\brain\life.dm" #include "code\modules\mob\living\carbon\brain\login.dm" #include "code\modules\mob\living\carbon\brain\MMI.dm" @@ -1481,7 +1483,6 @@ #include "code\modules\mob\living\carbon\human\appearance.dm" #include "code\modules\mob\living\carbon\human\body_accessories.dm" #include "code\modules\mob\living\carbon\human\death.dm" -#include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" #include "code\modules\mob\living\carbon\human\human_attackalien.dm" @@ -1512,7 +1513,6 @@ #include "code\modules\mob\living\carbon\human\species\species.dm" #include "code\modules\mob\living\carbon\human\species\station.dm" #include "code\modules\mob\living\carbon\slime\death.dm" -#include "code\modules\mob\living\carbon\slime\emote.dm" #include "code\modules\mob\living\carbon\slime\examine.dm" #include "code\modules\mob\living\carbon\slime\life.dm" #include "code\modules\mob\living\carbon\slime\powers.dm" @@ -1521,7 +1521,6 @@ #include "code\modules\mob\living\carbon\slime\subtypes.dm" #include "code\modules\mob\living\carbon\slime\update_icons.dm" #include "code\modules\mob\living\silicon\death.dm" -#include "code\modules\mob\living\silicon\emote.dm" #include "code\modules\mob\living\silicon\laws.dm" #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" @@ -1544,7 +1543,6 @@ #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" #include "code\modules\mob\living\silicon\pai\death.dm" -#include "code\modules\mob\living\silicon\pai\emote.dm" #include "code\modules\mob\living\silicon\pai\examine.dm" #include "code\modules\mob\living\silicon\pai\life.dm" #include "code\modules\mob\living\silicon\pai\pai.dm" @@ -1555,7 +1553,6 @@ #include "code\modules\mob\living\silicon\pai\software_modules.dm" #include "code\modules\mob\living\silicon\robot\component.dm" #include "code\modules\mob\living\silicon\robot\death.dm" -#include "code\modules\mob\living\silicon\robot\emote.dm" #include "code\modules\mob\living\silicon\robot\examine.dm" #include "code\modules\mob\living\silicon\robot\inventory.dm" #include "code\modules\mob\living\silicon\robot\laws.dm" @@ -1588,7 +1585,6 @@ #include "code\modules\mob\living\simple_animal\bot\cleanbot.dm" #include "code\modules\mob\living\simple_animal\bot\construction.dm" #include "code\modules\mob\living\simple_animal\bot\ed209bot.dm" -#include "code\modules\mob\living\simple_animal\bot\emote.dm" #include "code\modules\mob\living\simple_animal\bot\floorbot.dm" #include "code\modules\mob\living\simple_animal\bot\medbot.dm" #include "code\modules\mob\living\simple_animal\bot\mulebot.dm" @@ -2017,12 +2013,18 @@ #include "code\modules\surgery\organs\wound.dm" #include "code\modules\surgery\organs\subtypes\diona.dm" #include "code\modules\surgery\organs\subtypes\drask.dm" +#include "code\modules\surgery\organs\subtypes\grey.dm" +#include "code\modules\surgery\organs\subtypes\kidan.dm" #include "code\modules\surgery\organs\subtypes\machine.dm" #include "code\modules\surgery\organs\subtypes\misc.dm" #include "code\modules\surgery\organs\subtypes\nucleation.dm" #include "code\modules\surgery\organs\subtypes\skrell.dm" #include "code\modules\surgery\organs\subtypes\standard.dm" +#include "code\modules\surgery\organs\subtypes\tajaran.dm" +#include "code\modules\surgery\organs\subtypes\unathi.dm" #include "code\modules\surgery\organs\subtypes\unbreakable.dm" +#include "code\modules\surgery\organs\subtypes\vox.dm" +#include "code\modules\surgery\organs\subtypes\vulpkanin.dm" #include "code\modules\surgery\organs\subtypes\wryn.dm" #include "code\modules\surgery\organs\subtypes\xenos.dm" #include "code\modules\telesci\bscrystal.dm" diff --git a/sound/machines/recycler.ogg b/sound/machines/recycler.ogg new file mode 100644 index 00000000000..d4f2c884087 Binary files /dev/null and b/sound/machines/recycler.ogg differ