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/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm index b50efa38848..bb50f35b41d 100644 --- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm +++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm @@ -455,7 +455,7 @@ "aiM" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/structure/cable/yellow,/turf/simulated/floor/plating,/area/security/prison) "aiN" = (/obj/machinery/flasher/portable,/obj/machinery/flasher/portable,/obj/structure/reagent_dispensers/peppertank{pixel_x = 0; pixel_y = 29},/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/security/warden) "aiO" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/warden) -"aiP" = (/obj/structure/rack,/obj/item/weapon/gun/energy/advtaser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/advtaser,/obj/item/weapon/gun/energy/advtaser{pixel_x = 3; pixel_y = -3},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{tag = "icon-vault (NORTH)"; icon_state = "vault"; dir = 1},/area/security/warden) +"aiP" = (/obj/structure/rack,/obj/item/weapon/gun/energy/gun/advtaser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/gun/advtaser,/obj/item/weapon/gun/energy/gun/advtaser{pixel_x = 3; pixel_y = -3},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{tag = "icon-vault (NORTH)"; icon_state = "vault"; dir = 1},/area/security/warden) "aiQ" = (/obj/machinery/syndicatebomb/training,/turf/simulated/floor/plasteel{tag = "icon-vault (WEST)"; icon_state = "vault"; dir = 8},/area/security/warden) "aiR" = (/obj/structure/rack,/obj/item/weapon/gun/energy/laser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/laser,/obj/item/weapon/gun/energy/laser{pixel_x = 3; pixel_y = -3},/turf/simulated/floor/plasteel{tag = "icon-vault (EAST)"; icon_state = "vault"; dir = 4},/area/security/warden) "aiS" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/warden) @@ -583,7 +583,7 @@ "alk" = (/obj/machinery/alarm{pixel_y = 24},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness{name = "\improper Recreation Area"}) "all" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_l"; icon_state = "propulsion_l"},/turf/space,/area/shuttle/vox) "alm" = (/obj/structure/rack,/obj/item/clothing/accessory/storage/black_vest,/obj/item/clothing/suit/space/vox/pressure,/obj/item/clothing/head/helmet/space/vox/pressure,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) -"aln" = (/obj/structure/rack,/obj/item/weapon/gun/launcher/spikethrower,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) +"aln" = (/obj/structure/rack,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) "alo" = (/obj/machinery/door/poddoor{id_tag = "trash"; name = "disposal bay door"},/turf/simulated/floor/plating,/area/maintenance/disposal) "alp" = (/obj/machinery/mass_driver{dir = 8; id_tag = "trash"},/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/maintenance/disposal) "alq" = (/obj/machinery/conveyor_switch/oneway{convdir = -1; id = "garbage"; name = "disposal coveyor"},/turf/simulated/floor/plating,/area/maintenance/disposal) @@ -1679,7 +1679,7 @@ "aGo" = (/obj/machinery/light,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 6},/area/security/nuke_storage) "aGp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{icon_state = "vault"},/area/security/nuke_storage) "aGq" = (/obj/machinery/camera/motion{c_tag = "Vault"; dir = 1; network = list("MiniSat")},/obj/machinery/light,/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 10},/area/security/nuke_storage) -"aGr" = (/obj/structure/safe,/obj/item/weapon/storage/secure/briefcase{contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/weapon/gun/projectile/automatic/pistol,/obj/item/weapon/suppressor,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/weapon/soap/nanotrasen)},/obj/item/weapon/storage/backpack/duffel{contents = newlist(/obj/item/clothing/under/lawyer,/obj/item/clothing/accessory/waistcoat,/obj/item/clothing/shoes/laceup,/obj/item/clothing/gloves/color/black,/obj/item/clothing/glasses/sunglasses,/obj/item/clothing/head/fedora); desc = "A large dufflebag for holding extra things. There is a NanoTrasen logo on the back."; icon_state = "duffle-syndieammo"; item_state = "duffle-syndieammo"},/obj/item/weapon/card/id/silver{access = list(12); assignment = "Reaper"; name = "Thirteen's ID Card (Reaper)"; registered_name = "Thirteen"},/obj/item/weapon/lazarus_injector,/obj/item/weapon/gun/energy/advtaser,/obj/item/weapon/gun/projectile/revolver/russian,/obj/item/ammo_box/a357,/obj/item/clothing/accessory/stethoscope,/obj/item/weapon/book{desc = "An undeniably handy book."; icon_state = "bookknock"; name = "A Simpleton's Guide to Safe-cracking with Stethoscopes"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 4},/area/security/nuke_storage) +"aGr" = (/obj/structure/safe,/obj/item/weapon/storage/secure/briefcase{contents = newlist(/obj/item/clothing/suit/armor/vest,/obj/item/weapon/gun/projectile/automatic/pistol,/obj/item/weapon/suppressor,/obj/item/clothing/mask/balaclava,/obj/item/bodybag,/obj/item/weapon/soap/nanotrasen)},/obj/item/weapon/storage/backpack/duffel{contents = newlist(/obj/item/clothing/under/lawyer,/obj/item/clothing/accessory/waistcoat,/obj/item/clothing/shoes/laceup,/obj/item/clothing/gloves/color/black,/obj/item/clothing/glasses/sunglasses,/obj/item/clothing/head/fedora); desc = "A large dufflebag for holding extra things. There is a NanoTrasen logo on the back."; icon_state = "duffle-syndieammo"; item_state = "duffle-syndieammo"},/obj/item/weapon/card/id/silver{access = list(12); assignment = "Reaper"; name = "Thirteen's ID Card (Reaper)"; registered_name = "Thirteen"},/obj/item/weapon/lazarus_injector,/obj/item/weapon/gun/energy/gun/advtaser,/obj/item/weapon/gun/projectile/revolver/russian,/obj/item/ammo_box/a357,/obj/item/clothing/accessory/stethoscope,/obj/item/weapon/book{desc = "An undeniably handy book."; icon_state = "bookknock"; name = "A Simpleton's Guide to Safe-cracking with Stethoscopes"},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 4},/area/security/nuke_storage) "aGs" = (/obj/structure/shuttle/engine/heater,/obj/structure/window/reinforced{dir = 1; layer = 2.9},/turf/simulated/shuttle/plating,/area/shuttle/siberia) "aGt" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_security{name = "Labor Camp Shuttle Airlock"; req_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/hallway/primary/fore) "aGu" = (/obj/effect/spawner/window/reinforced{useFull = 1; tag = "fullReinWin"},/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/obj/machinery/door/poddoor/preopen{id_tag = "Secure Gate"; name = "brig shutters"},/turf/simulated/floor/plating,/area/security/brig) diff --git a/_maps/map_files/RandomZLevels/beach.dmm b/_maps/map_files/RandomZLevels/beach.dmm index 0a5cd703fc0..04512b660bf 100644 --- a/_maps/map_files/RandomZLevels/beach.dmm +++ b/_maps/map_files/RandomZLevels/beach.dmm @@ -19,7 +19,7 @@ "as" = (/obj/structure/boulder,/turf/unsimulated/beach/water/deep/sand_floor,/area/awaymission/undersea) "at" = (/obj/item/flag/cult,/turf/unsimulated/beach/water/deep/wood_floor,/area/awaymission/undersea) "au" = (/obj/structure/mineral_door/sandstone,/obj/structure/barricade/wooden,/turf/unsimulated/beach/water/deep/wood_floor,/area/awaymission/undersea) -"av" = (/obj/item/weapon/crossbowframe,/turf/unsimulated/beach/water/deep/sand_floor,/area/awaymission/undersea) +"av" = (/turf/unsimulated/beach/water/deep/sand_floor,/area/awaymission/undersea) "aw" = (/obj/item/toy/eight_ball/conch,/turf/unsimulated/beach/water/deep/wood_floor,/area/awaymission/undersea) "ax" = (/obj/structure/reagent_dispensers/beerkeg,/turf/unsimulated/beach/water/deep/wood_floor,/area/awaymission/undersea) "ay" = (/obj/structure/closet/cabinet,/turf/unsimulated/beach/water/deep/wood_floor,/area/awaymission/undersea) diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 6eef766fd9b..6a8fb071c95 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -225,7 +225,7 @@ "aeq" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/security/interrogationobs) "aer" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/camera{c_tag = "Brig Prison Hallway"; dir = 4; network = list("Prison","SS13")},/turf/simulated/floor/plasteel{icon_state = "red"; dir = 8},/area/security/permabrig) "aes" = (/obj/structure/lattice,/obj/machinery/camera{c_tag = "Brig Secure Armory Exterior South"; dir = 8; network = list("SS13")},/turf/space,/area/security/permabrig) -"aet" = (/obj/structure/rack,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/item/weapon/gun/energy/advtaser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/advtaser{pixel_x = 0; pixel_y = 0},/obj/item/weapon/gun/energy/advtaser{pixel_x = 3; pixel_y = -3},/turf/simulated/floor/plasteel{dir = 8; icon_state = "vault"; tag = "icon-vault (WEST)"},/area/security/securearmoury) +"aet" = (/obj/structure/rack,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/item/weapon/gun/energy/gun/advtaser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/gun/advtaser{pixel_x = 0; pixel_y = 0},/obj/item/weapon/gun/energy/gun/advtaser{pixel_x = 3; pixel_y = -3},/turf/simulated/floor/plasteel{dir = 8; icon_state = "vault"; tag = "icon-vault (WEST)"},/area/security/securearmoury) "aeu" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/decal/warning_stripes/southeast,/obj/vehicle/secway,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/securearmoury) "aev" = (/obj/structure/rack,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/item/weapon/shield/riot,/obj/item/weapon/shield/riot,/obj/item/weapon/shield/riot,/turf/simulated/floor/plasteel{dir = 8; icon_state = "vault"; tag = "icon-vault (WEST)"},/area/security/securearmoury) "aew" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/carpet,/area/security/hos) @@ -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) @@ -1283,7 +1283,7 @@ "ayI" = (/turf/simulated/floor/plating{icon_state = "panelscorched"},/area/maintenance/fsmaint2) "ayJ" = (/turf/simulated/wall/rust,/area/maintenance/fsmaint2) "ayK" = (/obj/structure/rack,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/fsmaint2) -"ayL" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plating,/area/maintenance/auxsolarport) +"ayL" = (/obj/structure/stool,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "ayM" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/auxsolarport) "ayN" = (/obj/machinery/power/terminal,/obj/machinery/light/small{dir = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/maintenance/auxsolarport) "ayO" = (/obj/structure/stool/bed,/obj/effect/landmark{name = "xeno_spawn"; pixel_x = -1},/turf/simulated/floor/plating,/area/maintenance/fpmaint2) @@ -1316,7 +1316,7 @@ "azp" = (/obj/structure/stool/bed/chair/wood/wings{tag = "icon-wooden_chair_wings (NORTH)"; icon_state = "wooden_chair_wings"; dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/wood,/area/crew_quarters/mrchangs) "azq" = (/obj/structure/stool/bed/chair/wood/wings{tag = "icon-wooden_chair_wings (NORTH)"; icon_state = "wooden_chair_wings"; dir = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/wood,/area/crew_quarters/mrchangs) "azr" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{dir = 2; icon_state = "barber"},/area/civilian/barber) -"azs" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plating,/area/maintenance/auxsolarstarboard) +"azs" = (/obj/structure/stool,/turf/simulated/floor/plating,/area/maintenance/auxsolarport) "azt" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/auxsolarstarboard) "azu" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/terminal,/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/auxsolarstarboard) "azv" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/maintenance/fsmaint2) @@ -1638,7 +1638,7 @@ "aFz" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/wall,/area/crew_quarters/sleep) "aFA" = (/obj/machinery/light{dir = 8},/obj/item/device/radio/intercom{frequency = 1459; name = "station intercom (General)"; pixel_x = -28},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/crew_quarters/sleep) "aFB" = (/obj/machinery/light{dir = 8},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutral"},/area/crew_quarters/fitness) -"aFC" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) +"aFC" = (/obj/structure/stool,/turf/simulated/floor/plating,/area/maintenance/auxsolarstarboard) "aFD" = (/obj/structure/window/reinforced{dir = 8},/obj/effect/landmark/start{name = "Civilian"},/obj/machinery/door/window/westright{dir = 1; name = "Boxing Ring"},/turf/simulated/floor/wood,/area/crew_quarters/fitness) "aFE" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/wood,/area/crew_quarters/fitness) "aFF" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/fitness) @@ -1759,7 +1759,7 @@ "aHQ" = (/obj/structure/table/woodentable,/obj/machinery/media/receiver/boombox,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aHR" = (/obj/structure/table/woodentable,/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aHS" = (/obj/structure/table/woodentable,/obj/item/toy/cards/deck,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) -"aHT" = (/obj/structure/disposalpipe/segment,/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) +"aHT" = (/obj/structure/stool,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aHU" = (/obj/structure/table,/obj/item/weapon/paper/holodeck,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aHV" = (/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/fsmaint2) "aHW" = (/obj/effect/decal/cleanable/cobweb2,/obj/structure/closet/crate,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/fsmaint2) @@ -1877,8 +1877,8 @@ "aKe" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/wall,/area/crew_quarters/sleep) "aKf" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutral"},/area/crew_quarters/fitness) "aKg" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) -"aKh" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) -"aKi" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) +"aKh" = (/obj/structure/disposalpipe/segment,/obj/structure/stool,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) +"aKi" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/stool,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aKj" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0; tag = ""},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aKk" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aKl" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) @@ -2104,9 +2104,9 @@ "aOx" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/maintenance/fsmaint2) "aOy" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/maintenance/fsmaint2) "aOz" = (/obj/machinery/mass_driver{dir = 4; id_tag = "chapelgun"},/obj/machinery/door/window{dir = 8; name = "Mass Driver"; req_access_txt = "22"},/turf/simulated/floor/plating{tag = "icon-warnplate (WEST)"; icon_state = "warnplate"; dir = 8},/area/maintenance/fsmaint2) -"aOA" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plating{tag = "icon-warnplate (EAST)"; icon_state = "warnplate"; dir = 4},/area/maintenance/fsmaint2) +"aOA" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/unary/vent_pump,/turf/simulated/floor/plating{tag = "icon-warnplate (EAST)"; icon_state = "warnplate"; dir = 4},/area/maintenance/fsmaint2) "aOB" = (/obj/machinery/door/poddoor{id_tag = "chapelgun"; name = "Chapel Launcher Door"; protected = 0},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) -"aOC" = (/turf/space,/area/chapel/main) +"aOC" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) "aOD" = (/turf/simulated/shuttle/wall{icon_state = "swall11"; dir = 2},/area/shuttle/arrival/station) "aOE" = (/obj/effect/landmark{name = "HONKsquad"},/obj/structure/closet/walllocker/emerglocker/north,/turf/simulated/shuttle/floor,/area/shuttle/arrival/station) "aOF" = (/turf/simulated/shuttle/floor,/area/shuttle/arrival/station) @@ -2181,7 +2181,7 @@ "aPW" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/chapel/office) "aPX" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/chapel/office) "aPY" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/turf/simulated/wall,/area/chapel/office) -"aPZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/driver_button{id_tag = "chapelgun"; name = "Chapel Mass Driver"; pixel_x = 25},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) +"aPZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/driver_button{id_tag = "chapelgun"; name = "Chapel Mass Driver"; pixel_x = 25},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) "aQa" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/wall,/area/maintenance/fsmaint2) "aQb" = (/turf/simulated/wall,/area/chapel/main) "aQc" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/chapel/main) @@ -2304,7 +2304,7 @@ "aSp" = (/obj/structure/table,/obj/item/weapon/storage/toolbox/electrical,/turf/simulated/floor/plasteel,/area/storage/primary) "aSq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/storage/primary) "aSr" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor/plasteel,/area/storage/primary) -"aSs" = (/obj/structure/stool{pixel_y = 8},/obj/effect/landmark/start{name = "Civilian"},/turf/simulated/floor/plasteel,/area/storage/primary) +"aSs" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/stool,/turf/simulated/floor/plasteel,/area/crew_quarters/fitness) "aSt" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor/plasteel,/area/storage/primary) "aSu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/plasteel,/area/storage/primary) "aSv" = (/obj/structure/table,/obj/item/weapon/weldingtool,/obj/item/weapon/crowbar,/obj/item/stack/packageWrap,/obj/item/stack/packageWrap,/obj/item/stack/packageWrap,/obj/item/stack/packageWrap,/turf/simulated/floor/plasteel,/area/storage/primary) @@ -2366,7 +2366,7 @@ "aTz" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor/wood,/area/library) "aTA" = (/obj/structure/crematorium,/obj/effect/landmark{name = "revenantspawn"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/office) "aTB" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/firealarm{dir = 4; pixel_x = 24},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/office) -"aTC" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) +"aTC" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) "aTD" = (/obj/effect/landmark/start{name = "Chaplain"},/obj/structure/stool/bed/chair,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) "aTE" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin{pixel_x = -2; pixel_y = 5},/obj/item/weapon/storage/fancy/crayons,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) "aTF" = (/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) @@ -2697,7 +2697,7 @@ "aZS" = (/obj/machinery/navbeacon{codes_txt = "patrol;next_patrol=EVA2"; location = "Dorm"},/turf/simulated/floor/plasteel,/area/hallway/primary/central/ne) "aZT" = (/obj/machinery/camera{c_tag = "Bar East"; network = list("SS13")},/obj/machinery/newscaster{pixel_y = 32},/obj/structure/flora/kirbyplants,/turf/simulated/floor/wood,/area/crew_quarters/bar) "aZU" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/crew_quarters/bar) -"aZV" = (/obj/structure/stool{pixel_y = 8},/obj/effect/landmark/start{name = "Bartender"},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/crew_quarters/bar) +"aZV" = (/obj/structure/stool,/obj/effect/landmark/start{name = "Civilian"},/turf/simulated/floor/plasteel,/area/storage/primary) "aZW" = (/obj/machinery/door/window{dir = 4; name = "Bar Door"; req_access_txt = "25"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/crew_quarters/bar) "aZX" = (/turf/simulated/floor/carpet,/area/crew_quarters/bar) "aZY" = (/obj/machinery/computer/security/telescreen/entertainment{pixel_x = 32},/obj/structure/table/woodentable,/obj/item/ashtray/bronze{pixel_x = -1; pixel_y = 1},/turf/simulated/floor/carpet,/area/crew_quarters/bar) @@ -2801,7 +2801,7 @@ "bbS" = (/obj/structure/bookcase{name = "Forbidden Knowledge"},/turf/simulated/floor/plasteel{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/library) "bbT" = (/obj/structure/table/woodentable,/obj/item/device/taperecorder{pixel_y = 0},/obj/item/device/camera{desc = "A one use - polaroid camera. 30 photos left."; name = "Camera"; pictures_left = 30; pixel_x = 0; pixel_y = 0},/turf/simulated/floor/plasteel{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/library) "bbU" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen/invisible,/obj/machinery/camera{c_tag = "Library Study"; dir = 8; network = list("SS13")},/obj/item/stack/tape_roll,/obj/item/weapon/pen/multi,/turf/simulated/floor/plasteel{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/library) -"bbV" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) +"bbV" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) "bbW" = (/turf/simulated/floor/plasteel{dir = 1; icon_state = "chapel"},/area/chapel/main) "bbX" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{dir = 4; icon_state = "chapel"},/area/chapel/main) "bbY" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 1; icon_state = "chapel"},/area/chapel/main) @@ -2844,10 +2844,10 @@ "bcJ" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "bridge blast"; name = "Bridge Blast Doors"; opacity = 0},/obj/effect/spawner/window/reinforced,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating,/area/bridge) "bcK" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/hallway/primary/central/ne) "bcL" = (/turf/simulated/floor/plasteel{tag = "icon-stage_stairs"; icon_state = "stage_stairs"},/area/hallway/primary/central/ne) -"bcM" = (/obj/machinery/computer/security/telescreen/entertainment{pixel_x = -32},/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/wood,/area/crew_quarters/bar) -"bcN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/wood,/area/crew_quarters/bar) -"bcO" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/wood,/area/crew_quarters/bar) -"bcP" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/wood,/area/crew_quarters/bar) +"bcM" = (/obj/structure/stool,/obj/effect/landmark/start{name = "Bartender"},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/crew_quarters/bar) +"bcN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/stool,/turf/simulated/floor/wood,/area/crew_quarters/bar) +"bcO" = (/obj/machinery/computer/security/telescreen/entertainment{pixel_x = -32},/obj/structure/stool,/turf/simulated/floor/wood,/area/crew_quarters/bar) +"bcP" = (/obj/structure/stool,/turf/simulated/floor/wood,/area/crew_quarters/bar) "bcQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/bar) "bcR" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/structure/disposalpipe/segment,/turf/simulated/floor/wood,/area/crew_quarters/bar) "bcS" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/obj/structure/table,/obj/item/weapon/kitchen/knife,/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/kitchen) @@ -3007,7 +3007,7 @@ "bfQ" = (/turf/simulated/floor/plasteel{dir = 1; icon_state = "yellowcorner"},/area/bridge) "bfR" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/floor/plasteel,/area/bridge) "bfS" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/bridge) -"bfT" = (/obj/structure/table/reinforced,/obj/item/device/aicard,/obj/item/device/multitool,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 8},/area/bridge) +"bfT" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/bookcase,/obj/item/weapon/book/manual/sop_engineering,/obj/item/weapon/book/manual/sop_medical,/obj/item/weapon/book/manual/sop_science,/obj/item/weapon/book/manual/sop_security,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_legal,/obj/item/weapon/book/manual/sop_command,/turf/simulated/floor/plasteel{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/lawoffice) "bfU" = (/obj/structure/stool/bed/chair{dir = 1},/obj/machinery/door_control{id = "bridge blast"; name = "Bridge Blast Door Control"; pixel_x = 28; pixel_y = -2; req_access_txt = "19"},/obj/machinery/keycard_auth{pixel_x = 29; pixel_y = 8},/turf/simulated/floor/plasteel,/area/bridge) "bfV" = (/obj/structure/table/reinforced,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 4},/area/bridge) "bfW" = (/turf/simulated/floor/plasteel{dir = 1; icon_state = "greencorner"},/area/bridge) @@ -3057,7 +3057,7 @@ "bgO" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/wall,/area/security/vacantoffice) "bgP" = (/obj/effect/decal/cleanable/generic,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/port) "bgQ" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/structure/closet/wardrobe/white,/turf/simulated/floor/plasteel,/area/crew_quarters/locker) -"bgR" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel,/area/crew_quarters/locker) +"bgR" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/structure/stool,/turf/simulated/floor/wood,/area/crew_quarters/bar) "bgS" = (/obj/structure/table,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/turf/simulated/floor/plasteel,/area/crew_quarters/locker) "bgT" = (/obj/structure/table,/turf/simulated/floor/plasteel,/area/crew_quarters/locker) "bgU" = (/obj/structure/table,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/crew_quarters/locker) @@ -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) @@ -3656,7 +3656,7 @@ "bsp" = (/obj/machinery/camera{c_tag = "Cargo Delivery Office"; dir = 4; network = list("SS13")},/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/telepad_cargo,/turf/simulated/floor/plasteel{dir = 8; icon_state = "brown"},/area/quartermaster/office) "bsq" = (/obj/structure/filingcabinet/filingcabinet,/turf/simulated/floor/plasteel{icon_state = "arrival"; dir = 4},/area/quartermaster/office) "bsr" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/hallway/primary/central/west) -"bss" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/bookcase,/obj/item/weapon/book/manual/sop_engineering,/obj/item/weapon/book/manual/sop_medical,/obj/item/weapon/book/manual/sop_science,/obj/item/weapon/book/manual/sop_security,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_legal,/turf/simulated/floor/plasteel{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/lawoffice) +"bss" = (/obj/structure/table/reinforced,/obj/item/weapon/book/manual/sop_command,/obj/item/device/aicard,/obj/item/device/multitool,/turf/simulated/floor/plasteel{icon_state = "blue"; dir = 8},/area/bridge) "bst" = (/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/structure/table/woodentable,/turf/simulated/floor/carpet,/area/bridge/meeting_room) "bsu" = (/obj/item/weapon/folder/blue,/obj/structure/table/woodentable,/turf/simulated/floor/carpet,/area/bridge/meeting_room) "bsv" = (/obj/machinery/vending/coffee,/turf/simulated/floor/wood,/area/bridge/meeting_room) @@ -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) @@ -4839,7 +4839,7 @@ "bPc" = (/turf/simulated/wall,/area/hallway/primary/central/sw) "bPd" = (/obj/machinery/door/airlock/command{name = "Head of Personnel"; req_access = null; req_access_txt = "57"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plasteel,/area/crew_quarters/heads) "bPe" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall/r_wall,/area/server) -"bPf" = (/obj/machinery/door/airlock/external{aiControlDisabled = 1; hackProof = 1; id_tag = "emergency_home"; name = "Escape Airlock"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) +"bPf" = (/obj/machinery/door/airlock/external{aiControlDisabled = 0; hackProof = 1; id_tag = "emergency_home"; name = "Escape Airlock"},/turf/simulated/floor/plating,/area/hallway/secondary/exit) "bPg" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/engine/gravitygenerator) "bPh" = (/obj/machinery/door/firedoor{dir = 8; name = "Firelock West"},/obj/machinery/door/airlock/engineering{name = "Gravity Generator"; req_access_txt = "0"; req_one_access_txt = "10;30"},/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/engine/gravitygenerator) "bPi" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = -32; pixel_y = 0},/turf/simulated/floor/plasteel,/area/hallway/primary/central/se) @@ -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) @@ -5227,7 +5227,7 @@ "bWA" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/wood,/area/blueshield) "bWB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/wood,/area/blueshield) "bWC" = (/obj/machinery/light{dir = 1},/obj/machinery/power/apc{dir = 4; name = "Blueshield Office APC"; pixel_x = 24; pixel_y = -3},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/wood,/area/blueshield) -"bWD" = (/obj/structure/table,/obj/item/weapon/folder/blue,/obj/item/weapon/stamp/hop,/obj/item/device/eftpos,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/turf/simulated/floor/plasteel,/area/crew_quarters/heads) +"bWD" = (/obj/structure/table,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/storage/fancy/donut_box,/turf/simulated/floor/wood,/area/bridge/meeting_room) "bWE" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor/wood,/area/ntrep) "bWF" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/wood,/area/ntrep) "bWG" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/wood,/area/ntrep) @@ -5544,7 +5544,7 @@ "ccF" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/apmaint) "ccG" = (/obj/machinery/keycard_auth{pixel_x = -24; pixel_y = 0},/obj/machinery/door/window{dir = 1; name = "Desk Door"; req_access_txt = "67"},/turf/simulated/floor/wood,/area/blueshield) "ccH" = (/obj/structure/table/woodentable,/obj/item/ashtray/glass{pixel_x = -4; pixel_y = -4},/obj/item/weapon/lighter/zippo/blue{pixel_x = 7; pixel_y = 4},/turf/simulated/floor/plasteel{icon_state = "bcarpet05"},/area/blueshield) -"ccI" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin,/obj/item/weapon/pen/blue,/obj/item/weapon/folder/blue{pixel_x = 4; pixel_y = 6},/obj/item/weapon/paper/blueshield,/turf/simulated/floor/plasteel{icon_state = "bcarpet05"},/area/blueshield) +"ccI" = (/obj/structure/table/woodentable,/obj/item/weapon/book/manual/security_space_law,/obj/item/weapon/coin/plasma,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_command,/obj/item/device/megaphone,/turf/simulated/floor/wood,/area/crew_quarters/captain) "ccJ" = (/obj/structure/sign/poster/legit{pixel_x = 32},/obj/machinery/photocopier,/turf/simulated/floor/wood,/area/blueshield) "ccK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/wall,/area/ntrep) "ccL" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/photocopier,/turf/simulated/floor/wood,/area/ntrep) @@ -7337,6 +7337,7 @@ "cLe" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLf" = (/obj/structure/closet/crate,/obj/item/clothing/under/color/lightpurple,/obj/item/weapon/spacecash/c200,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLg" = (/obj/effect/spawner/window,/turf/simulated/floor/plating,/area/maintenance/asmaint) +"cLh" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/light_switch{pixel_x = -25},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/chapel/office) "cLi" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/disposalpipe/segment,/obj/structure/cable,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/plating,/area/toxins/xenobiology) "cLj" = (/obj/machinery/door/window/southright{name = "Containment Pen"; req_access_txt = "55"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/engine,/area/toxins/xenobiology) "cLk" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/obj/structure/cable,/turf/simulated/floor/plating,/area/toxins/xenobiology) @@ -8497,7 +8498,7 @@ "dhv" = (/obj/structure/rack,/obj/item/weapon/pneumatic_cannon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/tank/nitrogen,/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) "dhw" = (/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_l"; icon_state = "propulsion_l"},/turf/space,/area/shuttle/vox) "dhx" = (/obj/structure/rack,/obj/item/clothing/accessory/storage/black_vest,/obj/item/clothing/suit/space/vox/pressure,/obj/item/clothing/head/helmet/space/vox/pressure,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) -"dhy" = (/obj/structure/rack,/obj/item/weapon/gun/launcher/spikethrower,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) +"dhy" = (/obj/structure/rack,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) "dhz" = (/obj/structure/rack,/obj/item/clothing/accessory/storage/black_vest,/obj/item/clothing/suit/space/vox/stealth,/obj/item/clothing/head/helmet/space/vox/stealth,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox) "dhA" = (/obj/structure/grille,/obj/structure/shuttle/window{tag = "icon-window5_end (NORTH)"; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; dir = 1},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox) "dhB" = (/obj/structure/grille,/obj/structure/shuttle/window{tag = "icon-window5_end"; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; dir = 2},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox) @@ -8519,7 +8520,7 @@ "dhR" = (/obj/structure/closet/syndicate/suits,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "dhS" = (/obj/effect/landmark{name = "Syndicate-Uplink"; tag = ""},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "dhT" = (/obj/structure/table,/obj/item/device/aicard,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) -"dhU" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) +"dhU" = (/obj/structure/stool,/turf/simulated/floor/plasteel,/area/crew_quarters/locker) "dhV" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/syndicate) "dhW" = (/obj/machinery/door/airlock/external{frequency = 1331; icon_state = "door_locked"; id_tag = "synd_outer"; locked = 0; name = "Ship External Access"; req_access = null; req_access_txt = "150"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "smindicate"; name = "Outer Airlock"; opacity = 0},/obj/machinery/door_control{id = "smindicate"; name = "External Door Control"; pixel_x = -26; pixel_y = -2; req_access_txt = "150"},/obj/docking_port/mobile{dheight = 9; dir = 2; dwidth = 5; height = 22; id = "syndicate"; name = "syndicate infiltrator"; roundstart_move = "syndicate_away"; width = 18},/obj/docking_port/stationary{dheight = 9; dir = 2; dwidth = 5; height = 22; id = "syndicate_nw"; name = "northwest of station"; width = 18},/turf/simulated/shuttle/plating,/area/shuttle/syndicate) "dhX" = (/turf/space,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/syndicate) @@ -8536,6 +8537,7 @@ "dii" = (/obj/docking_port/stationary{dir = 2; dwidth = 2; height = 18; id = "skipjack_nw"; name = "northwest of SS13"; width = 19},/turf/space,/area/space) "dij" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"; name = "Equipment Room"; req_access_txt = "150"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "dik" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1331; id_tag = "synd_pump"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) +"dil" = (/obj/machinery/hologram/holopad,/obj/machinery/light_switch{pixel_x = 0; pixel_y = 28},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/chapel/main) "dim" = (/obj/structure/rack,/obj/item/clothing/suit/space/syndicate/black/red,/obj/item/clothing/head/helmet/space/syndicate/black/red,/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1331; id_tag = "synd_pump"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "din" = (/obj/item/device/radio/intercom/syndicate{pixel_x = -28},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "dio" = (/obj/docking_port/stationary{dheight = 9; dir = 2; dwidth = 5; height = 22; id = "syndicate_ne"; name = "northeast of station"; width = 18},/turf/space,/area/space) @@ -8563,6 +8565,7 @@ "diK" = (/obj/structure/table,/obj/item/weapon/gun/syringe,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "diL" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "diM" = (/obj/machinery/door/window{dir = 1; name = "Secure Storage"; req_access_txt = "150"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) +"diN" = (/obj/structure/table,/obj/item/weapon/folder/blue,/obj/item/weapon/stamp/hop,/obj/item/device/eftpos,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_command,/turf/simulated/floor/plasteel,/area/crew_quarters/heads) "diO" = (/obj/structure/table,/obj/item/weapon/grenade/syndieminibomb{pixel_x = 4; pixel_y = 2; pixel_z = 0},/obj/item/weapon/grenade/syndieminibomb{pixel_x = -1},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "diP" = (/obj/structure/mirror{pixel_x = 28},/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) "diQ" = (/obj/machinery/telecomms/allinone{intercept = 1},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate) @@ -8732,13 +8735,67 @@ "dlY" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/regular{pixel_x = -2; pixel_y = 4},/obj/item/weapon/book/manual/sop_engineering,/turf/simulated/floor/plasteel,/area/engine/break_room) "dlZ" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/book/manual/sop_science,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/xenobiology) "dma" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/table/reinforced,/obj/item/weapon/clipboard,/obj/item/weapon/folder/yellow,/obj/item/weapon/stamp/ce,/obj/item/weapon/book/manual/sop_engineering,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) -"dmb" = (/obj/item/weapon/storage/fancy/donut_box,/obj/structure/table,/obj/item/weapon/book/manual/sop_general,/turf/simulated/floor/wood,/area/bridge/meeting_room) -"dmc" = (/obj/structure/table/woodentable,/obj/item/weapon/book/manual/security_space_law,/obj/item/weapon/coin/plasma,/obj/item/device/megaphone,/obj/item/weapon/book/manual/sop_general,/turf/simulated/floor/wood,/area/crew_quarters/captain) -"dmd" = (/obj/machinery/light{dir = 1},/obj/structure/bookcase,/obj/item/weapon/book/manual/sop_engineering,/obj/item/weapon/book/manual/sop_medical,/obj/item/weapon/book/manual/sop_science,/obj/item/weapon/book/manual/sop_security,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_legal,/turf/simulated/floor/wood,/area/ntrep) +"dmb" = (/obj/machinery/light{dir = 1},/obj/structure/bookcase,/obj/item/weapon/book/manual/sop_engineering,/obj/item/weapon/book/manual/sop_medical,/obj/item/weapon/book/manual/sop_science,/obj/item/weapon/book/manual/sop_security,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_legal,/obj/item/weapon/book/manual/sop_command,/turf/simulated/floor/wood,/area/ntrep) +"dmc" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin,/obj/item/weapon/pen/blue,/obj/item/weapon/folder/blue{pixel_x = 4; pixel_y = 6},/obj/item/weapon/paper/blueshield,/obj/item/weapon/book/manual/sop_command,/turf/simulated/floor/plasteel{icon_state = "bcarpet05"},/area/blueshield) +"dmd" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/trade/sol) "dme" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) "dmf" = (/obj/machinery/door/firedoor{dir = 8; name = "Firelock West"},/obj/machinery/door/airlock/glass_engineering{name = "Mechanic Workshop"; req_access_txt = "70"; req_one_access_txt = "0"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) "dmg" = (/obj/item/device/radio/intercom{pixel_y = -30},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/small,/obj/structure/stool/bed/chair/wood/wings{tag = "icon-wooden_chair_wings (WEST)"; icon_state = "wooden_chair_wings"; dir = 8},/turf/simulated/floor/wood,/area/crew_quarters/bar) "dmh" = (/obj/machinery/camera{c_tag = "Bar South"; dir = 1; network = list("SS13")},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/gameboard,/turf/simulated/floor/wood,/area/crew_quarters/bar) +"dmi" = (/turf/simulated/shuttle/wall{icon_state = "swall_s6"; dir = 2},/area/shuttle/trade/sol) +"dmj" = (/turf/simulated/shuttle/wall{icon_state = "swall14"; dir = 2},/area/shuttle/trade/sol) +"dmk" = (/obj/machinery/door/airlock/external{frequency = 1450; icon_state = "door_locked"; id_tag = "trade_sol_outer"; locked = 1; name = "External Access"; req_access = null; req_access_txt = "160"},/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dml" = (/obj/structure/window/full/shuttle,/obj/structure/grille,/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dmm" = (/obj/structure/grille,/obj/structure/shuttle/window,/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dmn" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f10"; dir = 2},/area/shuttle/trade/sol) +"dmo" = (/obj/structure/shuttle/engine/heater{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/shuttle/trade/sol) +"dmp" = (/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"; dir = 4},/turf/space,/area/shuttle/trade/sol) +"dmq" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/turf/simulated/shuttle/wall{icon_state = "swall3"; dir = 2},/area/shuttle/trade/sol) +"dmr" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1450; id_tag = "trade_sol_pump"; req_access_txt = "160"; req_one_access_txt = "0"},/obj/machinery/airlock_sensor{frequency = 1450; id_tag = "trade_sol_sensor"; pixel_x = 25; pixel_y = 12},/obj/machinery/embedded_controller/radio/airlock/airlock_controller{frequency = 1450; id_tag = "trade_sol"; pixel_x = 25; req_access_txt = "160"; tag_airpump = "trade_sol_pump"; tag_chamber_sensor = "trade_sol_sensor"; tag_exterior_door = "trade_sol_outer"; tag_interior_door = "trade_sol_inner"},/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dms" = (/obj/structure/closet/crate,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmt" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 8},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmu" = (/obj/machinery/light/spot{tag = "icon-tube1 (NORTH)"; icon_state = "tube1"; dir = 1},/obj/machinery/computer/shuttle/trade/sol,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmv" = (/obj/structure/stool/bed/chair,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmw" = (/obj/structure/shuttle/window,/obj/structure/grille,/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dmx" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion"; dir = 4},/turf/space,/area/shuttle/trade/sol) +"dmy" = (/turf/simulated/shuttle/wall{icon_state = "swallc4"},/area/shuttle/trade/sol) +"dmz" = (/obj/machinery/door/airlock/external{frequency = 1450; icon_state = "door_locked"; id_tag = "trade_sol_inner"; locked = 1; name = "External Access"; req_access = null; req_access_txt = "160"},/turf/simulated/shuttle/plating,/area/shuttle/trade/sol) +"dmA" = (/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmB" = (/obj/machinery/door/airlock/shuttle{id_tag = "s_docking_airlock"; req_access_txt = "160"},/obj/docking_port/mobile{dir = 8; dwidth = 2; height = 11; id = "trade_sol"; name = "sol trade shuttle"; roundstart_move = "trade_sol_base"; width = 5},/obj/docking_port/stationary{dir = 8; dwidth = 2; height = 11; id = "trade_sol_offstation"; lock_shuttle_doors = 1; name = "northwest of Cyberiad"; width = 5},/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmC" = (/obj/structure/shuttle/engine/propulsion{icon_state = "burst_r"; dir = 4},/turf/space,/area/shuttle/trade/sol) +"dmD" = (/obj/machinery/light/spot,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmE" = (/obj/machinery/access_button{command = "cycle_interior"; frequency = 1450; master_tag = "trade_sol"; name = "interior access button"; pixel_x = 25; pixel_y = 25; req_access_txt = "160"},/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmF" = (/obj/structure/stool/bed/chair{dir = 1},/obj/machinery/light/spot,/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmG" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/trade/sol) +"dmH" = (/turf/simulated/shuttle/wall{icon_state = "swall_s5"; dir = 2},/area/shuttle/trade/sol) +"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 @@ -8788,13 +8845,13 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhNcaVdhObFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdhPaafaafaafaafbFldhNcaVdhOdhQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikaalaalaalaalaalaalaalaamaanaaoaapaalaalaalaalbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhRcaVcaVdhSbFldhNcaVdhObFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaaqaaraasaataauaaybnHbnIaavaayaazaaAaaBaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhRcaVdhUdhTbFldhNcaVdhObFlaafdhWdhVdhXbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaaCaaDaaEaaFaayaayaawaaGaaHaayaazaazaaIaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhRcaVayLdhTbFldhNcaVdhObFlaafdhWdhVdhXbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaaCaaDaaEaaFaayaayaawaaGaaHaayaazaazaaIaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhYcaVcaVdhZbFldiacaVcczdicdibdibdibbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaaqaayaaKaaLaaMaayaaNaaOaavaaPaataataalaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhRcaVcaVcaVdidcaVcaVdiedigdifdifdihbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdiibikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaataataataaQaaRaaSaawaaGaaHaaxaaTaaUaaVaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldhRcaVcaVcaVdijcaVcaVcaVaVUdikdikdimbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalaaWaaXaaYaaZabaabbabcabdabeabfabgabhabhaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdhPaafaafaafaafaafaafdincaVcaVaafaafaafaafaafaafdhXbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalabiabjabkablabmabnaboabpabqabraatabsabtaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdiobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldipdipdiqdisdirbFlditcaVcaVbFldiudiwdivdiydixbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikaalabuaalabvabwabxabxaalaalabyaaoaalaalabzaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFlcaVcaVcaVdhUcaVdizcaVcaVcaVdiAcaVdhUcaVdhUdiBbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalabBaatabCabDabEabFbikbikbikbikbikaalabGaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikabAcQScJadgjbikbikbikabAbikbikbikdgjbikbikbikabAdiCdgldgjbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFlcaVcaVcaVayLcaVdizcaVcaVcaVdiAcaVayLcaVayLdiBbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalabBaatabCabDabEabFbikbikbikbikbikaalabGaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikabAcQScJadgjbikbikbikabAbikbikbikdgjbikbikbikabAdiCdgldgjbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldiDdiEcaVcaVcaVdiFcaVcaVcaVdiGcaVcaVcaVcaVdiHbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalabBaatabCabHaalbikbikbikbikbikbikaalaalaalbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdgmdgodgndgmbikbikabAdgmdgpdgrdgqdgmdgjbikbikdgmdgsdgtdgmbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFldiIdiEcaVdiKdiJbFldiLdiMdiLbFlaWldiOcaVcaVcaVbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikaalaalaalaalabuaatabIabJaalaalaalaalbikbikbikabKabLabLabKbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdgmdgvdgudgmbikabAdgwdgydgxdgAdgzdgydgwdgjbikdgmdgBdgCdgmbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbFlcaVcaVdiPbFlaafbFlcaVdiRdiQbFlaafbFlcaVcaVcaVbFlbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaalabMabNabOabPabQabRabSabTabUabVaalbikbikbikbikabKabLabWabKbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdgmdgEdgDdgFbikdgHdgGdgydgydgIdgydgydgGdgJbikdgLdgKdgMdgmbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8815,62 +8872,62 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaeAafyafAafyaeAafyafAafyaeAbikagSahCahDahEahFahGahHahIahJahKahLahMahNagvahOahRahQairahSahTahUahVahWahXahYahZahUaiaaibaicaidahYahZahUahUahAadaadaadaadaadaaieaieaieahAbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikagQaabaabaabahBaabaabaabagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGacGafxacGacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaeAafyafyafAaeAafyafyafAaeAbikagSaifaigaihagSaiiaijaikailaimainaioaipagvaiqaisahhamuaitaiuahUaivaiwaixaiyaizaiAaiBaiCaiDaiEaiFaiGbOIaiHahAaieaieaieaieaieaieaieaieahAbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikagQbikbikbikaiIbikbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikaabbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaeAafAafyaiJaeAafAafyaiKaeAbikagSaiLaiMaiNagSaiOaiOaiOaiOaiPaiQaiRaiSagvaiTaiUaiVaiWaiXaiYahUaiZajaajbajcajdajeajfajgaiDaiEajhaiGajhajiahAaieaieaieaieaieaieaieaieahAagQagQajjaabagQagQagQagQagQagQagQagQagQagQagQagQagQagQaabaabajkajlajmaabaabagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabajnaabafxbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikaeAajoajpajqajrajoajpajqajsajtajuajuajuajuajuajuajuajuajvajwajxajyajzajAajBajCajDajEajFajGahUajHajIajJajKajdajeajKajgajLaiEaiCaiCajMajNajOaieaieaieaieaieaieaieaieahAaabaabaabaabaabaabbikaabbikaabaabaabaabaabaabaabaabbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGacGacGafxafxaabaabbikajQbikaabaabafxafxacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikaeAajRajSajTafyajUajVajWakcajtajYajZakaakbaknakdakdajuakeakfakgakhakiajBakjakkaklakmalJajFakoakpamwakqajKakraksaktakuakvakwakxakxakzaiCakAaieaieaieaieaieaieaieaieahAaabakBakCakCakCakDakCakCakCakCakDakCakCakCakCakEaabbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikbikaabbikaabbikbikajQbikbikaabbikaabbikbikacGbikbikbikbikbikbikbikbikbikbikbikbikaeAakFafyakGakHakIakJakKakLajtakMakNakOakOakPakQakRajuakSakTakUakVakiakWakXakYakZalaalbalcaldaleaAEalfalgalhalialjalkallalmaiCaiCaiCalnajOaieaieaieaieaieaieaieaieahAaabaloaabaabaabaloaabbikbikaabaloaabaabbikbikaloaabbikaabaabajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGaabalpalpalpalpalpbikalqbikalpalpalpalpalpaabacGbikbikbikbikbikbikbikbikbikbikbikbikaeAalralsakGafyaltakJalualvajtalwalxalyalzakQakQakRajualAalBalCalDalEajBalFalGaklalHalIajFajXalKalLalLalMajdalNalOalPalQaiCaiFaiGaiCalRahAahAahAahAahAahAahAahAahAahAaabaloaabbikajkajlajmbikbikajkajlajmbikbikajkajlajmaabaabbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamaalZaowanxambbikbikbikamcaeAaeAaeAamdamdameamfamgamdajuamhamiamjamkamlammamnajuamoampamqakVamrajGamsamtaXNamvaYjajGamxamyamzamAamBamCamDamEamFamGaiCajhamHamIamJahAamKamKamKamKamKbikbikbikbikaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmidmddmkdmjdmldmddmddmmdmddmddmnbikbikbikbikbikbikbikbikbikafxaabajnaabafxbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikaeAajoajpajqajrajoajpajqajsajtajuajuajuajuajuajuajuajuajvajwajxajyajzajAajBajCajDajEajFajGahUajHajIajJajKajdajeajKajgajLaiEaiCaiCajMajNajOaieaieaieaieaieaieaieaieahAaabaabaabaabaabaabbikaabbikaabaabaabaabaabaabaabaabbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmpdmodmrdmqdmtdmsdmsdmsdmvdmudmwbikbikbikacGacGacGafxafxaabaabbikajQbikaabaabafxafxacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikaeAajRajSajTafyajUajVajWakcajtajYajZakaakbaknakdakdajuakeakfakgakhakiajBakjakkaklakmalJajFakoakpamwakqajKakraksaktakuakvakwakxakxakzaiCakAaieaieaieaieaieaieaieaieahAaabakBakCakCakCakDakCakCakCakCakDakCakCakCakCakEaabbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmxdmodmzdmydmsdmAdmAdmAdmAdmAdmBbikbikbikacGbikbikaabbikaabbikbikajQbikbikaabbikaabbikbikacGbikbikbikbikbikbikbikbikbikbikbikbikaeAakFafyakGakHakIakJakKakLajtakMakNakOakOakPakQakRajuakSakTakUakVakiakWakXakYakZalaalbalcaldaleaAEalfalgalhalialjalkallalmaiCaiCaiCalnajOaieaieaieaieaieaieaieaieahAaabaloaabaabaabaloaabbikbikaabaloaabaabbikbikaloaabbikaabaabajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmCdmodmEdmDdmAdmAdmAdmAdmGdmFdmwbikbikbikacGaabalpalpalpalpalpbikalqbikalpalpalpalpalpaabacGbikbikbikbikbikbikbikbikbikbikbikbikaeAalralsakGafyaltakJalualvajtalwalxalyalzakQakQakRajualAalBalCalDalEajBalFalGaklalHalIajFajXalKalLalLalMajdalNalOalPalQaiCaiFaiGaiCalRahAahAahAahAahAahAahAahAahAahAaabaloaabbikajkajlajmbikbikajkajlajmbikbikajkajlajmaabaabbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmHdmddmddmddmldmddmddmmdmddmddmIbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamaalZaowanxambbikbikbikamcaeAaeAaeAamdamdameamfamgamdajuamhamiamjamkamlammamnajuamoampamqakVamrajGamsamtaXNamvaYjajGamxamyamzamAamBamCamDamEamFamGaiCajhamHamIamJahAamKamKamKamKamKbikbikbikbikaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGaabamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikamOamNamQamPamOamRamSamSamTamUamVamWamXamYamZanaanbancajuajuandaneajuajuajuajuajuanfanganhanianfajGajBajCanjajEajFajGankanlanmannahUahUahUahUannanoanpanmahUahAayjahAanrantansansanubikbikbikbikbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikaabbikbikbikaEEanwanzanyanBanAanDanCanAanGanGanHanIanJanKanLanManNanOanPanQanRanSanTanSanSanUanVanWanXanYanSanZaoaaobaocaodaoeaofaogaohanSaoiaojaokaolaomaonaooaopaoqaoraosaplaotaovaEHaouaoyaoxbikbikbikbikbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikajkajPajmbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOanEaoAanFamOamRamSamSamSaoBaoHaoIaoJaoKaoLaoMaoNaoOaoPaoQaoRaoSaoTaoUaoVaoWaoXaoYaoWaoZapaaoTapbapcapdaoTaoTapdaoXapcapeaoTaoTapbapcaoVapfapgaphapiapjapkaplapmapnaovaozansansapobikaacapqaacbikaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikaabaabajkajPajmaabaabagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikajjbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamOaoCaoCaoDamObikbikbikapwapwapxapyapzapAapAapAapBapBapBapBapCapDapEapEapEapFapGapHapFapEapEapEapIapJapKapLapMapKapNapJapOapOapOapPapQapOapRapSapTapUapVapWapXapmapnapYapYamKapZapZapZamKaqaamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmaabaabbikaabaiIaabbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGaqbamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikaEEaoEaoCaoFamOamRamSamSamSaqgaqhaqiaqjaqkaqlaqmapBaqnaqoaqpaqqaqraqsaqtaquaqvaqwaqxaqyaqzaqAaqsaqBaqCaqDaqEaqFaqGaqHaqCapOaqIaqJaqKaqLapOaqMaqNaqOaqPaqQaqRapXapmaqSaqTaqUaqVaqWaqWaqXamKaqYamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikaabaloaabbikbikaqZbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikacGbikbikbikamOaoGaoCaoCaptanAapuanCanAapvanLarharianGanGarjapBarkarlarmarnaroarparqarrarsartaruarvarrarwarxaryarzarAarBarCarDarEarFarGarHarIarJarKapOarLarMarMarNarMarOapXapmaovaovaovaovarPaovarQarRarSamKakBarTakEbikbikaiIaabaabaabaabaiIaabaabaabaabaiIaabaabaabaabarUarVakEaabbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOaqcaqcaqcamOamRamSamSamSarXarYaoMarZasaanGasbapBascasdaseasfasgashasiasjaskaslasmasnasoaspashasqarFasrassastasrarEasuapOarGaswasxasyapOaszasAarMarNarMasBapXasCasDasEasFasEasGasHamKamKapnamKaloasIasJakCakCarTakCakCakCakCarTakCakCakCakCarTakCakCakCasKasLasIaloaabbikagQaabbikbikbikbikbikbikbikbikbikbikaabbikaabbikasMasMasNasNasNasNasNasNasMasMaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikaqeaqdaqdaqdaqfbikbikbikapwapwapwapwapwasSanGasTasUapBatRapBasVasWapEapEatSapEasXasYapEatSapEasZataatbatcatdateatfatgathapOatiatjatkatlatmatnatoatpatqarMatrapXatsattatuatvatwatxatyatzatAatBamKatCarTatDaabaabbikaabbikbikbikbikbikbikbikbikaabaabaabaabaabatEatFatDaabaabaabaabaabbikbikbikbikbikbikbikbikbikaabbikaabasMasMatGatHatIatJatKatLatMatIasMasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikaabatNamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwatOanGasTasUatPatUatTauyatVaqsatQauJauEavxauTavEavBatWaqsatXatYatZauaaubaubaucaudapOaueaufaugauhapOauiaujaukarNarMaulapXatsarPattattattaumaovaunauoaupamKbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikaabaabaabaabauqaabaabbikbikaabaabaabbikbikbikbikbikbikbikbikasMasMasMasMauratJausatJausautatJatJatJauuasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGbikbikaabbikaabbikbikauvbikbikaabbikaabbikbikacGbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikapwauwanGauxasUarkavJauzauAauBauCauDdlLauFauGauHauIdlMauKauLauMauNauNauOauNauNauPauQauRauSdlNapOauUapOauVauWauXauYauZavaapXatsavbavcavcavcavdaveavfavgavhamKbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabbikbikbikaabaabaabaviaabaabbikbikaabbikaabaabbikbikbikbikbikbikbikasMavjavkavlavmavnavoavpatJatJavqavratJavsasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikacGacGacGaabaabaabaabavtavuavtaabaabaabaabacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwavvanGavwasUdlPdlQavyavzavAashdlRdlSashavCavDashdlTdlUashavFavGavHavGavGavHavGavIapOatidlVapOavKapOavLavMavNavOavPavQavRavSavTavUavUavUavVavWavXavYavYavYbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikaabaabavZawaavZaabaabbikaabbikbikaabaabbikbikbikbikbikbikasMawbawcawdaweawfawgatJatJatJawhawiatJawjasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikaahbikbikbikbikaabbikaabbikbikaabbikavtawkawlbikbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmapwapwawnapwasUasUasUawoawpawqawrawrawsawrawsawrawrawtasZasZasvawvawwawuawvawwawuawyawzawzawzawzawzapOawAawBawCawCawDawCawEawFavUawGawHawIavVawJawKawLawMavWbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikaabbikavZawNavZbikaabbikaabbikbikbikaabaabbikbikbikbikbikasMawOawPavlawQawRawSawTatJawUawVawWawXasMawYaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsapsapsbikbikbikbikbikbikaabbikaabbikbikaabavtavtawZaxaavtbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxbaxcaxdaxeaxfaxgaxhaxiaxhaxjaxhaxhaxkaxlaxlaxlaxlaxlaxmaxnaxoaxlaxlaxlaxlaxpaxlaxlaxlaxlaxqaxraxsaxtaxuaxvaxwaxxapWaxyaxzaxAaxBaxCaxDaxEaxFavUaxGaxHaxIavVaxKaxLaxJaAZavWbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikaabavZavZaxMavZavZaabbikaabbikbikbikbikaabaabbikbikbikbikasMaxNaxOavlasMavlavlaxPaxQasMasMasMasMasMasMaabaabbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsapsapsbikbikbikbikbikbikaabaabbikaabbikbikaabaxRaxSaxTaxUaxRaxVaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxWaxXaxYaxZayaaybaycaydayeayfaxqaxqaygaxqaxqaxqaxqaxqayhaxqaxqaxqaxqaxqaxqayiaxqaxqaxqaxqaSWaxqaykaxqaylaxqaymaynapWayoaypayqayraysaytaxEayuavUayvaywayxayyayzayAayBawMavWbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikaabayCayDayEayFayCaabbikaabbikbikaabbikbikaabaabbikbikayGasMavlasMavlayHayIayHayJayHayHayHayKayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaxVaxVaxVaxVaxVaabaabaxRayLayMayNaxRayOaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmayPayQayRaySayTawmayUayVayWayXayYayZazaazbazcayXayXayXazdayXayXayXayXayXayXazeazfazgazgazgazhaziazjaziazkazlazmaznapWazoazoazoazoazoazoaxEaxFavUazpaxHazqavVcscazraxJcvYavWbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikaabayCazsaztazuayCaabbikaabbikbikaabbikbikayGazvayGazvayGayKayHayHayHayHayHayHayHayHayHazwazxayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapsdmMdmLdmOdmNbikbikbikbikbikbikajjbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikamOaoCaoCaoDamObikbikbikapwapwapxapyapzapAapAapAapBapBapBapBapCapDapEapEapEapFapGapHapFapEapEapEapIapJapKapLapMapKapNapJapOapOapOapPapQapOapRapSapTapUapVapWapXapmapnapYapYamKapZapZapZamKaqaamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmaabaabbikaabaiIaabbikbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmQdmQdmQdmPbikbikbikbikbikbikacGaqbamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikaEEaoEaoCaoFamOamRamSamSamSaqgaqhaqiaqjaqkaqlaqmapBaqnaqoaqpaqqaqraqsaqtaquaqvaqwaqxaqyaqzaqAaqsaqBaqCaqDaqEaqFaqGaqHaqCapOaqIaqJaqKaqLapOaqMaqNaqOaqPaqQaqRapXapmaqSaqTaqUaqVaqWaqWaqXamKaqYamKaabaloaabbikajkajPajmbikbikajkajPajmbikbikajkajPajmbikbikbikaabaloaabbikbikaqZbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmRdmRdmRdmPbikbikbikbikbikbikacGbikbikbikaabbikbikbikanvbikbikbikaabbikbikbikacGbikbikbikamOaoGaoCaoCaptanAapuanCanAapvanLarharianGanGarjapBarkarlarmarnaroarparqarrarsartaruarvarrarwarxaryarzarAarBarCarDarEarFarGarHarIarJarKapOarLarMarMarNarMarOapXapmaovaovaovaovarPaovarQarRarSamKakBarTakEbikbikaiIaabaabaabaabaiIaabaabaabaabaiIaabaabaabaabarUarVakEaabbikagQbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmTdmSdmUdmPbikbikbikbikbikbikacGaabalpalpalpalpalpbikamMbikalpalpalpalpalpaabacGbikbikbikamOaqcaqcaqcamOamRamSamSamSarXarYaoMarZasaanGasbapBascasdaseasfasgashasiasjaskaslasmasnasoaspashasqarFasrassastasrarEasuapOarGaswasxasyapOaszasAarMarNarMasBapXasCasDasEasFasEasGasHamKamKapnamKaloasIasJakCakCarTakCakCakCakCarTakCakCakCakCarTakCakCakCasKasLasIaloaabbikagQaabbikbikbikbikbikbikbikbikbikbikaabbikaabbikasMasMasNasNasNasNasNasNasMasMaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmVdmSdmUdmPbikbikbikbikbikbikacGbikalSalTalTalTalTalUalValWalXalXalXalXalYbikacGbikbikbikaqeaqdaqdaqdaqfbikbikbikapwapwapwapwapwasSanGasTasUapBatRapBasVasWapEapEatSapEasXasYapEatSapEasZataatbatcatdateatfatgathapOatiatjatkatlatmatnatoatpatqarMatrapXatsattatuatvatwatxatyatzatAatBamKatCarTatDaabaabbikaabbikbikbikbikbikbikbikbikaabaabaabaabaabatEatFatDaabaabaabaabaabbikbikbikbikbikbikbikbikbikaabbikaabasMasMatGatHatIatJatKatLatMatIasMasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmVdmSdmUdmPbikbikbikbikbikbikaabatNamLamLamLamLamLbikamMbikamLamLamLamLamLaabacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwatOanGasTasUatPatUatTauyatVaqsatQauJauEavxauTavEavBatWaqsatXatYatZauaaubaubaucaudapOaueaufaugauhapOauiaujaukarNarMaulapXatsarPattattattaumaovaunauoaupamKbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikaabaabaabaabauqaabaabbikbikaabaabaabbikbikbikbikbikbikbikbikasMasMasMasMauratJausatJausautatJatJatJauuasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmSdmSdmSdmWbikbikbikbikbikbikacGbikbikaabbikaabbikbikauvbikbikaabbikaabbikbikacGbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikapwauwanGauxasUarkavJauzauAauBauCauDdlLauFauGauHauIdlMauKauLauMauNauNauOauNauNauPauQauRauSdlNapOauUapOauVauWauXauYauZavaapXatsavbavcavcavcavdaveavfavgavhamKbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabbikbikbikaabaabaabaviaabaabbikbikaabbikaabaabbikbikbikbikbikbikbikasMavjavkavlavmavnavoavpatJatJavqavratJavsasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmXdmSdmSdmYbikbikbikbikbikbikacGacGacGaabaabaabaabavtavuavtaabaabaabaabacGacGacGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikapwavvanGavwasUdlPdlQavyavzavAashdlRdlSashavCavDashdlTdlUashavFavGavHavGavGavHavGavIapOatidlVapOavKapOavLavMavNavOavPavQavRavSavTavUavUavUavVavWavXavYavYavYbikbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikaabaabavZawaavZaabaabbikaabbikbikaabaabbikbikbikbikbikbikasMawbawcawdaweawfawgatJatJatJawhawiatJawjasMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmPdmZdmSdnadmPbikaahbikbikbikbikaabbikaabbikbikaabbikavtawkawlbikbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmapwapwawnapwasUasUasUawoawpawqawrawrawsawrawsawrawrawtasZasZasvawvawwawuawvawwawuawyawzawzawzawzawzapOawAawBawCawCawDawCawEawFavUawGawHawIavVawJawKawLawMavWbikbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikaabbikavZawNavZbikaabbikaabbikbikbikaabaabbikbikbikbikbikasMawOawPavlawQawRawSawTatJawUawVawWawXasMawYaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdnbdnddncdnddnebikbikbikbikbikbikaabbikaabbikbikaabavtavtawZaxaavtbikaabbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxbaxcaxdaxeaxfaxgaxhaxiaxhaxjaxhaxhaxkaxlaxlaxlaxlaxlaxmaxnaxoaxlaxlaxlaxlaxpaxlaxlaxlaxlaxqaxraxsaxtaxuaxvaxwaxxapWaxyaxzaxAaxBaxCaxDaxEaxFavUaxGaxHaxIavVaxKaxLaxJaAZavWbikbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikaabavZavZaxMavZavZaabbikaabbikbikbikbikaabaabbikbikbikbikasMaxNaxOavlasMavlavlaxPaxQasMasMasMasMasMasMaabaabbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdnbdnfdnebikbikbikbikbikbikaabaabbikaabbikbikaabaxRaxSaxTaxUaxRaxVaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmaxWaxXaxYaxZayaaybaycaydayeayfaxqaxqaygaxqaxqaxqaxqaxqayhaxqaxqaxqaxqaxqaxqayiaxqaxqaxqaxqaSWaxqaykaxqaylaxqaymaynapWayoaypayqayraysaytaxEayuavUayvaywayxayyayzayAayBawMavWbikbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikaabayCayDayEayFayCaabbikaabbikbikaabbikbikaabaabbikbikayGasMavlasMavlayHayIayHayJayHayHayHayKayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikaxVaxVaxVaxVaxVaabaabaxRazsayMayNaxRayOaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmayPayQayRaySayTawmayUayVayWayXayYayZazaazbazcayXayXayXazdayXayXayXayXayXayXazeazfazgazgazgazhaziazjaziazkazlazmaznapWazoazoazoazoazoazoaxEaxFavUazpaxHazqavVcscazraxJcvYavWbikbikbikbikbikbikbikbikaabaabbikbikbikbikbikbikbikbikaabayCaFCaztazuayCaabbikaabbikbikaabbikbikayGazvayGazvayGayKayHayHayHayHayHayHayHayHayHazwazxayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikazyazzazybikbikbikaxVaxVaxVaxVazAazBazCaxVbikbikaxRazDazEazFazGazHaxVbikbikaabbikbikbikbikbikbikbikbikbikbikawmawmawmawmawmawmawmazIazIazJazKazKazLazMazNazOazPazPazOazQazOazRazRazRazRazRazRazSazRazRazTazUazVazWazIazXazIazYazIazIaqVazZaovaovaovaovaAaaxFavUaAbaxHaAcavVaAdayAayBawMavWbikbikbikbikbikbikbikbikaabaabbikbikbikbikazyaAeazybikaabayCaAfaAgaAhayCaAiaAiaAiaAiaAiazvazvazvayGaAjayHazwazxayJayHayJayJayJayGaAkayGayGayGayGayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikaAlaAmaAlbikbikaabaxVaAnaAoaApazHaAqazHaxVaAlaAlaxRaxRaAraAsazGazHaxVaxVaAlaAlaAlaxVaxVbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikazJaAtaAuaAvazMaAwazOaAxaAyaAzaAAaABaACaADbssaAFaAGaAHaAIaAJaAKaALaxqaxraAMaANaAOaAPaAQaAPaAPaAPaARaAPaAPaAPaAPaASaATaAUaAVaAWaAXaAYcNsaBaaUadcuavWaabaBbaBcaBcaBcaBcaBcaBdaabaabbikbikbikbikazvaBeazvbikaAiayCayCaBfaBgayCaBhayHayHayHayJaBiayHaBjayGayHayHayHaBkayJayHayGaBlaBmayGayHaBnayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikaAlaAmaAlbikbikaabaxVaAnaAoaApazHaAqazHaxVaAlaAlaxRaxRaAraAsazGazHaxVaxVaAlaAlaAlaxVaxVbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikazJaAtaAuaAvazMaAwazOaAxaAyaAzaAAaABaACaADbfTaAFaAGaAHaAIaAJaAKaALaxqaxraAMaANaAOaAPaAQaAPaAPaAPaARaAPaAPaAPaAPaASaATaAUaAVaAWaAXaAYcNsaBaaUadcuavWaabaBbaBcaBcaBcaBcaBcaBdaabaabbikbikbikbikazvaBeazvbikaAiayCayCaBfaBgayCaBhayHayHayHayJaBiayHaBjayGayHayHayHaBkayJayHayGaBlaBmayGayHaBnayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikappaBpaBobikaBqaBsaBraabaabaAlazHaAlbikbikaabaxVaBuaBvaBwaBxaByaBzaxVaBAazHaBBaBCaBDaBEaBEaBEaBEaBEaBEaBEaBEaBFaxVbikaBGbikbikbikbikbikbikbikbikbikbikbikbikbikbikaBHaBIaBJaBKazMaAwazOaBLafvaBNaAAaABaBOaBPaBPaBPaBPaBPaAIbjlaAKaxlaxqaxrazIaBQaBRaBSaBTaBSaBSaBUaBVaBWaBWaBWaBWaBWaBWaBXaBYaBZaCaaCbaCcaCdaCeavWavWaCfaCgaChaChaChaChaChaCgaCfaabbikbikbikbikazvaCiaCjbikaAiaCkaClaCmaCnayHayHayHayJayHayJaCoayHayHayGayHaCpaCqaCoaAkayHayGaCraCsayGayHaCtayGbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaCuaBtaCvaBtaCuaCwaCxaCwaCuaabaAlaCzaCAbikbikaxVaxVaxVaxVaxVaCBaCCaCDaCEaCFaCGaCGaCHaCIaCIaCJaCKaxVazHaxVaxVaxVaCLaxVbikaabbikbikbikbikbikbikaabaabaabaabaabaabaabaabaCMaCNaCOaBKazMaAwazOaCPaCQaCRaAAaCSaCTaBPaCUaBPaCVaCVaAIaBPaAKaxlaxqaCWazIaCXaBRaCYaCZaDaaDbaDcaDdaDeaDfaDgaDhaDiaDjaDkaDlaDmaDnaDoaDpaDqaDraDsaDtaCfaCgaChaChaChaChaChaCgaCfaabaabaabaabazvazvaDuaDvazvaAiaDwayHaDxayHayKayHayGayGaDyayGayGaDzayJayJaCoaDAaDBayHayGayHaDCaDCaDCaDCaDCaDCaDCaDCaDCaDDaDDaDDaDDaacaDDaDDaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaDEaBtaCyaBtaDEaCwaDFaCwaDEaxVaAlaDHaDIaAlaAlaxVazHazHazHazHazHazHazHaCBaCLaxVaxVaxVaxVaxVaDJaxVaxVazHaDKaxVaDLaCLaxVaxVaxVbikbikbikbikbikaDMaDMaDMaDMaDMaDMaDMaDMaabaCMaDNaDOaDPaDQaDRaDSaDTaDUaDVaDWaABaDXaBPaDYaDZaEaaEbaEcaEdaAKaxlaxqaxrazIatsaEeaEfaCZaDaaDbaEgaEhaEhaEhaEhaEhaEhaEhaEhaEhaEhaEiaEjaEkaElaEmaEnaEoaEpaCgaChaChaChaChaChaCgaCfaCfaCfbikbikazvayHaEqaEraBhaEsaDAaCoaDxayHaEtayIaEuaAkayHayHayHayHaEvayHayHaDAaEwayHaDzayHaDCaExaEyaEzaDCaEAaEBaECaDCaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaDEaDGcUCaEDaDEaEFddzaEGaEJaEKazHaELaEMaENaDKaEOazHaxVaxVaxVaxVaxVaxVaxVaCLaxVaEPaEQaERaxVaESaETaEUazHaEOaxVaENaEVaBEaBFaEWbikbikbikbikbikaEXaEYaEZaFaaFbaFcaFdaDMaabaCMaFeaFfaFgaCMaFhazOaFiaFjaFkaFlaABaFnaBPaFoaFpaFqaFraFsaFtaFuaFvaydaFwaFxaFyaFzaFAaCZaDaaDbaFBaEhaFCaFCaFCaEhaEhaFDaFEaFEaFFaEiaFGaFHaFIaFIaFJaFKaFLaFMaChaChaChaChaChaFNaFOaFPaFQbikbikazvayHayHaFRayHaEsaFSayHaFTaFUaFUaFUaFUaFVaFUaFWayHayHayHayHayHayHayHayHayJayIaDCaFXaFYaFYaDCaFZaGaaGbaDCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaDEaGcaGdaGeaDEaGcaGdaGeaEJaBzazHaGfazHazHazHazHazHaxVaGgaGhaGiaGjaGkaxVaCLaxVaEQaGlaEPaGmaGnaGoaxVaGpaxVaxVaxVaxVaGpaCLaEWbikazyazyazyazyaGqaEYaGraGsaGtaGuaGvaGwaDMaCMaBHaGxaGxaGxaGyaGzaGAaGzaGzaGzaGBaGCaGDaGEaGFaGFaGFaGFaGGaGHaGIaxqaGJazIatsaGKaGLaCZaDaaDbaEgaFCaGMaGMaGNaFCaEhaGOaGPaGPaGQaGRaFGaGSaGTaGUaGVaEhaGWaFQaChaChaChaChaChaFQaGXaGYaFQaabaabayGayHayHayJayJaEsaGZaGZaAiaAiaAiaEsaEsaEsayGaHaaHbayGayJayJayGayJayJayGayGaHcaHdaHeaHfaHgaHhaHiaFXaHjaDCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaCuaDEaEIaHlaCuaDEaEIaHlaCuaxVaCBaxVaxVaxVaxVaxVazHaxVazHaHnaHoazHazHaxVaCLaxVaHpaabaHpaxVaBvaGoaxVaHqaHraxVaENaBzaxVaAwaDMaDMaHsaHsaHsaHsaHsaHsaHsaHsaHsaGvaGvaGwaHtaHuaHvaHwaHxaHyaHzaHAaHBaHBaHBaHBaHCaHDaHEaHFaHGaHBaHBaHHaHHaHIaHJaHKaHLaHMaHNaGKaHOaHPaHPaDbaEgaFCaHQaHRaHSaFCaEhaGOaGPaGPaGQaHTaFGaGSaGUaGUaGVaEhaGWaFQaChaChaChaChaChaFQaHUaGYaFQbikbikayGaHVayHayHaHWayJaHXazwaHYaHZayKayGaFSayKayGaIaayHayGaIbayHayGaIcaIdaIeaFUaIfaFUaIgaIhaIiaIjaIkaIlaImaDCaDDaDDaacaacaDDaDDaDDaDDaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaIoaIoaIoaIqaIoaIoaIoaIsaItaIuaIuaIuaIuaIvaxVazHaxVaIwaIxaIyazHaIzaGpaCLaxVaxVaxVaxVaxVaxVaGpaxVazHaIyaCBazHazHaGvaIAaIBaICaIDaIDaIDaIDaIEaIDaIDaIFaIGaICaIHaIIaIIaIIaIIaIIaIIaIIaIJaIKaIKaIKaIKaILaIMaIKaINaIKaIOaILaIKaIKaIKaIKaIPaIQaIRaISaITaFzaIUaIVaHPaIWaEgaFCaIXaIYbvsaFCaEhaIZaJaaJaaJbaEiaFGaJcaJdaJdaJeaEhaJfaJgaChaChaChaChaChaJhaJiaJjaFQbikbikayGayHayHayHayHayHayHaIeaFUaFUaFUaFUaFUaFUaFUaCmayHayHayHayHaDzayHayHaDxayHaJkaJlaJmaJnaJoaFYaFYaFYaJpaDCaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaJqaJraJsaJtaJuaJvaJwaJxaJvaJyaJzaJvaJvaJAaxVazHaxVaJBazHazHaJCaJDaxVaEVaBFazHazHazHazHazHazHaGpaJEazHaxVaEKaEKaDMaJFaDMaJGaJHaJIaJIaJIaJJaJIaJIaJIaJKaJGaJLaJMaJMaJMaJMaJMaJMaJMaGvaIKaJNaJOaJPaJQaJRawxaJTaJUaJVaJWaJXaJOaJYaIKaJZaxqaKaazIaKbaGKaKcaKdaKdaKeaKfaKgaKhaKiaKiaKjaKkaKlaKjaKkaKkaKmaKnaKoaEhaEhaKpaEhaKqaKraChaChaChaChaChaKraCfaCfaCfayGayGayGayKayJayJaAkayGayGaDxayJayGaKsayJayGaAkayGaDxaHVayJayGaAkayGayHaHVaDxayHaKtaDCaKuaIhaKvaKwaKxaIhaKyaDCaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaDEaDGcUCaEDaDEaEFddzaEGaEJaEKazHaELaEMaENaDKaEOazHaxVaxVaxVaxVaxVaxVaxVaCLaxVaEPaEQaERaxVaESaETaEUazHaEOaxVaENaEVaBEaBFaEWbikbikbikbikbikaEXaEYaEZaFaaFbaFcaFdaDMaabaCMaFeaFfaFgaCMaFhazOaFiaFjaFkaFlaABaFnaBPaFoaFpaFqaFraFsaFtaFuaFvaydaFwaFxaFyaFzaFAaCZaDaaDbaFBaEhaHTaHTaHTaEhaEhaFDaFEaFEaFFaEiaFGaFHaFIaFIaFJaFKaFLaFMaChaChaChaChaChaFNaFOaFPaFQbikbikazvayHayHaFRayHaEsaFSayHaFTaFUaFUaFUaFUaFVaFUaFWayHayHayHayHayHayHayHayHayJayIaDCaFXaFYaFYaDCaFZaGaaGbaDCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaDEaGcaGdaGeaDEaGcaGdaGeaEJaBzazHaGfazHazHazHazHazHaxVaGgaGhaGiaGjaGkaxVaCLaxVaEQaGlaEPaGmaGnaGoaxVaGpaxVaxVaxVaxVaGpaCLaEWbikazyazyazyazyaGqaEYaGraGsaGtaGuaGvaGwaDMaCMaBHaGxaGxaGxaGyaGzaGAaGzaGzaGzaGBaGCaGDaGEaGFaGFaGFaGFaGGaGHaGIaxqaGJazIatsaGKaGLaCZaDaaDbaEgaHTaGMaGMaGNaHTaEhaGOaGPaGPaGQaGRaFGaGSaGTaGUaGVaEhaGWaFQaChaChaChaChaChaFQaGXaGYaFQaabaabayGayHayHayJayJaEsaGZaGZaAiaAiaAiaEsaEsaEsayGaHaaHbayGayJayJayGayJayJayGayGaHcaHdaHeaHfaHgaHhaHiaFXaHjaDCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbjNaInaCuaDEaEIaHlaCuaDEaEIaHlaCuaxVaCBaxVaxVaxVaxVaxVazHaxVazHaHnaHoazHazHaxVaCLaxVaHpaabaHpaxVaBvaGoaxVaHqaHraxVaENaBzaxVaAwaDMaDMaHsaHsaHsaHsaHsaHsaHsaHsaHsaGvaGvaGwaHtaHuaHvaHwaHxaHyaHzaHAaHBaHBaHBaHBaHCaHDaHEaHFaHGaHBaHBaHHaHHaHIaHJaHKaHLaHMaHNaGKaHOaHPaHPaDbaEgaHTaHQaHRaHSaHTaEhaGOaGPaGPaGQaKhaFGaGSaGUaGUaGVaEhaGWaFQaChaChaChaChaChaFQaHUaGYaFQbikbikayGaHVayHayHaHWayJaHXazwaHYaHZayKayGaFSayKayGaIaayHayGaIbayHayGaIcaIdaIeaFUaIfaFUaIgaIhaIiaIjaIkaIlaImaDCaDDaDDaacaacaDDaDDaDDaDDaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdmJdmKaGddmKaIoaIoaIoaIqaIoaIoaIoaIsaItaIuaIuaIuaIuaIvaxVazHaxVaIwaIxaIyazHaIzaGpaCLaxVaxVaxVaxVaxVaxVaGpaxVazHaIyaCBazHazHaGvaIAaIBaICaIDaIDaIDaIDaIEaIDaIDaIFaIGaICaIHaIIaIIaIIaIIaIIaIIaIIaIJaIKaIKaIKaIKaILaIMaIKaINaIKaIOaILaIKaIKaIKaIKaIPaIQaIRaISaITaFzaIUaIVaHPaIWaEgaHTaIXaIYbvsaHTaEhaIZaJaaJaaJbaEiaFGaJcaJdaJdaJeaEhaJfaJgaChaChaChaChaChaJhaJiaJjaFQbikbikayGayHayHayHayHayHayHaIeaFUaFUaFUaFUaFUaFUaFUaCmayHayHayHayHaDzayHayHaDxayHaJkaJlaJmaJnaJoaFYaFYaFYaJpaDCaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaInaKzaJqaJraJsaJtaJuaJvaJwaJxaJvaJyaJzaJvaJvaJAaxVazHaxVaJBazHazHaJCaJDaxVaEVaBFazHazHazHazHazHazHaGpaJEazHaxVaEKaEKaDMaJFaDMaJGaJHaJIaJIaJIaJJaJIaJIaJIaJKaJGaJLaJMaJMaJMaJMaJMaJMaJMaGvaIKaJNaJOaJPaJQaJRawxaJTaJUaJVaJWaJXaJOaJYaIKaJZaxqaKaazIaKbaGKaKcaKdaKdaKeaKfaKgaSsaKiaKiaKjaKkaKlaKjaKkaKkaKmaKnaKoaEhaEhaKpaEhaKqaKraChaChaChaChaChaKraCfaCfaCfayGayGayGayKayJayJaAkayGayGaDxayJayGaKsayJayGaAkayGaDxaHVayJayGaAkayGayHaHVaDxayHaKtaDCaKuaIhaKvaKwaKxaIhaKyaDCaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaDEaKzaKAaKzaKBaJraJraKCaKzaKAaKzaKDaKEaKFaKGaxVazHaGpaGpaxVaxVaxVaKHaKHaKHazNaKHaKHaKHaKHaKHaGvaDMaDMaDMaDMaDMaDMaDMaJFaKIaJGbikaabbikaabbikaabbikaabbikaJGaJLaJMaKJaKKaKLaKMaKNaJMaGvaIKaKOaKOaKPaKQaKRaKSaKTaKSaKUaKVaKWaKOaKOaIKaJZaxqaKXazIaKbaGKaGLaCZaDaaDbaEgaKYaKZaLaaLbaLcaLcaLdaLeaLcaLeaLfaLgaLhaLiaLjaLkaLlaCfaKraChaChaChaChaChaKrayGaCtayHaLmaLnayJayGayJaCtayHayGaCtaDxayGaLoayHayGaLpayHayJaLqaLrayGaLsayHayJaAkaAkaDxaAkaLtaDCaLuaIhaLvaLwaLvaIhaLxaDCaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaLyaCuaLzaGdaKzaLAaLBaLCaLDaKzaGdaLEaInaCuaLFaLGaxVazHazHazHazHazHazHaKHaLHaLIaLJaLKaLLaLMaLHaKHaLNaLOaIDaIDaIDaIDaIDaIDaLPaLQaJGaabaLRaLRaLRaLRaLRaLRaLRaabaJGaJLaJMaLSaLTaLUaLVaLSaJMaGvaIKaIKaIKaIKaLWaLXaJOaLYaJOaLXaLZaIKaIKaIKaIKaJZaxqaMaazIaKbaGKaFAaCZaDaaDbaFBaMbaMcaMcaMcaMcaMcaMcaMcaMdaMcaMeaMeaMeaMeaMeaMfayGaCfaKraChaChaChaChaChaKrayGayGayHaMgaLnayJaMhayGayHayHayGayHaDxayJayHayHayGayHayHayJaDxayIayGayHayHayJaMiayHaDxayHaMjaMkaMkaDCaDCaDCaDCaDCaDCaDCaDDaDDaDDaDDaDDaabbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaKAaKzaKzaKzaKzaKzaKzaKAaInaMlaCuaMmaMnaMoaMoaMoaMoaMoaMoaMpaKHaLHaMqaLJaMraMqaMqaLHaKHaMsaMtaMuaMuaMuaMuaMuaMuaMuaMuaMvbikaLRaMwaMxaMyaMzaMAaLRbikaJGaJLaJMaMBaMCaMDaMEaLSaJMaGvaIKaMFaMFaKPaMGaMHaKSaKTaKSaMHaMIaMJaKOaKOaIKaJZaxqaKaazIaMKaBRaMLaCZaDaaDbaEgaMbaMcaMMaMNaMOaMOaMcaMPaMQaMRaMeaMSaMTaMUaMeaMVayGbikaMWaMXaMXaMXaMXaMXaMYbikayGayHaMZaNaayJayJayGayGayJayJaNbaNcayJayGazxayGayGayJayJaNdaNeayGayGayGaHYaMiayHaDxayHaMjazwayKaFSayGaNfaNgaNfayGayGayGaabaabaabaabaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaNhaNiaNjaNiaNiaNkaNlaNiaNiaNjaNmaNnaCuaKBaNoaMoaNpaNqaNraNsaNtaNuaKHaLHaMqaLJaNvaMqaMqaLHaKHaNwaNxaNyaNzaNAaNBaNCaNDaNEaNFaMvaabaLRaNGaNHaNIaNJaNKaLRaabaJGaJLaJMaNLaNMaNNaNOaNPaJMaGvaIKaJNaJOaNQaNRaLXaJOaNSaJOaLXaNTaNUaJOaJYaIKaJZaxqaNVazIaKbaEeaEfaCZaDaaDbaNWaNXaMcaNYaMQaMQaMQaNZaOaaObaOcaMeaOdaOeaOfaOgaOhazxbikbikbikbikbikbikbikbikbikayGaOiaOjaOkaOlaOmayGaEtayHaHVaDxayHayGbikayGayHayHayHayHaDxaOnaOoaOpaOpaOpaOpaOqaOraOsaOtaOuaOvaOuaOwaOxaOxaOyaOzaOAaOBaOCaOCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaNhaNmaNiaODaOEaOFaOGaOHaOIaOJaOKaOLaOMaONaOOaKzaKBaOPaMoaOQaORaOSaOTaOSaOUaKHaOVaMqaOWaOXaOYaOXaOZaPaaPbaPcaPdaPdaPdaPdaPdaPdaPeaPfaMvbikaLRaPgaNHaPhaNJaPiaLRbikaJGaJLaJMaPjaPkaPlaPmaPnaJMaGvaIKaPoaPoaKPaPpaMHaKSaPqaKSaMHaPraKWaPsaPsaIKaPtazUaPuazIaKbaEeaPvaPvaPvaPvaPwaPxaPyaPzaPAaPBaPBaPBaPCaPBaPDaPEaPFaPGaPHaPEaPIaPJazxayGayGayGayGayGayGayGayGayGayGayGayGaBMayGayGayGayGayHaDxaOiazvaabazvayHaPLaPMaPNaPOaPPaPQaPRaPRaPRaPRaPSaPTaPUaPVaPWaPXaPWaPYaPWaPWaPZaQaaQbaQbaQcaQdaQeaQeaQeaQeaQeaQeaQeaQeaQeabLadbbikbikbikbikbikbikbikaaabdBaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaONaQgaQhaQiaOMaQjaOFaQjaOFaQjaOFaQjaOMaQkaQlaKzaKBaQmaMoaQnaQoaQpaQqaQraQsaKHaQtaMqaQuaQvaQwaQxaQyaKHaQzaPdaPdaPdaPdaPdaPdaPdaPeaQAaMvaabaLRaQBaQCaQDaQEaQFaLRaabaJGaJLaJMaQGaQHaQIaQJaQKaJMaGvaIKaIKaIKaIKaQLaLXaJOaLYaJOaLXaQMaIKaIKaIKaIKaQNaQOaQPazIaMKaQQaQRaQRaQRaQSaQTaQUaQVaQWaQXaQVaQYaQZaRaaQVaRbaRcaRdaReaRfaMeaRgaRhaRiaRjaRjaRhaRkaRlaRlaRlaRlaRlaRmaRnaRlaRoaRpaRqaRraRsaRvaRuaTkaRwaRxaRwaRyaRzayHayGaRAaRBaRCaRDaREaRFaRGaRHaRIaRJaRIaRKaRLaRMaRNaROaRPaRQaRRaRSaRTaRUaQdaRVaRWaRXaRYaRZaSaaSbaScaSdaprbikbikbikbikbikbikbikaaabfmbifbieaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaSfaOFaOFaNjaOMaQjaOFaQjaSgaQjaOFaQjaOMaQkaQlaKzaKBaShaMoaMoaSiaSjaSkaSjaMoaKHaKHaKHaKHaSlaSmaSnaSoaKHaSpaSqaSraPdaPdaSsaPdaStaSuaSvaMvbikaLRaLRaSwaSxaSwaLRaLRbikaJGaJLaJMaSyaSzaSAaQJaSBaJMaGvaIKaJNaJOaSCaNRaLXaJOaLYaJOaLXaNTaSDaIKaIKaIKaSEaSFaSGaSHaSIaSJamKamKaSKaSLaSMaSNaMcaSOaMQaMcaSPaMcaSQaMcaSRaSSaSTaSUaSVaTeaSXaSYaSZaTaaTbaTcaTdaTbaTbaUjaTbaSYaTfaSYaOvaTgaSYaThaTiaTjaTmaTlaToaTnaTqaTpaWIaTraOuaTsaTtaTuaTvaTwaTxaTyaTzaRHaTAaTBaRIaTCaTDaTEaTFaROaTGaRQaRRaRSaTHaTIaQdaTJaTKaTKaTLaScaScaScaScaSdaprbikbikbikbikbikbikaaabfmbigbijbihbieaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaNhaNiaNjaNiaNiaNkaNlaNiaNiaNjaNmaNnaCuaKBaNoaMoaNpaNqaNraNsaNtaNuaKHaLHaMqaLJaNvaMqaMqaLHaKHaNwaNxaNyaNzaNAaNBaNCaNDaNEaNFaMvaabaLRaNGaNHaNIaNJaNKaLRaabaJGaJLaJMaNLaNMaNNaNOaNPaJMaGvaIKaJNaJOaNQaNRaLXaJOaNSaJOaLXaNTaNUaJOaJYaIKaJZaxqaNVazIaKbaEeaEfaCZaDaaDbaNWaNXaMcaNYaMQaMQaMQaNZaOaaObaOcaMeaOdaOeaOfaOgaOhazxbikbikbikbikbikbikbikbikbikayGaOiaOjaOkaOlaOmayGaEtayHaHVaDxayHayGbikayGayHayHayHayHaDxaOnaOoaOpaOpaOpaOpaOqaOraOsaOtaOuaOvaOuaOwaOxaOxaOyaOzaOAaOBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaNhaNmaNiaODaOEaOFaOGaOHaOIaOJaOKaOLaOMaONaOOaKzaKBaOPaMoaOQaORaOSaOTaOSaOUaKHaOVaMqaOWaOXaOYaOXaOZaPaaPbaPcaPdaPdaPdaPdaPdaPdaPeaPfaMvbikaLRaPgaNHaPhaNJaPiaLRbikaJGaJLaJMaPjaPkaPlaPmaPnaJMaGvaIKaPoaPoaKPaPpaMHaKSaPqaKSaMHaPraKWaPsaPsaIKaPtazUaPuazIaKbaEeaPvaPvaPvaPvaPwaPxaPyaPzaPAaPBaPBaPBaPCaPBaPDaPEaPFaPGaPHaPEaPIaPJazxayGayGayGayGayGayGayGayGayGayGayGayGaBMayGayGayGayGayHaDxaOiazvaabazvayHaPLaPMaPNaPOaPPaPQaPRaPRaPRaPRaPSaPTaPUaPVaPWaPXaPWaPYaPWaPWaPZaQabpqaQbaQcaQdaQeaQeaQeaQeaQeaQeaQeaQeaQeabLadbbikbikbikbikbikbikbikaaabdBaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaONaQgaQhaQiaOMaQjaOFaQjaOFaQjaOFaQjaOMaQkaQlaKzaKBaQmaMoaQnaQoaQpaQqaQraQsaKHaQtaMqaQuaQvaQwaQxaQyaKHaQzaPdaPdaPdaPdaPdaPdaPdaPeaQAaMvaabaLRaQBaQCaQDaQEaQFaLRaabaJGaJLaJMaQGaQHaQIaQJaQKaJMaGvaIKaIKaIKaIKaQLaLXaJOaLYaJOaLXaQMaIKaIKaIKaIKaQNaQOaQPazIaMKaQQaQRaQRaQRaQSaQTaQUaQVaQWaQXaQVaQYaQZaRaaQVaRbaRcaRdaReaRfaMeaRgaRhaRiaRjaRjaRhaRkaRlaRlaRlaRlaRlaRmaRnaRlaRoaRpaRqaRraRsaRvaRuaTkaRwaRxaRwaRyaRzayHayGaRAaRBaRCaRDaREaRFaRGaRHaRIaRJaRIaRKaRLaRMaRNaROaRPaOCbbVaTCaRTaRUaQdaRVaRWaRXaRYaRZaSaaSbaScaSdaprbikbikbikbikbikbikbikaaabfmbifbieaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaSfaOFaOFaNjaOMaQjaOFaQjaSgaQjaOFaQjaOMaQkaQlaKzaKBaShaMoaMoaSiaSjaSkaSjaMoaKHaKHaKHaKHaSlaSmaSnaSoaKHaSpaSqaSraPdaPdaZVaPdaStaSuaSvaMvbikaLRaLRaSwaSxaSwaLRaLRbikaJGaJLaJMaSyaSzaSAaQJaSBaJMaGvaIKaJNaJOaSCaNRaLXaJOaLYaJOaLXaNTaSDaIKaIKaIKaSEaSFaSGaSHaSIaSJamKamKaSKaSLaSMaSNaMcaSOaMQaMcaSPaMcaSQaMcaSRaSSaSTaSUaSVaTeaSXaSYaSZaTaaTbaTcaTdaTbaTbaUjaTbaSYaTfaSYaOvaTgaSYaThaTiaTjaTmaTlaToaTnaTqaTpaWIaTraOuaTsaTtaTuaTvaTwaTxaTyaTzaRHaTAaTBaRIcLhaTDaTEaTFaROaTGaRQaRRaRSaTHaTIaQdaTJaTKaTKaTLaScaScaScaScaSdaprbikbikbikbikbikbikaaabfmbigbijbihbieaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaONaTMaTNaQiaOMaQjaOFaQjaOFaQjaOFaQjaOMaQkaQlaKzaKBaTOaTPaTQaTRaTSaTSaJraTTaTUaTVaTWaTXaTYaTZaMqcoCaKHaUbaUcaUdaUeaUfaUgaUhaUiaUZaUkaMvbikaabbikaUlaUmaUlbikaabbikaJGaJLaJMaUnaUoaUpaUqaUraJMaGvaIKaUsaUtaKPaUuaUvaKSaUwaKSaUxaUyaUzaIKaUAaUBaUCaUDaUEaUFaUGaUHbikbikaSKaUIaUJaUKaMcaULaUMaMQaMQaUNaMQaMQaMQaUOaMeaUPaMeaUQaURaMeaUSaMeaUTaUUaUVaUWaUXaUYaUTbwNaVaaVbaVcaVbaVbaVbaVbaVdaWLaVbaVeaVfaWFaWBaVbaVhayHaRDaViaTvaVjaVkaVlaVmaVnaVoaVpaVqaRIaVraVsaVtaVuaVvaTGaRQaRRaRSaRTaVwaQdaVxaTKaTKaTLaScaScaScaScaSdaprbikbikbikbikbikbikbdBblqbjMbmKbjMbqQbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaVyaVzaNiaODaOMaOFaVAaVBaOFaOFaVCaVAaOMaONaVDaKzaKBaVEaVFaVGaVHaVGaVGaVGaVGaVGaVIaJraKHaVJaVKaVJaKHaKHaVLaVMaVLaMuaMuaMuaMuaVLaVNaVOaMvaVPaVQaVQaVRaVSaVRaVQaVQaVTaJGaVVaJMaVWaJMaVXaVYaVZaJMaWaaIKaIKaIKaIKaWbaWcaWdaWeaWdaWcaWbaIKaIKaWfaUDaUDaUDaUDaWgaWhaWiaWjaWkaSKbKgaUJaWmaMcaMcaMcaMcaMcaMcaMcaMeaMeaUOaWnaWoaWpaWqaWraWsaWuaWtaUTaWvaWwaWxaWyaWzaUTaWAaWGaWCaWDaWCaWEaWHaYDaWNaYFaWJaWKaYGaWMaYEaVbaWOaRtaWPaWQaWRaVjbtTcvIaVmaWTaRIaWUaWVaWWaWXaWYaTFaTFaRIaRIaRQaRRaRSaTHaWZaQdaXaaXbaXcaXdaXeaXfaScaScaXgaprbikbikbikbikbikaaabfmbqRbmKbmKbmKbqSbieaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaVyaNiaNjaNiaNiaNkaNlaNiaNiaNjaVzaXhaCuaXiaVEaInaXjaXjaXkaXjaXlaDEaXmaXnaJraXoaXpaXqaXqaXraXsaXqaXtaXqaXqaXqaXuaXqaXqaXvaXwaXxaXyaXzaXAaXyaXBaXyaXyaXyaXyaXCaXDaXEaXqaXqaXFaXGaXHaXIaXJaXKaXLaXMaXRaXPaXPaXPaXPaXPaXPaXPaXQaXWaXXaXSaXTaXUaXVaXYaZHaXZaUDaUDaYaaYbaYcaYbaYcaYdaYeaYfaYgaYhaYiaMeaYkbBvaYmaYlaYnaYnaYoaYpaYqaYraUTaYsaYtaYuaYuaYvaUTaYwaYxaYyaYzaYAaYAaYBaYCaYHbbFbalbbHbbGbbJaVgaVbaVhaKsaRDaYIaYJaYJaYKaYLaYJaYMaRIaYNaYOaRIaYPaYQaTFaYRaRIaYSaYTaYUaRSaQbaQbaQdaYVaQeaYWaYXaQeaQeaQeaQeaQeabLadbbikbikbikbikbqUbqTbqVbmKbmKbrUbthbmKbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaYYaKzaKzaKzaKzaKzaKzaYYaInaMlaCuaYZaZaaInaZbaZcaZdaZdaZeaDEaZfaXnaZgaZhaXpaZiaZjaZkaZlaZlaZmaZnaZnaZnaZoaZpaZpaZqaZraZsaZlaZlaZtaZpaZvaZwaZxaZxaZyaZzaZAaZuaZuaZuaZBaXGaXHaXIaXJaXJaXJaXJaZCaXJaXJaXJaXJaXJaXJaZDaZEaZNaZFaZGaZJaZIaZLaZKaZMaZNaZNaZNaZOaZPaZPaZPaZQaYiaYiaYiaZRaZSaYiaMebbsaZUaYnaYnaZVaYnaZWaZXaYqaZYaUTaZZbaababbacbadaUTbaebafbagbahbaibajaVbaVbbbKbbLaVbaVbbakbbMbakaVbaVhayHaRDbamaTvaTvaTvbanaTvbaoaRIaRIaRIaRIaRIaRIaRIbapaRIaRSaRSaRRaRSbaqbaraQbbasbatbaubavbawbaxbaybazbaAbikbikbikbikaaabtibtjbtibtibtibtkbtibtlbtibtjbtiaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaLyaCuaInaGdaKzbaBbaCbaDbaEaKzaGdaInaInaCubaFaVEaInbaGbaHaZdaZdaZeaDEbaIaXnaJraZhaXpaXqbaJbaKbaLbaLbaMbaNbaObaLbaPbaLbaQbaLbaRbaSbaLbaLbaWbaLbaLbaUbaVbaLbaWbaXbaYbaZaXqaXqbbabbbbbcbbdbbebbfbbebbgbbhbbgbbgbbgbbgbbgbbgbbibbjbbkbbkbbkbbkbblbbkbbmbbnbbkbbkbbobbpbbqbbqbbqbbqbbqbbqbbqbbraYiaYiaMebcTbbtbbubbvbbvbbwbbxaZXaYqbbyaUTaUTaUTaUTaUTbbzaUTbbAbbBbbCbbDaWCbbEaVbbdfbdcbdgbbIbkZbjrcSNcIgaVbaVhaHYaRDbbNbbOaTvbbPbbQaTvbbRbbRaRDbbSbbTbbUaQbbbVbbWbbXaRSaRSbbYbbZaQbbcaaQbbcbbatbccbcdbcebatbatbcfbaAbikbikbikbikbqUbtmbwlbutbwmbtmbmKbutbwmbtmbwlbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaDEaInaYYaKzaKBaJraJraKCaKzaYYaKzbcgbchbcibcjaInbckbckaXkbckaXlaDEbclaXnaJraDEbcmbcmbcnbcobcobcobcobcobcobcpbcqbcobcobcobcobcobcobcrbcsbctbctbcubctbcvbcwbcxbcvbcvbcybczbcAbcmbcBbcBbcCbcCbcCbcDbcDbcDbcDbcDbcDbcDbcDbcEbcFbcFbcGbcFbcHbcHbcHbcHbcIbcJbcHbcEbcKbcKbcKbcKbcKbcKbcKbcKbcLbcLbcLaMebcMbcNbcObcObcObcObcPbcQbcRbmwbcUaZTbcVbcWbcXbcYaUTaUTbcZbdabdbbdabdaaVbcYtbdddcnbdebdebdecZrcZqaVbbdhbdiaRDbdjaTvbbPbbPbbQbbPaTvbdkaRDbdlbdmbdnaQbaRSbdobdpbdqbdqbdrbdsbdtbdubdvbdwbdxbdybdzbavbatbatbdAbaAbikbikbikbikbqUbwnbmKbutbBQbtmbmKbutbBQbtmbmKbFmbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaInaYYaKzaKzaKzaKzaKzaKzaYYaInaMlaCuaYZaZaaInaZbaZcaZdaZdaZeaDEaZfaXnaZgaZhaXpaZiaZjaZkaZlaZlaZmaZnaZnaZnaZoaZpaZpaZqaZraZsaZlaZlaZtaZpaZvaZwaZxaZxaZyaZzaZAaZuaZuaZuaZBaXGaXHaXIaXJaXJaXJaXJaZCaXJaXJaXJaXJaXJaXJaZDaZEaZNaZFaZGaZJaZIaZLaZKaZMaZNaZNaZNaZOaZPaZPaZPaZQaYiaYiaYiaZRaZSaYiaMebbsaZUaYnaYnbcMaYnaZWaZXaYqaZYaUTaZZbaababbacbadaUTbaebafbagbahbaibajaVbaVbbbKbbLaVbaVbbakbbMbakaVbaVhayHaRDbamaTvaTvaTvbanaTvbaoaRIaRIaRIaRIaRIaRIaRIbapaRIaRSaRSaRRaRSbaqbaraQbbasbatbaubavbawbaxbaybazbaAbikbikbikbikaaabtibtjbtibtibtibtkbtibtlbtibtjbtiaQfbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaLyaCuaInaGdaKzbaBbaCbaDbaEaKzaGdaInaInaCubaFaVEaInbaGbaHaZdaZdaZeaDEbaIaXnaJraZhaXpaXqbaJbaKbaLbaLbaMbaNbaObaLbaPbaLbaQbaLbaRbaSbaLbaLbaWbaLbaLbaUbaVbaLbaWbaXbaYbaZaXqaXqbbabbbbbcbbdbbebbfbbebbgbbhbbgbbgbbgbbgbbgbbgbbibbjbbkbbkbbkbbkbblbbkbbmbbnbbkbbkbbobbpbbqbbqbbqbbqbbqbbqbbqbbraYiaYiaMebcTbbtbbubbvbbvbbwbbxaZXaYqbbyaUTaUTaUTaUTaUTbbzaUTbbAbbBbbCbbDaWCbbEaVbbdfbdcbdgbbIbkZbjrcSNcIgaVbaVhaHYaRDbbNbbOaTvbbPbbQaTvbbRbbRaRDbbSbbTbbUaQbdilbbWbbXaRSaRSbbYbbZaQbbcaaQbbcbbatbccbcdbcebatbatbcfbaAbikbikbikbikbqUbtmbwlbutbwmbtmbmKbutbwmbtmbwlbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaDEaInaYYaKzaKBaJraJraKCaKzaYYaKzbcgbchbcibcjaInbckbckaXkbckaXlaDEbclaXnaJraDEbcmbcmbcnbcobcobcobcobcobcobcpbcqbcobcobcobcobcobcobcrbcsbctbctbcubctbcvbcwbcxbcvbcvbcybczbcAbcmbcBbcBbcCbcCbcCbcDbcDbcDbcDbcDbcDbcDbcDbcEbcFbcFbcGbcFbcHbcHbcHbcHbcIbcJbcHbcEbcKbcKbcKbcKbcKbcKbcKbcKbcLbcLbcLaMebcObcNbcPbcPbcPbcPbgRbcQbcRbmwbcUaZTbcVbcWbcXbcYaUTaUTbcZbdabdbbdabdaaVbcYtbdddcnbdebdebdecZrcZqaVbbdhbdiaRDbdjaTvbbPbbPbbQbbPaTvbdkaRDbdlbdmbdnaQbaRSbdobdpbdqbdqbdrbdsbdtbdubdvbdwbdxbdybdzbavbatbatbdAbaAbikbikbikbikbqUbwnbmKbutbBQbtmbmKbutbBQbtmbmKbFmbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbdCbdDaJrbdEbdFbdGbdHbdIbdJbdHbdKbdLbdHbdHbdMbdNbdObdPbdQbdQbdQbdRbdQbdSbdTaDEbdUbdVbdWbcobdXbdYbdZbeabebbecbedbeebefbegbehbeibcobejbekbctbelbembenbcvbeobepbeqbcvberbesbetberberberbeuaXJaXObcDbikbikbikbikbikbikbikbcEbevbewbexbeybezbeAbeBbeCbeDbeEbeFbcEbikbikbikbikbikbikbikbcKbeGaYibeHaMebeIbcNbmwbmwbmwbmwbmwbeJbeKbmwbmwbmwbnMbeMbeMbeNbeObePbeQbeRbeSbeTbeUaVbbeVbeWdlHbeYbeYbeXbeZbfaaVbaVhayHaRDbfbbfcaTvbbPbbQaTvbfdbfdaRDaRDbfeaRDaQbbffbbWbbZbfgbfgbfhbbZaQbaQbaQbbfibatbfjbfjbfkbfjbatbflbaAaabbikbikaabbdBbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbdCbfnbfobfnbfnbfnbfnbfnbfnbfobfnbfnbfpaJrbfqbfrbfsaJrbftaJrbfubfvbfwbfxbfyaDEbdVbdVbfzbcobfAbecbecbecbecbecbedbfBbecbecbecbfCbcobejbfDbctbfEbfFbfGbcvbfHbfIbfJbcvbfKbfLbfMbfNbfObesbeuaXJaXObcDbikbikbikbikbcEbcEbcEbcEbfPbfQbfRbfSbfTbfUbfVbfWbfXbfYbfZbcEbcEbcEbcEbikbikbikbikbcKbeGaYibgabgbbgcbgdbgebgfbgcbggbghbgibgjbgkbglbmwbeLbgmbeMbgnbgobeMbgpbgqbgrbgsbeMbgtbgubgvdlHbeYbeYbeXbgwbgxaVbaVhaKsaRDbdjaTvbbPbbPbbQbbPaTvaTvbgybgzaTvbgAaQbbgBbgCbgDbfgbfgbgEbgDbgFaQbbgGbgHbatbgIbgIbgJbgIbatbdAbaAbgKbaAbaAbaAbqUbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaCuaCuaInaInaInaInaInaInaInaInaInaCuaDEbgLbgMbgNbgNbgNbgNbgNbgNbgObgNbgNbgNaDEbdVbejbgPbcobgQbecbecbgRbgSbgTbgUbgRbecbecbecbgVbcobejbekbctbgWbgXbgYbcvbgZbhabhbbcvbhcbhdbhebhfbhgbesbhhbhiaXObcDbcDbhjbcEbcEbcEbhkbhlbhmbhnbhobhobhpbhqbhobhrbhobhsbhtbhubhvbhwbhxbcEbcEbcEbhjbcKbcKbeGaYiaYiaMebhybhzbgkbhAbmwbhBbhCbmwbhDbhEbglbmwbnMbeMbeMbhFbcSbhHbhIbhJbhKbhLbeMbhMbgubhNdlHbeYbeYbhObhPbhQaVbaVhayHaRDbhRbhSbhTbbPbbQbhUaTvaTvbhVaTvbhWbhXaQbbhYbhZbiabfgbfgbibbiabicaQbbidbgHbatbatbatbavbatbatbKnbIzbPfbNjbiibPfddJbmKbmKbmKbmKbmKbmKbmKbmKbmKbmKbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikblsbltbltblubltbltbltblvbltbltbmPaabaInaLAaJtbilbgNbimbinbiobipbiqbirbisbitbgNbiubivbiwbixbcobiybecbecbgRbgTbizbiAbgRbecbecbiBbiCbcobejbekbctbctbiDbctbcvbiEbiFbiGbcvbiHbhfbiIbhfbiJbesbeubiKaXOaXPaXPbiLbiMbiNbcEbiObfRbiPbhobhobiQbiRbiSakybiSbiUbiVbiWbiXbiYbiZbjabcEbjbbiMbjcbjdbjebeGaYiaYibjfbmwbjgbmwbmwbmwbjhbjibmwbhDbjjbglbmwbeLbeMbeMbjkbBDbjmbjnbjobjpbhLbjqaVbdlJdlIdlKbeYbeYbeXbhPbjsaVbbjtbjuaRDbjvaRDaRDbjwbbQbjxbjyaTvbjzbjAaWSbjBbdvbjCbjDbjEbjFbjFbjGbjHbjIbdvbjJbjKbatbjLbatbavbatbatddAbaAbaAbaAbaAbgKbqUddBbmKbutbwmbtmbmKbutbwmbtmbmKddCbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbdCbfnbfobfnbfnbfnbfnbfnbfnbfobfnbfnbfpaJrbfqbfrbfsaJrbftaJrbfubfvbfwbfxbfyaDEbdVbdVbfzbcobfAbecbecbecbecbecbedbfBbecbecbecbfCbcobejbfDbctbfEbfFbfGbcvbfHbfIbfJbcvbfKbfLbfMbfNbfObesbeuaXJaXObcDbikbikbikbikbcEbcEbcEbcEbfPbfQbfRbfSbssbfUbfVbfWbfXbfYbfZbcEbcEbcEbcEbikbikbikbikbcKbeGaYibgabgbbgcbgdbgebgfbgcbggbghbgibgjbgkbglbmwbeLbgmbeMbgnbgobeMbgpbgqbgrbgsbeMbgtbgubgvdlHbeYbeYbeXbgwbgxaVbaVhaKsaRDbdjaTvbbPbbPbbQbbPaTvaTvbgybgzaTvbgAaQbbgBbgCbgDbfgbfgbgEbgDbgFaQbbgGbgHbatbgIbgIbgJbgIbatbdAbaAbgKbaAbaAbaAbqUbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaCuaCuaInaInaInaInaInaInaInaInaInaCuaDEbgLbgMbgNbgNbgNbgNbgNbgNbgObgNbgNbgNaDEbdVbejbgPbcobgQbecbecdhUbgSbgTbgUdhUbecbecbecbgVbcobejbekbctbgWbgXbgYbcvbgZbhabhbbcvbhcbhdbhebhfbhgbesbhhbhiaXObcDbcDbhjbcEbcEbcEbhkbhlbhmbhnbhobhobhpbhqbhobhrbhobhsbhtbhubhvbhwbhxbcEbcEbcEbhjbcKbcKbeGaYiaYiaMebhybhzbgkbhAbmwbhBbhCbmwbhDbhEbglbmwbnMbeMbeMbhFbcSbhHbhIbhJbhKbhLbeMbhMbgubhNdlHbeYbeYbhObhPbhQaVbaVhayHaRDbhRbhSbhTbbPbbQbhUaTvaTvbhVaTvbhWbhXaQbbhYbhZbiabfgbfgbibbiabicaQbbidbgHbatbatbatbavbatbatbKnbIzbPfbNjbiibPfddJbmKbmKbmKbmKbmKbmKbmKbmKbmKbmKbutbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikblsbltbltblubltbltbltblvbltbltbmPaabaInaLAaJtbilbgNbimbinbiobipbiqbirbisbitbgNbiubivbiwbixbcobiybecbecdhUbgTbizbiAdhUbecbecbiBbiCbcobejbekbctbctbiDbctbcvbiEbiFbiGbcvbiHbhfbiIbhfbiJbesbeubiKaXOaXPaXPbiLbiMbiNbcEbiObfRbiPbhobhobiQbiRbiSakybiSbiUbiVbiWbiXbiYbiZbjabcEbjbbiMbjcbjdbjebeGaYiaYibjfbmwbjgbmwbmwbmwbjhbjibmwbhDbjjbglbmwbeLbeMbeMbjkbBDbjmbjnbjobjpbhLbjqaVbdlJdlIdlKbeYbeYbeXbhPbjsaVbbjtbjuaRDbjvaRDaRDbjwbbQbjxbjyaTvbjzbjAaWSbjBbdvbjCbjDbjEbjFbjFbjGbjHbjIbdvbjJbjKbatbjLbatbavbatbatddAbaAbaAbaAbaAbgKbqUddBbmKbutbwmbtmbmKbutbwmbtmbmKddCbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikblsbohbptbojbpwbpwbqWbpwbpwbpwbqWblubjNaInaKzaKBbfqbgNbimbjObjPbimbjQbjRbjSbjTbgNbjUaFmbjWbcsbcobjXbjYbjZbkabkbbkcbkdbkebkebkebkfbkgbcobejbivbkhbkibkjbkkbcvbcvbcvbcvbcvbklbkmbknbkobkpbesbeubiKaXJaXJaXJbkqbkrbksbktbkubkvbhobkwbkxbkybkzbkAbkBbkCbkDbkEbkFbkGbkubkHbkIbkJbkKbkMbkLbkObkObkPaYibkQaMebmwbkRbkSbglbmwbkTbkUbmwbkVbkWbglbmwbnMbeMbeMbeMbeNbeMbkXbeMbjpbhLbkYaVbdlObhNbeXbeYbeYbeXbhPblaaVbblbblcbldbleblfblgblhblibljbljbljbljbljbljblkbllblmbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbatbatbavbatbatddDbgKblrblrblrbaAbwmbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbwmbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbqYbqXbqXbqXbqXbqXbqXbqXbqXbqXbqXbqZbraaGdbraaJrbfqbgNblwbimblxblxblxblybimblzbgNblAblBbjWblCblCblCblCblDblCblEbecblFblGblHblHblIblJbcoblKblLblMblNblOblPblQblRblSblRblTblTblTblTblTblUberbeublVblWblXblYblZbmabmbbmcbmdbkBbmebmfbmgbmgbmgbmgbmhbmgbmibmjbmkbmlbmebmmbmnbcEbmobmpbmqbkNbmsbmtaYiaYibjfbmwbnCbmwbmwbmwaRebmwbmwbmvbmvbmwbmwbmxbeMbeMbmybmzbeMbeMbeMbmAbmBbmCaVbbgxbhNbeXbeXbeXbeXbhPbmDaVbbmEbmFbmFbmGbmFbmHbbPbbPbbPbbPbmIbbPbbPbbPbmJblobfgbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbfjbfjbfkbfjbatddEbaAbmLbmMbmNbaAbBQbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbBQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbrbbrebrdbrfbrfbrgbrfbrfbrfbrgbluaInaInaKzbrVbcjbmQbimbmRblxblxblxblybmRbimbgNbmSbmTbjWblCbmUbmVbmWbmXblCbmYbmZbnabcobnbbncbndbnebcobejbnfbngbngbnhbngbngbngbngbnibnjbnjbnjbnkbnjbnlbnmbnnbnobnpbnqbnqbnqbnqbnqbnqbnrbnsbnrbmgbmgbntbnubnvbnwbnxbnybntbnzbmgbnAbnBbnAbnAbnAbnAbnAbnAbnAbmtaYiaYiaMebnEbnDcakbnGbmwbnFbmwbnJdmhdmgbmwbpjaUTbnKbnLaUTaUTczObnNddybnNaUTaUTaVbbnObnPbnQbnQbnQbnQbnPbnRaVbbnSbmFbmFbmGbnTaRDbnUbnVbnWbnXbnYbnZboabobbocaQbbodaRSboebfgbfgboeaRSbofaQbbogbgHbatbgIbgIbgJbgIbatddDbgKblrblrblrbaAbGVbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbGVbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbltbltblubltbltbltblvbltbltbtnaabaInboibdFbokbgNbjObjObjObimbolbombonboobgNbopboqbjWblCborblCbosbotblCboubovbowbcobnbbncbndbiCbcobejbnfbngboxboybozboAboBbngboCboDboEboFbnmbnmbnmbnmboGboHboIbnqboJboKboLboMboNboOboPboQbmgboRbnvboSboTboUboTboSbnvboVbmgboWboXboYboZbpabpbbpcbpdbnAbpebpfbpfbpgaMeaMeaMeaMebphbjfbphbpiaMeaURaMeaMeaUTaUTaUTaUTbplbpkbpkbpkbpkbpmbpJaVbbakbpnbakbpobpobakbpnbakaVbbnSbmFbmFbppbnTaRDaRDaRDaRDaRDbjvaRDaRDaRDaRDaQbbpqaQcaQcaQcaQcaQcaQcaQbaQbbprbpsbatbatbatbavbatbatddAbaAbaAbaAbaAbgKbqUddFbmKbmKbmKbmKbmKbmKbmKbmKbmKddGbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaKzaDEaDEaDEaDEaDEaDEbtobpubgNbgNbgNbgNbgNbgNbpvbgNbgNbgNbejbejbpxblCbpybpzbosbpAblCdlEbpCbpBbcobnbbncbndbecbcobejbnfbngbpDbpEbpFboAbpFbngboCbpGbpHbpIbmubpKbpLbnmbpMbpNboIbpObpPbpQbpRbpSbpSbpRbpTbpUbmgbpVbnvbnvbpWbpXboTboSbnvbpYbmkbpZbqabqbbqcbqdbqebqbbqfbnAbqgbqhbqibqjbqkbqlbqmbqnbqnbqnbqnbqnbqnbqobqpbqqbqnbqnbqsbqnbqnbqnbqnbqnbqnbqnbqndcZbqubqvbqvbqvbqvbqvbqvbqwbqlbqxbqybqyaHkbqAbqBbqAbqCbqAbqDbqEbqFbqAbqGbqHbqIbqJbqKbqKbqKbqKbqKbqKbqKbqLbqMbqNbqNbqNbqNbqObqNbqPbKnddHbPfddIbiibPfdlbbmKbmKbmKbmKddKbmKddKbmKbmKbmKddGbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbtpbtqbtqbtqbtqbwpbwpbtqbtqbxZbikaabaInaLAaJtbzPbzObzRbzQbzQbzQbzQbzSbzUbzTbcsbdVbBFbrhblCblCblCbribotblCbcobcobcobcobnbbrjbrkbrlbcobrmbrnbngbrobrpboAbpFbrqbngboCbrrbpHbpIbpIbrsbrtbnmbrubpNboIbpObrvbrwbrxbrybrzbrAbpTbrBbmgbrCbpWbnvbrDbrEbrDbnvbpWbrFbnzbrGbqbbqbbqcbrHbqebqbbrIbnAbrJbqibqibqjbqkbqlbqnbqnbqnbqnbqnbqnbqnbrKbqnbqnbqnbqnbqnbqnbrLbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrNbrObrPbqKbqKbrQbmFbmFbmFbmFbmFbmGbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbrRbmFbrSbrTbatbatbatbatbatbatbatddLbaAbgKbaAbaAbaAbqUddMddOddNbdBddPbdBddPbdBddQddMddObqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCbBHdjhbDDdjidjidjkdjjbtqbxZbjNaInaInaKBbrWbrXbrYbrXbrXbrXbrXbrZbsabsbbcsbcsbscbsdblCbmUbsebsfbpAblCbsgbshbsgbcobcobcobcobsibcobsjbskbngbslbsmbpFbsnbsobngboCbnmbspbpIbpIbpIbsqbnmbsrbpNboIbpOdmbbrwbrxbstbsubrAbpTbsvbmgbswbsxbnvbsybszbsAboSbsBbsCbsDbsEbsFbsGbsHbsIbsJbqbbsKbnAbsLbsMbqibqjbqkbqlbqnbsNbqnbqnbqnbqnbsObsPbsPbsPbsPbsQbqnbqnbqnbqnbsRbqnbsNbsSbqnbsTbsUbsVbqnbsWbsXbsXbsYbsZbtabtbbmFbmFbmFbmFbmFbmFbmFbtcbtdbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbtebtfbtfbtgddSddRddUddTddTddTddTddVddWbaAaabbikbikaabbqUddXddZddYdeabqUbikbqUdecdebdecdecbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjldjidjidjidjidjidjidjideHdjnaGddjnaJrbtrbrXbtsbttbtubtvbtwbrZbtxbtybtzbtzbtAbtBblCblCblCbosbtCborbcsbcsbcsbcsbtDbejbejbskbejbsjbskbngbtEbtFbtGbtHboAbngbtIbnmbtJbpIbpIbpIbtKbtLbtMbpNbtNbnqbtObtPbpRbpRbpRbpRbpTbtQbmgbtRbtSbmgbmgbmgbmgbmgbmgbmgbnzbnAbqrbtUbtVbtWbtXbtYbtZbnAbvubuabuabucbucbucbucbucbucbucbudbudbuebufbugbugbufbuebudbudbuhbuhbuhbuhbuhbuhbuibuibujbuibuibuibuibuibukafkbumbunbmFbmFbuobuobupbupbupbupbupbuqbtfbtfbtebtfbmFbtfbtfbtfbtfburbusbusbusbusdedbuubuubuubuubuubuubuubuubuubikbikbikbikbdBddYddYddYdeebqUbikbqUdefdebdebdegbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjodjpdjpdjidjpdjpdjpbtqdjqaInaInaInaKBbuvbrXbuwbuxbuxbuxbuybrZbejbuzbuAbuBbuCbuDblCbmUbuEbosbuFborbuGbuHbuIbuJbuKbuLbuLbuMbuLbuNbuObngbuPbuQbuRbuSbuTbuUbuVbnmbuWbpIbpIbuXbuYbuZbtMbpNbvabnqbvbbvcbvdbvebvfbvgbvhbnqbnqbvibvjbvkbvlbvmbvlbvnbvjbikbvobnAbvpbvqbvrdmcbtXbqbbvtbnAbxebvwbxfbucbzcbvybvzbvAbvBbvCbvDbvEbvFbvGbvHbvHbvGbvIbvJbvKbuhbvLbvMbvNbvObuhbvPbvQbvRbvSbvTbvUbvUbvVbukafNbvXbvYbvZbvYbwabwabupbwbbwcbwdbupbwebwfbwebupbwgbtfburbusbwhbwibwhbusbwjbwkbusdeicngbxXbwobikbikbikbikbikbikbikbikbikbikbqUddXddZddYdejbqUbikbqUdekdekdekdekbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbqYbqXbqXbqXbqXbqXbqXbqXbqXbqXbqXbqZbraaGdbraaJrbfqbgNblwbimblxblxblxblybimblzbgNblAblBbjWblCblCblCblCblDblCblEbecblFblGblHblHblIblJbcoblKblLblMblNblOblPblQblRblSblRblTblTblTblTblTboFblUbeublVblWblXblYblZbmabmbbmcbmdbkBbmebmfbmgbmgbmgbmgbmhbmgbmibmjbmkbmlbmebmmbmnbcEbmobmpbmqbkNbmsbmtaYiaYibjfbmwbnCbmwbmwbmwaRebmwbmwbmvbmvbmwbmwbmxbeMbeMbmybmzbeMbeMbeMbmAbmBbmCaVbbgxbhNbeXbeXbeXbeXbhPbmDaVbbmEbmFbmFbmGbmFbmHbbPbbPbbPbbPbmIbbPbbPbbPbmJblobfgbfgbfgbfgbfgbfgbfgblnbloblpbgHbatbfjbfjbfkbfjbatddEbaAbmLbmMbmNbaAbBQbtmbmKbutbBQbtmbmKbutbBQbtmbmKbutbBQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbrbbrebrdbrfbrfbrgbrfbrfbrfbrgbluaInaInaKzbrVbcjbmQbimbmRblxblxblxblybmRbimbgNbmSbmTbjWblCbmUbmVbmWbmXblCbmYbmZbnabcobnbbncbndbnebcobejbnfbngbngbnhbngbngbngbngbnibnjbnjbnjbnkbnjbnlbuWbnnbnobnpbnqbnqbnqbnqbnqbnqbnrbnsbnrbmgbmgbntbnubnvbnwbnxbnybntbnzbmgbnAbnBbnAbnAbnAbnAbnAbnAbnAbmtaYiaYiaMebnEbnDcakbnGbmwbnFbmwbnJdmhdmgbmwbpjaUTbnKbnLaUTaUTczObnNddybnNaUTaUTaVbbnObnPbnQbnQbnQbnQbnPbnRaVbbnSbmFbmFbmGbnTaRDbnUbnVbnWbnXbnYbnZboabobbocaQbbodaRSboebfgbfgboeaRSbofaQbbogbgHbatbgIbgIbgJbgIbatddDbgKblrblrblrbaAbGVbtmbmKbutbGVbtmbmKbutbGVbtmbmKbutbGVbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbrcbltbltblubltbltbltblvbltbltbtnaabaInboibdFbokbgNbjObjObjObimbolbombonboobgNbopboqbjWblCborblCbosbotblCboubovbowbcobnbbncbndbiCbcobejbnfbngboxboybozboAboBbngboCboDboEbSVbyzbyzbyzbuVboGboHboIbnqboJboKboLboMboNboOboPboQbmgboRbnvboSboTboUboTboSbnvboVbmgboWboXboYboZbpabpbbpcbpdbnAbpebpfbpfbpgaMeaMeaMeaMebphbjfbphbpiaMeaURaMeaMeaUTaUTaUTaUTbplbpkbpkbpkbpkbpmbpJaVbbakbpnbakbpobpobakbpnbakaVbbnSbmFbmFbppbnTaRDaRDaRDaRDaRDbjvaRDaRDaRDaRDaQbbpqaQcaQcaQcaQcaQcaQcaQbaQbbprbpsbatbatbatbavbatbatddAbaAbaAbaAbaAbgKbqUddFbmKbmKbmKbmKbmKbmKbmKbmKbmKddGbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaKzaDEaDEaDEaDEaDEaDEbtobpubgNbgNbgNbgNbgNbgNbpvbgNbgNbgNbejbejbpxblCbpybpzbosbpAblCdlEbpCbpBbcobnbbncbndbecbcobejbnfbngbpDbpEbpFboAbpFbngboCbpGbpHbAibmubpKbpLbnmbpMbpNboIbpObpPbpQbpRbpSbpSbpRbpTbpUbmgbpVbnvbnvbpWbpXboTboSbnvbpYbmkbpZbqabqbbqcbqdbqebqbbqfbnAbqgbqhbqibqjbqkbqlbqmbqnbqnbqnbqnbqnbqnbqobqpbqqbqnbqnbqsbqnbqnbqnbqnbqnbqnbqnbqndcZbqubqvbqvbqvbqvbqvbqvbqwbqlbqxbqybqyaHkbqAbqBbqAbqCbqAbqDbqEbqFbqAbqGbqHbqIbqJbqKbqKbqKbqKbqKbqKbqKbqLbqMbqNbqNbqNbqNbqObqNbqPbKnddHbPfddIbiibPfdlbbmKbmKbmKbmKddKbmKddKbmKbmKbmKddGbdBbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbtpbtqbtqbtqbtqbwpbwpbtqbtqbxZbikaabaInaLAaJtbzPbzObzRbzQbzQbzQbzQbzSbzUbzTbcsbdVbBFbrhblCblCblCbribotblCbcobcobcobcobnbbrjbrkbrlbcobrmbrnbngbrobrpboAbpFbrqbngboCbrrbpHbAibpIbrsbrtbnmbrubpNboIbpObrvbrwbrxbrybrzbrAbpTbrBbmgbrCbpWbnvbrDbrEbrDbnvbpWbrFbnzbrGbqbbqbbqcbrHbqebqbbrIbnAbrJbqibqibqjbqkbqlbqnbqnbqnbqnbqnbqnbqnbrKbqnbqnbqnbqnbqnbqnbrLbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrMbrNbrObrPbqKbqKbrQbmFbmFbmFbmFbmFbmGbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbrRbmFbrSbrTbatbatbatbatbatbatbatddLbaAbgKbaAbaAbaAbqUddMddOddNbdBddPbdBddPbdBddQddMddObqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCbBHdjhbDDdjidjidjkdjjbtqbxZbjNaInaInaKBbrWbrXbrYbrXbrXbrXbrXbrZbsabsbbcsbcsbscbsdblCbmUbsebsfbpAblCbsgbshbsgbcobcobcobcobsibcobsjbskbngbslbsmbpFbsnbsobngboCbnmbspbAibpIbpIbsqbnmbsrbpNboIbpObWDbrwbrxbstbsubrAbpTbsvbmgbswbsxbnvbsybszbsAboSbsBbsCbsDbsEbsFbsGbsHbsIbsJbqbbsKbnAbsLbsMbqibqjbqkbqlbqnbsNbqnbqnbqnbqnbsObsPbsPbsPbsPbsQbqnbqnbqnbqnbsRbqnbsNbsSbqnbsTbsUbsVbqnbsWbsXbsXbsYbsZbtabtbbmFbmFbmFbmFbmFbmFbmFbtcbtdbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbmFbtebtfbtfbtgddSddRddUddTddTddTddTddVddWbaAaabbikbikaabbqUddXddZddYdeabqUbikbqUdecdebdecdecbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjldjidjidjidjidjidjidjideHdjnaGddjnaJrbtrbrXbtsbttbtubtvbtwbrZbtxbtybtzbtzbtAbtBblCblCblCbosbtCborbcsbcsbcsbcsbtDbejbejbskbejbsjbskbngbtEbtFbtGbtHboAbngbtIbnmbtJbAibpIbpIbtKbtLbtMbpNbtNbnqbtObtPbpRbpRbpRbpRbpTbtQbmgbtRbtSbmgbmgbmgbmgbmgbmgbmgbnzbnAbqrbtUbtVbtWbtXbtYbtZbnAbvubuabuabucbucbucbucbucbucbucbudbudbuebufbugbugbufbuebudbudbuhbuhbuhbuhbuhbuhbuibuibujbuibuibuibuibuibukafkbumbunbmFbmFbuobuobupbupbupbupbupbuqbtfbtfbtebtfbmFbtfbtfbtfbtfburbusbusbusbusdedbuubuubuubuubuubuubuubuubuubikbikbikbikbdBddYddYddYdeebqUbikbqUdefdebdebdegbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbBGbDCdjodjpdjpdjidjpdjpdjpbtqdjqaInaInaInaKBbuvbrXbuwbuxbuxbuxbuybrZbejbuzbuAbuBbuCbuDblCbmUbuEbosbuFborbuGbuHbuIbuJbuKbuLbuLbuMbuLbuNbuObngbuPbuQbuRbuSbuTbuUdngbyzdnidnhbpIbuXbuYbuZbtMbpNbvabnqbvbbvcbvdbvebvfbvgbvhbnqbnqbvibvjbvkbvlbvmbvlbvnbvjbikbvobnAbvpbvqbvrccIbtXbqbbvtbnAbxebvwbxfbucbzcbvybvzbvAbvBbvCbvDbvEbvFbvGbvHbvHbvGbvIbvJbvKbuhbvLbvMbvNbvObuhbvPbvQbvRbvSbvTbvUbvUbvVbukafNbvXbvYbvZbvYbwabwabupbwbbwcbwdbupbwebwfbwebupbwgbtfburbusbwhbwibwhbusbwjbwkbusdeicngbxXbwobikbikbikbikbikbikbikbikbikbikbqUddXddZddYdejbqUbikbqUdekdekdekdekbqUbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjrbtqbtqbtqbtqbtqbtqbtqbtqdjqbikbikaInbwqbdFbwrbrXbwsbrXbwtbuxbwubwvbrZbwwbwxbwybwzbuDblCblCblCblCblCblCbwAbwBbwCbwDbwEbngbngbngbngbngbngbngbwFbngbngbngbwGbngbwHbwIbwJbpIbpIbpIbwKbtLbwLbpNbwMbnqbIDbvcbnrbnrbnrbnqbwObnqbwPbwQbwRbwSbwTbwUbwVbwWbwXbwYbwZbnAbxabqbbxbbxcbtXbxdbqbbnAbzbbxgbANbucbxhbxibxjbxkbxlbxmbxnbvHbvHbvHbvHbvHbvHbvHbvHbxobxpbxqbxrbxsbxtbuhbxubxvbxwbxxbxybxzbxvbxAbukbDdbvXbxCbxDbxEbxFbxFbxGbxHbxIbxJbxKbxLbxMbxNbupbxObxPbxQbusbxRbxSbxTbLSbxUbxVbusbxWbxXbxYbwobikbikbikbikbikbikbikbikbikbikbDybtldemdemdemdenbikdeodepdepdepbtlbDzbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaLyaCuaKzaKzaInaInaInaInaInaInaInaKBaJrbyabrXbybbycbydbyebyebyfbygbyhbyibyibyjbykbtzbtzbtzbtzbtzbtzbylbymbymbynbyobngbypbyqbyrbysbytbyubyvbywbngbyxbyybyzbuVbtLbwJbpIbpIbyAbnmbnmbyBbyCbyDbyEbyFbyGbyHbyIbyJbyKbyLbyMbyNbyObwXbyPbyQbyPbyQbyRbwXbwYbySbyTbyUbyVbyWbyXbyYbyZbzabyTbAObvwbvwbucbzebzdcSCbzfbzgbucbxnbvHbvHbvHbvHbvHbvHbvHbzhbzibzjbzkbzlbxqbzmbuhbznbzobzpbxxbxAbxzbzqbzrbukbIbbztbzubzvbzvbzwbzxbzybzzbzAbzAbzAbzBbzAbzCbzDbzEbzFbzGbzHbzIbzJbzKbzKbzKbzLbusbzMbxXbzNbwobikbikbikbikbikbikbikbikbikbikbikbDyderderderbDzbikbDyderderderbDzbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaIndjtdjsdjuaIoaIoaIobdFaJraJrbrXbzVbrXbzWbzXbzYbzZbrXbcsbAabAabAbbAcbAbbAbbAbbAcbAbbcsbcsbngbngbngbAdbngbAebAebAebAebAebAebyvbAfbAgbAhbAibAjbAkbAlbAmbAnbAobApbAqbArbAsbAtbAubAvbAwbAwbAxbAybAzbAAbABbACbADbAEbvjbAFbwVbAGbwTbAHbvjbikbAIbAJbAKbALbAJbAJbAJbAJbAMbnAbCBbvwbCCbAPbAQbARbASbATbAUbucbAVbAWbAXbAYbAZbBabBbbBcbvHbBdbuhbBebzlbBfbBgbuhbBhbBibxwbxxbxAbxzbxvbxAbukbDdbvXbBjbBkbBlbBmbBnbBobBpbBqbBrbBsbBtbBubKpbupbBwbBxbBybusbBzbBAbBBbxUbBCbKwbusbzMbxXbBEbwobikbikbikbikaabaabaabaabaabaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8880,18 +8937,18 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjCdjEdjDdjGdjFdjIdjHdjFdjJdjLdjKdjydjydjBbikbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevbGWbmrbNkbmrbGXbGYbGZbGYbGYbGYbGYbHabyvbAfbHbbngbngbHcbpIbAibFvbHdbtLbHebHfbHfbHgbHhbHibHjbHkbHlbHmbHnbHobHpbHqbHrbHsbCpbCqbAEbvjbEibHubHvbHwbHxbvjbikbEkbHybHzbHybHybHybHybHybHAbHybKPbvwbKObucbHCbHDbHDbHEbHFbEybHGbHHbHIbHJbHKbHLbHMbHIbHNbHObHPbHQbHRbHSbHTbHTbHUbHVbHWbHXbHYbLibLCbLBbNdbNcbNebIfbIfbIgbIhbIibxGbIjbxJbxJbIkbIlbEUbImbInbIobIpbIqbIrbIsbItbIubIvbIubusbusbIwbEXbGxbLDbLDbLDbLDbLDbGxbFhbFkbFibFkbFkbGTbFhaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydjHdjHdjHdjMdjFdjNdjNdjFdjOdjHdjHdjQdjPdjydjBbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevbLFbKmbIAbKmbIBbAebFqbFrbFrbFrbAebAebyvbAfbICbKobngbIEbpIbAibFvbIFbtLbIGbpIbrsbpIbIHbDXbvvbIIbHlbHmbIJbIKbILbIMbINbIObIPbIQbIRbISbISbITbIUbIVbvjbvjbikbEkbHybIWbIXbIYbIZbJabJbbJcbJdbMhbvwbKObCHbJfbJgbJhbJibJjbEybJkbJlbJmbJnbJobJpbJqbJrbJsbJtbJubJvbJwbJxbJybJzbJAbJBbJCbJDbJEbGwchEbIecnfcjubvYbJIbJJbJKbJLbJLbxGbJMbJNbJObxGbJPbEUbJQbxGbJRbJSbJTbJUbJVbJWbJXbJYbJZbKabKbbKcbKdbKebKfbKfbIxbJFbJHbGzbKlbFfbDBbNhbDBbFfbLEaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydjSdjRdjUdjTdjVdjFdjWdjHdjXdjHdjHdjHdjHdjHdjMdjFbikbikbikbikbikbikbikbikbikbikdewdeCdevdevdevcOfdewbFnbBRbBRdezbAebFqbAebAebAebAebAebyvbAfbICbLwbngbLQbpIbKqbKrbpIbKsbpHbpIbpIbKtbtLbDXbvvbIIbHlbHmbCpbKubKvbqzbKxbKybKzbKAbKBbKCbKDbwXbKEbKFbwXbwYbwYbKGbHybKHbKIbKJbKKbKLbKLbKMbKNbMibvwbMjbucbEybKQbEubKRbKSbEybJkbKTbKUbKVbKWbKXbKYbKUbJkbKZbLabLbcchbLbbLcbLbbLdbLdbLebLfbLgbLhbLhcpLbLgbLgbLhbLhbLjbLkbLjbLjbxGbxGbxGbxGbxGbLlbLmbBobxGbLnbLobLpbLqbLqbLrbLsbLtbLubLvbLIbLxbLybLzbLAbLAbEObGAbHZbGxbGzbGzbGzbIabGxbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjZdjYdjHdjHdkadkadkadjFdjHdjHdjFdkbdkddkcdkfdkedkgdjFbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevbWobKmbIAbKmbFobLGbLHbAebAebAebLGbAebyvbAfbICbNrbngbLJbpIbAibFvbpIbnmbLKbpIbpIbLLbtLbDXbvvbLMbHlbLNbCpbLObLPbWDbLRcobbKzbLTbLUbLVbLWbLXbLYbLZbMabikbikbikbHybMbbMcbMdbMdbMebMfbMgbHybNSbNRbKObNTbMkbMlbMmbMnbMobMpbMqbJlbMrbMsbMtbMubMvbMrbJkbKZbMwbMxbMybMzbMAbMBbLdbMCbMDbMEbLgbMFbMGbMHbMIbMJbMKbMLbKabMMbLqbLqbMNbMObLqbMPbMQbMRbMSbMTbLqbMUbiTbMWbMXbMYbMZbNabNbbNabNabNabIwbEXbGxbLDbLDbGxcnccndcnebOQbOSbUHbYdbGzbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjZdjYdjHdjHdkadkadkadjFdjHdjHdjFdkbdkddkcdkfdkedkgdjFbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevbWobKmbIAbKmbFobLGbLHbAebAebAebLGbAebyvbAfbICbNrbngbLJbpIbAibFvbpIbnmbLKbpIbpIbLLbtLbDXbvvbLMbHlbLNbCpbLObLPdiNbLRcobbKzbLTbLUbLVbLWbLXbLYbLZbMabikbikbikbHybMbbMcbMdbMdbMebMfbMgbHybNSbNRbKObNTbMkbMlbMmbMnbMobMpbMqbJlbMrbMsbMtbMubMvbMrbJkbKZbMwbMxbMybMzbMAbMBbLdbMCbMDbMEbLgbMFbMGbMHbMIbMJbMKbMLbKabMMbLqbLqbMNbMObLqbMPbMQbMRbMSbMTbLqbMUbiTbMWbMXbMYbMZbNabNbbNabNabNabIwbEXbGxbLDbLDbGxcnccndcnebOQbOSbUHbYdbGzbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkhdjYdjHdjHdjHdjHdjHdkidjHdjHdjFdjydjydjydjydjydjydkjbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevdeEdeDdeGdeDbNlbNmbNnbNnbNnbNnbNnbNobNpbNqbICbWSbngbNsbNtbNubNvbNwbNxbNybNybNybNzbNzbNAbvvbNBbNCbHmbCpbNDbNEbNFbKvbNGbKzbNHbNIbNJbNKbNLbFNbNMbMabikbikbikbHybNNbNObNPbNQbMebMfbMgbHybPibNUbQObPjbNVbNWbNXbNYbNZbOabObbOcbKUbKUbOdbOebKUbKUbJkbKZbOfbOgbOhbOibOjbOkbLdbOlbOmbOnbOobOpbOqbOrbOrbOsbOtbOubOvbOwbJVbJVbOxbJVbOybJVbOzbJVbOAbOBbOBbOCbODbOEbOFbOGbOHcsjbOJbOKbOLbNabOMcxHbikbikbikbGxbORbJFbOPbOQbGzbOObNibGxbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkmdkldkodkndjHdjFdjHdjHdjFdjHdkqdkpdkrbikbikbikbikbikbikbikbikbikbikbikbikbikdewdevdevdevdevdevdewbFnbBRbBRbngbngbBRbBRbBRbBRbBRbngbngbBRbBRbBRbngbOVbOVbOVbOWbOVbNzbOXbOYbOZbPabNzbDXbvvbPbbPcbPcbCpbCpbCpbCpbCpbPdbKzbISbIRbPebNKbPgbPhbMabMabvjbvjbvjbHybHzbHybHybHybHybHybHybHybQPbvwbQQbPkbPlbPmbPnbPlbPlbPobPpbPqbPrbPsbPtbPubPvbPwbMqbPxbPybPzbPAbPBbPCbPDbPEbPFbPGbPHbPIbPJbPKbPLbMHbPMbLhbLhbPNbPObPNbPPbPQbPPbPPbPPbPRbPSbPTbPTbPUbPVbPWbPXbOFbPYbPZbQabQbbQcbQdbNabOMcxHbikbikbikbGxbNfbNgbGxbGzbGxbGxbGzbGxbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjydjydjydjydjydjydjFdjOdjHdksdjHdkudktdkvbikbikbikbikbikbikbikbikbikbikbikbikbikdeJdeIdevdeKdevdeLdeMbikbikbikbikbikbikbikbikbikbikbQgaabbikbikbikbikbOVbQhbQibQjbQkbNzbQlbQmbQnbQobNzbDXbvvbQpbQqbQrbQsbQtbQubQvbQwbQxbQybQzbQAbQBbQCbQDbQEbQFbQGbQHbQIbQJbQKbQLbQMbQRbuabQSbvwbShbSgbSibvwbSjbPlbQTbQUbQVbQWbQXbJkbQYbQZbRabRbbRcbRdbRebRfbRgbRhbRibLbbRjbOibRkbRlbRmbRnbRobRpbLgbRqbMHbMHbMHbRrbLhbPNbRsbRtbRubRvbRwbRxbRybPPbRzbRAbRBbPTbPTbRCbPWbRDbREbWHbRGbRHbRIbRJbRKbNabRLbwobikbikbikbGxbGxbGxbGxbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydkxdkwdkydkxdkzdjFdjHdjHdjFdjHdkBdkAdkCbikbikbikbikbikbikbikbikbikbikbikbikbikdeOdeNdePdePdePdeNdeQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbOVbRMbRNbRObRPbNybRQbRRbRSbRTbNzbDXbRUbRVbvvbvvbFXbRWbubbQNbQMbRXbRYbRXbRZbSabSabSbbScbSdbSabSabSebSabSfbSabQMbQRbuabSlbSkbTJbTIbTLbTKbvwbPlbSmbQUbSnbSobSpbJkbSqbSrbSsbStbSubSvbSwbSxbJkbSybSzbLbbSAbSBbSBbSCbSDbSEbSFbSGbLgbSHbSIbMHbSJbSKbLhbPNbSLbSMbSNbSObSPbSQbSRbPPbSSbRAbSTbSTbPTbSUbSVbSWbSXbSYbSZbTabTbbTcbTdbNabOMbwobTebikbikbikbikbikbikbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjxdjydkxdkwdkydkxdkzdjFdjHdjHdjFdjHdkBdkAdkCbikbikbikbikbikbikbikbikbikbikbikbikbikdeOdeNdePdePdePdeNdeQbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbOVbRMbRNbRObRPbNybRQbRRbRSbRTbNzbDXbRUbRVbvvbvvbFXbRWbubbQNbQMbRXbRYbRXbRZbSabSabSbbScbSdbSabSabSebSabSfbSabQMbQRbuabSlbSkbTJbTIbTLbTKbvwbPlbSmbQUbSnbSobSpbJkbSqbSrbSsbStbSubSvbSwbSxbJkbSybSzbLbbSAbSBbSBbSCbSDbSEbSFbSGbLgbSHbSIbMHbSJbSKbLhbPNbSLbSMbSNbSObSPbSQbSRbPPbSSbRAbSTbSTbPTbSUdnjbSWbSXbSYbSZbTabTbbTcbTdbNabOMbwobTebikbikbikbikbikbikbikbikaabbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjZdjYdkDdkDdkDdkDdkDdkEdjHdjHdjFdjydjydjydjydjydjydjBbikbikbikbikbikbikbikbikbikbikbikdeRdeSdeSdeSdeTbikbikbikbikbikbikbikbikbOUbOTbQebOTbQfbikbikbikbOVbOVbTjbTkbRObTlbNybTmbQnbTnbTobNzbDXbTpbTqbTrbTsbTtbTubTvbTwbTxbTybTzbTAbTBbTCbTCbTDbTEbTEbTEbTEbTEbTEbTFbTGbTHbTNbTMbTPbTOdlidjmdlkdljdllbPlbTQbQUbQVbTRbSpbJkbSqbSrbTSbTTbTUbTVbTWbTXbJsbTYbTZbLbbLbbUabUabLbbSDbLdbUbbUcbLgbUdbUebUfbUgbUhbLhbPNbUibUjbUkbUlbUmbUnbUobPPbUpbRAbSTbSTbPTbUqbUrbUsbUtbUubUvbUwbUxbUybUzbNabOMbUAbUBbUAbUCbUDbUCbUCbUCbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikaabaabaabaabaabbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkhdjYdkDdkDdkDdkFdkGdjFdjHdjHdjFdjHdjHdjHdkHdjHdkIdjFbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbTgbTfbTibThbTgbUIbUIbUIbOVbUJbUKbULbUMbUNbUObUPbUQbUQbURbNzbUSbUTbUUbUVbUVbUWbUXbUYbUVbUZbUZbVabVbbONbUZbUZbVdbQMbQMbVebVfbVfbVfbVgbVhbVfbVfbVibVjbVkbVkbVlbVkbVmbVnbVkbVobVpbVqbPlbVrbVsbSqbVtbVubVvbVwbVxbVybVubJkbSybVzbVAbVBbVCbVDbVEbVFbVGbVHbVIbVJbVKbVLbVMbVNbVObLhbPNbPNbVPbVQbVRbVSbVRbVTbPPbVUbVVbVWbVWbPTbVXbVYbVZbNabNabNabNabNabNabNabNabOMbUAbWabWbbWcbWdbWdbWebUCbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikaabbWfbWfbWfbWfbWgbWgbWhbWhbWhbWhbWiaabaabbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkKdkJdkDdkLdkMdjFdjHdjHdkNdjHdjHdjHdkOdjHdkPdjFbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbQebUEbUFbUEbQebUIbWmbWlbOVbWnbWpbWqbWrbWsbNzbWtbWubWvbWwbNzbUTbUTbWxbUVbWybWzbWAbWBbWCbUZdmdbWEbWFbWGcAzbUZbWIbWJbWKbVfbWLbWMbWObWNbWPbWQbWRceLbWTbWUbWVbWWbWXbWYbWZbXabXbbXcbXdbXebXfbXgbXhbSrbXibXjbXkbXlbXmbXnbJsbXobXpbXqbXrbVDbXsbXsbXtbXubLgbXvbXwbXxbXybXzbXAbXBbLhbXCbXDbXEbXFbXEbXEbXGbXHbXIbXJbXKbXLbXMbPTbXNbXObPXbEXbxXbXPbXQbXRbXRbXQbXRbXSbUAbXTbXUbWcbWdbXWbXVbUCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWfbXXbXYbXXbWgbWhbWhbXZbYabXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkKdkJdkDdkLdkMdjFdjHdjHdkNdjHdjHdjHdkOdjHdkPdjFbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbQebUEbUFbUEbQebUIbWmbWlbOVbWnbWpbWqbWrbWsbNzbWtbWubWvbWwbNzbUTbUTbWxbUVbWybWzbWAbWBbWCbUZdmbbWEbWFbWGcAzbUZbWIbWJbWKbVfbWLbWMbWObWNbWPbWQbWRceLbWTbWUbWVbWWbWXbWYbWZbXabXbbXcbXdbXebXfbXgbXhbSrbXibXjbXkbXlbXmbXnbJsbXobXpbXqbXrbVDbXsbXsbXtbXubLgbXvbXwbXxbXybXzbXAbXBbLhbXCbXDbXEbXFbXEbXEbXGbXHbXIbXJbXKbXLbXMbPTbXNbXObPXbEXbxXbXPbXQbXRbXRbXQbXRbXSbUAbXTbXUbWcbWdbXWbXVbUCbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWfbXXbXYbXXbWgbWhbWhbXZbYabXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkQdkDdkDdkRdjFdjHdjHdjFdkSdjHdjHdkUdkTdjydkjbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbTgbUGbUEbUEdeycOWbTkbTkdeAbZAbTkbWqbYhbYibNzbNzbNzbNzbNzbNzbYjbUTbYkbYlbYmbYnbYnbYnbYobUZbYpbYqbYqbYqbYrbYsbYtbYubYvbYwbYxbYybYzbYAbYBbYCbVfbVibYDbVkbYEbYFbYGbYHbYIbVkbSmbQVbSnbSobYJbYKbYLbYMbYNbYObYPbYQbYRbVubYSbYTbYUbYVbYWbYXbYYbYZbZabZbbLgbLgbLgbLgbLgbZcbZdbZebLhbZfbXEbXEbZgbZhbXEbZibZjbZkbZlbRAbZmbZmbPTbPVbZnbPXbEXbUAbZobUAbUAbUAbUAbUAbUAbUAbZpbZqbUCbZrbZtbZsbUCaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacbZubXXbXXbZvbWhbWhbXZbXZbZwbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydkWdkVdkXdjFdjHdkYdjFdkZdladjHdjydjydkjbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbQebUFbUFbUFbQebUIbYfbYebZzbZAbTkbZBbZCbZDbZEbZFbZFbZFbZGbUTbUTbUTbWxbUVbZHbYnbZIbYnbZJbUZbYpbYqbZKbYqbZLbUZbZMbZNbZObVfbZPbZQbZRbZSbZTbZUbZVbZWbZXbZYbZZcaacabcaccadbVkbTQbQVbQVcaebYJbYKcafcagcahbXjcaicajcElcalcamcancaocapcaqcarcIfcasbXscatbVAcaucavcawcaxcaycazcaAbZjbZfcaBbXEbXEbXEcaCcaDbZjbZkcaEbRAbZmbZmbPTcaFcaGbPXbEXcaHcaIcaJbUAcaKcaLcaMcaNcaOcaPcaQbUCcaRcaScaTbUCbUAbUAbUAbUAbUAbUAbUAbUAbikbikbikbikbikaabbikbikbikbikbikbikbikcaUbWhbZubWhbWhbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdkkdjydjydjydjydjydjydjydjydjydjydkjbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbTgbWjbYbbWkbTgbUIbUIbUIbOVcaYcaZcaZcaZbOVbOVbUTcbacbacbbcbcbUTcbdcbebUVbZHbYnbYnbYncbfbUZbYpbYqbYqcbgcbhcbicbjcbkcblbVfbVfbVfbVfbVfcbmbVfbVfcbncbobVkbVkcbpbVkbVnbVkbVkbPlcbqcbqbPlccicbrcbscbtcbucbvcbwcbxcbycbzcbAcbBcaocapcbCcbDcbEcbFcbGcbHbVAcbIcbJcbKcbLcbMcbNcbOcbPcbQcbPcbRcbRcbRcbPcbScbPcbPcbTcbUbZmbZmbPTcbVbZnbPXcbWcbXcbYcbZccaccbccccccccdcceccfccgcckccjcdqcclcfeccmccnccoccpccqccrccscctaabaabaabaabaabaabaabaabbikbikbikbikbikbWgbWhccuccvccvbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbYcbOTbYgbOTbZxbikaabbikbOVbOVbUIbUIbUIbOVbikbUTccAccBccCccDbZFccEccFbUVccGccHccIbYnccJccKccLccMccNccOccPbUZccQccRccSccTccUccUccUccUccVccWccXccYccYccZccZcdacdbcdcbVibPlcddcdecdfcdgcdhbYKcdicbtcdjcdkcdlcdmbSwcdncdocdpcffcdrcdrcdscdrcdrcdrcdtbVAcducdvcdwcdxcdycdzcdAcbPcdBcdCcdDcdEcdFcdCcdGcdHcdCcdIcdJbRBbPTbPTcdKcdLcdMcdNcdOcdPcdQcdRcdScdTcdUcdVcdWcdXcdYcdZceacebceaceccebcebcebcedceecefcegcehaabbikbikbikbikaabbikbikbikbikbikbikbikbWhbWhceibXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbYcbOTbYgbOTbZxbikaabbikbOVbOVbUIbUIbUIbOVbikbUTccAccBccCccDbZFccEccFbUVccGccHdmcbYnccJccKccLccMccNccOccPbUZccQccRccSccTccUccUccUccUccVccWccXccYccYccZccZcdacdbcdcbVibPlcddcdecdfcdgcdhbYKcdicbtcdjcdkcdlcdmbSwcdncdocdpcffcdrcdrcdscdrcdrcdrcdtbVAcducdvcdwcdxcdycdzcdAcbPcdBcdCcdDcdEcdFcdCcdGcdHcdCcdIcdJbRBbPTbPTcdKcdLcdMcdNcdOcdPcdQcdRcdScdTcdUcdVcdWcdXcdYcdZceacebceaceccebcebcebcedceecefcegcehaabbikbikbikbikaabbikbikbikbikbikbikbikbWhbWhceibXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabcejbUTbUTbUTcekbUTbUTcelbUVcemcenceocepceqcercescetceucevcewccKcexceycezceAceBceBceBceBceCceDceEceFceGceFceHceIceJceKchvceMceNceOcePceQceRceSceTceUceVceWceXceYceZcfacfbcfccfgbMmbMmcfichOcgHceYchVcfjcfjcfkcfjcflcfmcfncfocbPcfpcfqcfrcfscfrcftcfucfvcdCbPTcfwbPTbPTcfxcfybZnbBxbEXbUAcfzbUAbUAcfAcfBcfCcfDcfEcebcfFcfGcfHcdUcfHcdUcfIcdUcdUbUAcfJcfKcfLcfMaabaabaabaabaabaabaabaabbikbikbikbikbikbWhbXZbXZbXZbXZbXZbXZcfNbXZcfObXZbXZbXZbXZbXZbWhbWhaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikcejcfPbVccqsbUTcfSbUVcfTcfUcfVbZHcfWcfXcfYbYpcfZcgacgbcfXcgccgdcgecgfcgfcggcghcgicgjcgkcglcgmbGycgnbVicgobGybGycgpcgqcgrcgscgtceQcgucgvcgwcgxcgycgzbMVcgBcgCcgzcgzcgDcgEcgEcgEcgEcgEcgGcgFciOcgJcgJcgKcgLcgMcgNcgOcgPcbPcgQcgRcgScgTcgScgUcgVcfrcgWcgXcgYbBxcgZbBxcfybZnbBxbEXchachbchcbUAbUAbUAbUAbUAchdcdUchechfcfIcdUchgcdUbZpcdUchhbUAchichjchkbUAaabbikbikbikbikaabbikbikbikbikbikbikbikbWhchlchlchlchlchlchlchmbXZchnchlcfObXZbXZbXZbXZbWhaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikcejchocfQchpbUTcfSchrchrchrchrchrchrbUZbUZbUZbUZbUZbUZbUZchschtchucWpchwchxchychychzchAcglbGybGychBchCchDbGybGybGycqOchFchGceOchHchIchJcgEchKchLchMbSqchLchNcfdcfdcfdcjncjlcjlcjlcjlckacgIbSqclPchPchQchRchSchTchUclQcbPchWchXcfrchYcfrchZciacibciccidciecifbBxcigcfybZncihbEXbFeciicijcikbwobxXbxXbUAcilcimcinciocipciqcirciscitciucivbUAciwciycixcizbikbikbikbikaahbikbikbikbikbikbikbikbikciAbXXbXXbXXbXXbXXbXXbXXciBciCbXZbXZbXZbXZciDbYabWhaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 46b1662d8d6..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) @@ -314,7 +314,7 @@ "gb" = (/obj/structure/table,/obj/machinery/kitchen_machine/microwave/upgraded,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/ninja/holding) "gc" = (/obj/structure/table,/obj/item/clothing/head/that{pixel_x = 4; pixel_y = 6},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/ninja/holding) "gd" = (/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) -"ge" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) +"ge" = (/obj/structure/stool,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "gf" = (/obj/item/device/camera,/turf/unsimulated/beach/sand,/area/ninja/holding) "gg" = (/obj/structure/toilet{dir = 8},/obj/structure/window/reinforced/tinted{dir = 1},/obj/machinery/door/window{dir = 8; name = "Tactical Toilet"; opacity = 1; req_access_txt = "150"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/syndicate_mothership) "gh" = (/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor/plating/airless,/area/syndicate_mothership) @@ -343,8 +343,8 @@ "gE" = (/obj/structure/table,/obj/item/weapon/lighter/zippo,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/ninja/holding) "gF" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/ninja/holding) "gG" = (/obj/structure/table,/obj/item/weapon/dice/d20,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/ninja/holding) -"gH" = (/obj/structure/stool{pixel_y = 8},/obj/item/clothing/head/bandana{pixel_y = -10},/obj/item/clothing/glasses/sunglasses,/turf/unsimulated/beach/sand,/area/ninja/holding) -"gI" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/beach/sand,/area/ninja/holding) +"gH" = (/obj/structure/stool,/obj/item/clothing/head/bandana{pixel_y = -10},/obj/item/clothing/glasses/sunglasses,/turf/unsimulated/beach/sand,/area/ninja/holding) +"gI" = (/obj/structure/stool,/turf/unsimulated/beach/sand,/area/ninja/holding) "gJ" = (/turf/simulated/floor/holofloor{dir = 8; icon_state = "green"},/area/holodeck/source_basketball) "gK" = (/obj/item/weapon/beach_ball/holoball,/turf/simulated/floor/holofloor,/area/holodeck/source_basketball) "gL" = (/turf/simulated/floor/holofloor{dir = 4; icon_state = "green"},/area/holodeck/source_basketball) @@ -364,7 +364,7 @@ "gZ" = (/obj/structure/stool,/turf/simulated/floor/holofloor{tag = "icon-carpet13-0 (EAST)"; icon_state = "carpet13-0"; dir = 4},/area/holodeck/source_meetinghall) "ha" = (/obj/structure/stool,/turf/simulated/floor/holofloor{tag = "icon-carpet9-0 (EAST)"; icon_state = "carpet9-0"; dir = 4},/area/holodeck/source_meetinghall) "hb" = (/turf/simulated/floor/beach/coastline,/area/holodeck/source_beach) -"hc" = (/obj/structure/stool{pixel_y = 8},/obj/machinery/computer/security/telescreen{name = "Entertainment monitor"; desc = "Damn, they better have /tg/thechannel on these things."; icon_state = "entertainment"; pixel_y = -30},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) +"hc" = (/obj/structure/stool,/obj/machinery/computer/security/telescreen{name = "Entertainment monitor"; desc = "Damn, they better have /tg/thechannel on these things."; icon_state = "entertainment"; pixel_y = -30},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "hd" = (/obj/machinery/vending/snack,/obj/structure/window/reinforced{dir = 4},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "he" = (/turf/unsimulated/beach/coastline,/area/ninja/holding) "hf" = (/obj/item/clothing/head/collectable/paper,/turf/unsimulated/beach/coastline,/area/ninja/holding) @@ -381,7 +381,7 @@ "hq" = (/obj/structure/table/holotable,/obj/item/clothing/gloves/boxing/hologlove{icon_state = "boxinggreen"; item_state = "boxinggreen"},/turf/simulated/floor/holofloor{dir = 6; icon_state = "green"},/area/holodeck/source_boxingcourt) "hr" = (/obj/machinery/vending/cigarette,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "hs" = (/obj/structure/table,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) -"ht" = (/obj/structure/stool{pixel_y = 8},/obj/machinery/light/spot,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) +"ht" = (/obj/structure/stool,/obj/machinery/light/spot,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "hu" = (/obj/machinery/vending/cola,/obj/structure/window/reinforced{dir = 4},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/ninja/holding) "hv" = (/turf/unsimulated/beach/water,/area/ninja/holding) "hw" = (/obj/machinery/light/spot,/turf/unsimulated/beach/water,/area/ninja/holding) @@ -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) @@ -627,15 +627,62 @@ "mc" = (/obj/item/trash/chips,/obj/machinery/light/spot,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/wizard_station) "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) -"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) -"ms" = (/turf/simulated/floor/plating/airless,/area/shuttle/syndicate_elite/mothership) +"mf" = (/obj/structure/stool,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_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) +"mn" = (/obj/structure/stool,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) +"mo" = (/obj/structure/stool,/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) +"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) "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) +"mw" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (EAST)"; icon_state = "fakewindows"; dir = 4},/area/trader_station/sol) +"mx" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (WEST)"; icon_state = "fakewindows"; dir = 8},/area/trader_station/sol) +"my" = (/obj/machinery/computer/shuttle/trade/sol,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mz" = (/obj/machinery/vending/snack,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mA" = (/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mB" = (/turf/unsimulated/floor{dir = 8; icon_state = "browncorner"},/area/trader_station/sol) +"mC" = (/obj/machinery/door/airlock/external{id_tag = "trade_sol_base"; name = "Docking Port"},/turf/unsimulated/floor/plating,/area/trader_station/sol) +"mD" = (/obj/docking_port/stationary{dir = 8; dwidth = 2; height = 11; id = "trade_sol_base"; name = "docking bay 2 at Jupiter Station"; width = 5},/turf/space,/area/space) +"mE" = (/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mF" = (/turf/unsimulated/floor{dir = 8; icon_state = "brown"},/area/trader_station/sol) +"mG" = (/turf/unsimulated/floor{dir = 1; icon_state = "browncorner"},/area/trader_station/sol) +"mH" = (/turf/unsimulated/wall/fakeglass{icon_state = "fakewindows"; dir = 1},/area/trader_station/sol) +"mI" = (/obj/machinery/light{dir = 1; in_use = 1},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mJ" = (/obj/structure/stool/bed/chair/comfy/brown,/obj/effect/landmark{name = "traderstart_sol"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mK" = (/turf/unsimulated/wall/fakeglass{icon_state = "fakewindows2"; dir = 1},/area/trader_station/sol) +"mL" = (/obj/structure/dispenser,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mM" = (/obj/structure/rack,/obj/effect/spawner/lootdrop/maintenance{lootcount = 4; name = "4maintenance loot spawner"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mN" = (/obj/structure/rack,/obj/effect/spawner/lootdrop/trade_sol_rare,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mO" = (/obj/structure/rack,/obj/effect/spawner/lootdrop/trade_sol_common,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mP" = (/obj/structure/table/woodentable,/obj/item/weapon/dice/d20,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mQ" = (/obj/structure/stool/bed/chair/comfy/brown{dir = 4},/obj/effect/landmark{name = "traderstart_sol"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mR" = (/obj/structure/table/woodentable,/obj/item/weapon/paper_bin,/obj/item/weapon/pen,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mS" = (/obj/structure/rack,/obj/item/weapon/storage/box/syndie_kit/space,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mT" = (/obj/structure/stool/bed/chair/comfy/brown{dir = 1},/obj/effect/landmark{name = "traderstart_sol"},/obj/machinery/light{dir = 4},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mU" = (/turf/unsimulated/wall/fakeglass{dir = 0; icon_state = "fakewindows"; tag = "icon-fakewindows (EAST)"},/area/trader_station/sol) +"mV" = (/obj/machinery/light,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mW" = (/obj/machinery/door/airlock{name = "Toilet"; req_access_txt = "0"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mX" = (/obj/machinery/light{dir = 8},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"mY" = (/obj/structure/urinal{pixel_y = 28},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"mZ" = (/obj/item/weapon/mop,/obj/structure/mirror{pixel_x = 28},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"na" = (/obj/structure/mopbucket,/obj/machinery/light{dir = 1},/obj/item/weapon/soap,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"nb" = (/turf/unsimulated/floor{icon_state = "browncorner"},/area/trader_station/sol) +"nc" = (/turf/unsimulated/floor{icon_state = "brown"},/area/trader_station/sol) +"nd" = (/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"ne" = (/obj/structure/mirror{pixel_x = 28},/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"nf" = (/turf/unsimulated/wall/fakeglass{icon_state = "fakewindows"; dir = 8},/area/trader_station/sol) +"ng" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows2 (WEST)"; icon_state = "fakewindows2"; dir = 8},/area/trader_station/sol) +"nh" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (NORTHEAST)"; icon_state = "fakewindows"; dir = 5},/area/trader_station/sol) +"ni" = (/turf/unsimulated/wall{desc = "It opens and closes."; icon = 'icons/obj/doors/Doormining.dmi'; icon_state = "door_closed"; name = "Docking Bay 2"},/area/trader_station/sol) "nj" = (/turf/unsimulated/wall,/area/syndicate_mothership) +"nk" = (/obj/structure/toilet{dir = 8},/obj/structure/window/reinforced/tinted{dir = 1},/obj/machinery/door/window{dir = 8; name = "Toilet"; opacity = 1; req_access_txt = "0"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/trader_station/sol) +"nl" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows2 (NORTH)"; icon_state = "fakewindows2"; dir = 1},/area/trader_station/sol) +"nm" = (/obj/machinery/light{dir = 4},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/trader_station/sol) +"nn" = (/obj/docking_port/stationary/transit{dir = 8; dwidth = 2; height = 11; id = "trade_sol_transit"; name = "trade_sol in transit"; turf_type = /turf/space/transit/horizontal; width = 5},/turf/space/transit/horizontal,/area/space) "oB" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (WEST)"; icon_state = "fakewindows"; dir = 8},/area/syndicate_mothership) "oC" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (EAST)"; icon_state = "fakewindows"; dir = 4},/area/syndicate_mothership) "oH" = (/obj/structure/table,/obj/item/weapon/storage/fancy/crayons,/obj/item/weapon/storage/fancy/crayons,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/syndicate_mothership) @@ -646,13 +693,11 @@ "oQ" = (/obj/machinery/vending/syndisnack,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "oR" = (/obj/machinery/vending/syndicigs,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pa" = (/obj/structure/noticeboard{pixel_x = -32},/obj/item/weapon/paper/syndimemo,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) -"pb" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pc" = (/mob/living/simple_animal/pet/fox/Syndifox,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pd" = (/obj/effect/decal/warning_stripes/southeastcorner,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pe" = (/obj/effect/decal/warning_stripes/south,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pl" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pm" = (/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/food/drinks/cans/beer{pixel_x = -2; pixel_y = 5},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) -"po" = (/obj/structure/stool{pixel_y = 8},/obj/effect/landmark{name = "Syndicate-Spawn"},/obj/effect/decal/warning_stripes/east,/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/syndicate_mothership) "pp" = (/obj/machinery/computer/telecrystals/uplinker,/turf/unsimulated/floor{icon_state = "floor4"},/area/syndicate_mothership) "pu" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (NORTHWEST)"; icon_state = "fakewindows"; dir = 9},/area/syndicate_mothership) "pv" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows2 (WEST)"; icon_state = "fakewindows2"; dir = 8},/area/syndicate_mothership) @@ -688,7 +733,6 @@ "qL" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/syndicate_mothership) "qM" = (/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/syndicate_mothership) "qX" = (/turf/unsimulated/wall/fakeglass{dir = 8; icon_state = "fakewindows3"; tag = "icon-fakewindows (WEST)"},/area/syndicate_mothership) -"qY" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/syndicate_mothership) "re" = (/obj/structure/closet/syndicate/personal,/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/syndicate_mothership) "rf" = (/obj/structure/table,/obj/item/weapon/gun/energy/ionrifle,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/syndicate_mothership) "rE" = (/turf/unsimulated/wall,/area/start) @@ -727,10 +771,8 @@ "sx" = (/obj/machinery/door/airlock/centcom{name = "Living Quarters"; opacity = 1; req_access_txt = "102"},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) "sy" = (/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) "sz" = (/obj/machinery/atm{pixel_y = 24},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) -"sA" = (/obj/structure/stool{pixel_y = 8},/obj/structure/sign/poster/legit{pixel_y = 32},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) "sB" = (/obj/item/weapon/reagent_containers/food/condiment/peppermill{pixel_x = 2; pixel_y = 6},/obj/structure/table,/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) "sC" = (/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/obj/structure/table,/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) -"sD" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) "sE" = (/turf/unsimulated/floor{icon_state = "bar"; dir = 2},/area/centcom/control) "sF" = (/obj/structure/closet/secure_closet/bar{req_access = null; req_access_txt = "102"},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "sG" = (/obj/structure/reagent_dispensers/beerkeg,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) @@ -742,7 +784,6 @@ "sM" = (/obj/item/weapon/reagent_containers/food/drinks/cans/beer,/obj/structure/table,/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) "sN" = (/obj/structure/table,/obj/machinery/juicer{pixel_y = 6},/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) "sO" = (/obj/structure/piano,/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) -"sP" = (/obj/structure/stool{pixel_y = 8},/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/unsimulated/floor{tag = "icon-redyellowfull"; icon_state = "redyellowfull"},/area/centcom/control) "sQ" = (/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "sR" = (/obj/structure/closet/secure_closet/freezer/meat{req_access_txt = "102"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/centcom/control) "sS" = (/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/centcom/control) @@ -751,7 +792,6 @@ "sV" = (/obj/structure/table,/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "sW" = (/obj/machinery/door/airlock/centcom{name = "Freezer"; opacity = 1; req_access_txt = "102"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/centcom/control) "sX" = (/turf/unsimulated/wall,/area/centcom/specops) -"sY" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "sZ" = (/obj/structure/table,/obj/machinery/processor{pixel_x = 0; pixel_y = 10},/turf/unsimulated/floor{icon_state = "cafeteria"; dir = 2},/area/centcom/control) "ta" = (/obj/machinery/mech_bay_recharge_port/upgraded,/turf/unsimulated/floor{icon_state = "bot"},/area/centcom/specops) "tb" = (/obj/machinery/camera{c_tag = "CentComm Special Ops. Assault Armor North"; dir = 2; network = list("ERT","CentComm")},/obj/mecha/combat/marauder/seraph/loaded,/turf/unsimulated/floor{icon_state = "delivery"; dir = 6},/area/centcom/specops) @@ -907,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/m2411,/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) @@ -1005,7 +1044,6 @@ "zd" = (/obj/machinery/vending/boozeomat,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/centcom/evac) "ze" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/centcom/evac) "zf" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/drinks/cans/cola,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/centcom/evac) -"zg" = (/obj/structure/stool{pixel_y = 8},/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/centcom/evac) "zh" = (/obj/machinery/computer/card,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/centcom/evac) "zi" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/centcom/evac) "zj" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/centcom/evac) @@ -1109,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) @@ -1136,12 +1173,12 @@ "EY" = (/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/turf/unsimulated/wall{dir = 4; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5"; name = "window"; opacity = 0; tag = "icon-window5 (EAST)"},/area/admin) "EZ" = (/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/turf/unsimulated/wall{dir = 2; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5"; name = "window"; opacity = 0; tag = "icon-window5"},/area/admin) "Fa" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "ADMINCHEMLOCKDOWN"; name = "Security Doors"; opacity = 0},/obj/machinery/door/airlock/hatch{name = "Chem Lab"; req_access_txt = "0"},/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) -"Fb" = (/obj/structure/rack,/obj/item/ammo_box/magazine/m762,/obj/item/ammo_box/magazine/m762,/obj/item/ammo_box/magazine/m762,/obj/item/ammo_box/magazine/m762,/obj/item/weapon/gun/projectile/automatic/l6_saw,/obj/item/weapon/gun/projectile/automatic/l6_saw{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"Fb" = (/obj/structure/rack,/obj/item/ammo_box/magazine/mm556x45,/obj/item/ammo_box/magazine/mm556x45,/obj/item/ammo_box/magazine/mm556x45,/obj/item/ammo_box/magazine/mm556x45,/obj/item/weapon/gun/projectile/automatic/l6_saw,/obj/item/weapon/gun/projectile/automatic/l6_saw{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Fc" = (/obj/structure/rack,/obj/item/weapon/gun/projectile/automatic/proto,/obj/item/weapon/gun/projectile/automatic/proto{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Fd" = (/obj/structure/rack,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/magazine/m556,/obj/item/ammo_box/a40mm,/obj/item/ammo_box/a40mm,/obj/item/ammo_box/a40mm,/obj/item/ammo_box/a40mm,/obj/item/weapon/gun/projectile/automatic/m90,/obj/item/weapon/gun/projectile/automatic/m90{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Fe" = (/obj/structure/mirror{dir = 4; pixel_x = 0; pixel_y = -32},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Ff" = (/obj/machinery/optable,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) -"Fh" = (/obj/structure/table,/obj/item/weapon/gun/energy/pulse_rifle/pistol,/obj/machinery/door_control{desc = "A remote control switch to lock down the admin lab."; icon_state = "doorctrl0"; id = "ADMINCHEMLOCKDOWN"; name = "Lockdown"; pixel_y = 24; req_access_txt = "0"},/turf/unsimulated/floor{dir = 9; icon_state = "carpetside"},/area/admin) +"Fh" = (/obj/structure/table,/obj/item/weapon/gun/energy/pulse/pistol,/obj/machinery/door_control{desc = "A remote control switch to lock down the admin lab."; icon_state = "doorctrl0"; id = "ADMINCHEMLOCKDOWN"; name = "Lockdown"; pixel_y = 24; req_access_txt = "0"},/turf/unsimulated/floor{dir = 9; icon_state = "carpetside"},/area/admin) "Fi" = (/turf/unsimulated/floor{dir = 1; icon_state = "carpetside"},/area/admin) "Fj" = (/obj/machinery/computer/secure_data,/obj/item/weapon/paper/sop,/turf/unsimulated/floor{dir = 5; icon_state = "carpetside"},/area/admin) "Fk" = (/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/turf/unsimulated/wall{dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/admin) @@ -1163,7 +1200,7 @@ "FA" = (/obj/structure/table,/obj/structure/window/reinforced,/obj/item/weapon/paper_bin,/obj/item/weapon/pen,/turf/unsimulated/floor{dir = 10; icon_state = "carpetside"},/area/admin) "FB" = (/obj/structure/table,/obj/machinery/door/window/southleft{name = "security checkpoint"; req_access_txt = "0"},/turf/unsimulated/floor{dir = 2; icon_state = "carpetside"},/area/admin) "FC" = (/obj/structure/table,/obj/structure/window/reinforced,/obj/machinery/recharger,/turf/unsimulated/floor{dir = 6; icon_state = "carpetside"},/area/admin) -"FD" = (/obj/machinery/recharger/wallcharger{pixel_x = 30},/obj/structure/rack,/obj/item/weapon/gun/energy/pulse_rifle/pistol/m1911,/obj/item/weapon/gun/energy/pulse_rifle/pistol/m1911{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"FD" = (/obj/machinery/recharger/wallcharger{pixel_x = 30},/obj/structure/rack,/obj/item/weapon/gun/energy/pulse/pistol/m1911,/obj/item/weapon/gun/energy/pulse/pistol/m1911{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "FE" = (/obj/structure/table,/obj/item/weapon/tank/oxygen/yellow,/obj/random/bomb_supply,/obj/item/clothing/under/rebeloutfit,/obj/item/clothing/suit/poncho/ponchoshame,/obj/item/clothing/head/sombrero/shamebrero,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/admin) "FF" = (/obj/machinery/door/airlock/hatch{name = "Tool Storage"; req_access_txt = "0"},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/admin) "FG" = (/obj/structure/table,/obj/item/weapon/FixOVein,/obj/item/weapon/retractor,/obj/item/weapon/cautery,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/admin) @@ -1174,8 +1211,8 @@ "FL" = (/turf/simulated/wall/r_wall,/area/adminconstruction) "FM" = (/obj/structure/rack,/obj/item/weapon/gun/energy/meteorgun,/obj/item/weapon/gun/energy/meteorgun{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "FN" = (/obj/structure/rack,/obj/item/weapon/twohanded/knighthammer{pixel_x = -3; pixel_y = 3},/obj/item/weapon/twohanded/mjollnir,/obj/item/weapon/twohanded/singularityhammer{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"FO" = (/obj/structure/rack,/obj/item/weapon/gun/energy/crossbow,/obj/item/weapon/gun/energy/crossbow{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"FP" = (/obj/machinery/recharger/wallcharger{pixel_x = 30},/obj/structure/rack,/obj/item/weapon/gun/energy/pulse_rifle,/obj/item/weapon/gun/energy/pulse_rifle{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"FO" = (/obj/structure/rack,/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow,/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"FP" = (/obj/machinery/recharger/wallcharger{pixel_x = 30},/obj/structure/rack,/obj/item/weapon/gun/energy/pulse,/obj/item/weapon/gun/energy/pulse{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "FQ" = (/obj/structure/table,/obj/random/tool,/obj/item/clothing/gloves/color/yellow,/obj/item/weapon/pinpointer/advpinpointer,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/admin) "FR" = (/obj/structure/table,/obj/item/weapon/grenade/syndieminibomb{pixel_x = 4; pixel_y = 2; pixel_z = 0},/obj/item/weapon/grenade/syndieminibomb{pixel_x = -1},/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/admin) "FS" = (/obj/structure/table,/obj/machinery/recharger{pixel_y = 0},/obj/item/toy/cards/deck/syndicate/black,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/admin) @@ -1199,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) @@ -1208,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) @@ -1342,68 +1376,68 @@ 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 -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikjdjdihihjeihihaNaNisiQjfjfjfiQitjgjhitaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatatatatataFaGaGaGaGaGaGaGaHatataIatataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihjAjAikjBjCjDihjEjejFihaNaNisiQjGjHjIiQititititititititititititaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataJaJaJaKauauauauauauauauaKaKaKauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkbikikjBkckdihkekfkgihaNaNisiQkhjHjIiQkikjkkklkmknkjkokpkqkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataKauauauauauauauaMauauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkCkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkJikikikikihihihihihihaNaNisiQkhjHjIiQkKkjknknkLknkjknkrkrkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatbhauauauauauaubibibiauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkTkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkWkXkYkZiklalblcldleihaNaNisiQjHjHjHlflglhknknkLknkjkokpkrkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatbhauauauauaubjbibibibjauauauauauaKataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlolplqikikiklrlsltluihaNaNisiQlvjHjHlwlglhknknknknlxknkrkrkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatbhauauauauauaubjbjbjauauauauauauauataNaNaNaNaNaNaNaNaNbZbZbZlBlBlBlBlBlClDjpjpjpjpjpjplEjpjpjpjpjpjplDlClBlBlBlBlBbZbZbZaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlGlplqikikiklHlIlHlIihaNaNisiQlJjHlKiQkKkjknknkLknkjkokpkrkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauauauauauauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZlWlWlWlWlWbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZlXlXlXlXlXbZaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlomambkJmcladclumeddihaNaNismgmhmimhmjkikjknknkLknkjknkrkrkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauaKaJaJaKauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNisaNmgmsmjaNmtkjknknmuknkjkokpmvkrksaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatatbkatatatatatatatatatatatatatbkatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNititititititititititititititititititaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckbmckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckaackckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatatblblatatatatatatatatatatatatatblblatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckaEckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababacababababababababababababababababababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbnaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababababacabababababababababababababababababababababababababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababadababababababababababababaeababacabafababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckawckckckckckaxckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababababababababababafabafababababafabababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababababababababacababadababacafabadabababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababababababagagagagagagagababababahababacabahabababacabababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaiaNaNaNaNaNaNaNaiacabababababajagagakagakababafabnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalabababacamnjnjoBoCnjnjanagagagnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalabababaonjnjoHoIoIoJnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalababadaonjaLoOoOoOoOoPoQoRnjfYjMfZnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaiaNaNaNaNaNaNaNaiababababaSnjpaoOpbpbpcoOpdpepWpXpXganjnjnjnjnjnjnjnjnjnjnjnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababaNaNaNaNaNaTagagababaUamnjplpbpmjNpboOpoppnjpXggnjnjghgjgigxgxhggxgxhxhGnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababaNaNaNaNaNpupvpvpvpvpvoCnjoOpbpwpxpboOpoppnjnjnjnjnjgjgiiuiwiviFiviHiGhxnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaiaNaNaNaNaNaNaNaNaNpypzpApzpzpzpzpCoOJboOoOoOoOpoppnjnjnjnjnjgjiIiwiviJiSiKiviHiTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaNaNaNaNaNaNaNaNaNaNpFaVoBpvpvpvoCnjpHpbpbpboOoOpoppoBpvpvpvpvpvpviviJiSiUiSiKiviTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikikikikixiyizihaNaNisaNaNaNaNaNitaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauayauataNaNaNaNaNaNaNaNaNaNaNbZdEdEdEdEdEbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZdFdFdFdFdFbZaNaNaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihiLiLikikikiMihiNiOiPihaNaNisaNaNaNaNaNititititaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNatauauauataNaNaNaNaNaNaNaNaNbZbZbZiZiZiZiZiZjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaiZiZiZiZiZbZbZbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihikikikikjdjdihihjeihihaNaNisaNaNaNaNaNitjgjhitaNaNaNaNaNaNaNaNaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmxmwatatatatataFaGaGaGaGaGaGaGaHatataIatataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihjAjAikjBjCjDihjEjejFihaNaNisaNaNaNaNaNititititititititititititaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmzmyataJaJaJaKauauauauauauauauaKaKaKauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +ckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkbikikjBkckdihkekfkgihaNaNisaNaNaNaNaNkikjkkklkmknkjkokpkqkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmBmAataKauauauauauauauaMauauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkCkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkJikikikikihihihihihihaNaNisaNaNaNaNaNkKkjknknkLknkjknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNmDmCmFmEatbhauauauauauaubibibiauauauauauauaJataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpkBkTkBjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihkWkXkYkZiklalblcldleihaNaNisaNaNaNaNaNlgiBknknkLknkjkokpkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmGmEatbhauauauauaubjbibibibjauauauauauaKataNaNaNaNaNaNaNaNaNbZjljmbZbZbZbZbZjnjojpjpjpjpjpjpjpjpjpjpjpjpjpjqjnbZbZbZbZbZjmjrbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlolplqikikiklrlsltluihaNaNisaNaNaNaNiClgiBknknknknlxknkrkrkrksaNaNmraNaNaNaNaNaNaNaNaNaNaNmrmEmEatbhauauauauauaubjbjbjauauauauauauauataNaNaNaNaNaNaNaNaNbZbZbZlBlBlBlBlBlClDjpjpjpjpjpjplEjpjpjpjpjpjplDlClBlBlBlBlBbZbZbZaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlGlplqikikiklHlIlHlIihaNaNisaNaNaNaNaNkKkjknknkLknkjkokpkrkrksaNaNmrmrmrmrmrmrmrmrmrmrmrmrmrmEmEatauauauauauauauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZlWlWlWlWlWbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZbZlXlXlXlXlXbZaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihlomambkJmcladclumeddihaNaNisaNaNaNaNaNkikjknknkLknkjknkrkrkrksaNaNaNaNaNaNmHmEmEmEmImEmEmEmEmEmJatauauaKaJaJaKauauauauauauauauauauauataNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZbZbZaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNihihihihihihihihihihihihaNaNisaNaNaNaNaNmtkjknknmuknkjkokpmvkrksaNaNaNaNaNaNmKmEmLmNmMmOmOmMmEmQmPatatbkatatatatatatatatatatatatatbkatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNititititititititititititititititititaNaNaNaNaNaNmKmEmEmEmEmEmEmEmEmQmRatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckbmckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNmKmEmMmOmOmOmSmMmEmEmTatblblataNaNaNaNaNaNaNaNaNaNaNatblblataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckaackckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNmUmVmEmEmEmEmEmEmEmEatatblblatatatatatatatatatatatatatblblatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckaEckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababacababababababababababababababababababnjaNaNaNaNaNmrmrmrmWmrmXmOmOmMmEmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbnaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababababacabababababababababababababababababababababababababnjaNaNaNaNaNmrmYnamZmrmEmEmEmEnbncataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababadababababababababababababaeababacabafababnjaNaNaNaNaNmrndndnemrnfngngngnhniataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckawckckckckckaxckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababababababababababafabafababababafabababnjaNaNaNaNaNmrndnkmrmraNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababababababababababababacababadababacafabadabababnjaNaNaNaNaNmrmrmrmrmraNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababababababagagagagagagagababababahababacabahabababacabababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaiaNaNaNaNaNaNaNaiacabababababajagagakagakababafabnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNnlnmataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalabababacamnjnjoBoCnjnjanagagagnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalabababaonjnjoHoIoIoJnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaNaNaNaNaNaNaNaNaNalababadaonjaLoOoOoOoOoPoQoRnjfYjMfZnjaNaNaNaNaNaNaNaNaNaNaNaNnlmEataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababaiaNaNaNaNaNaNaNaiababababaSnjpaoOmfmfpcoOpdpepWpXpXganjnjnjnjnjnjnjnjnjnjnjnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababaNaNaNaNaNaTagagababaUamnjplmfpmjNmfoOmkppnjpXggnjnjghgjgigxgxhggxgxhxhGnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabababababababaNaNaNaNaNpupvpvpvpvpvoCnjoOmfpwpxmfoOmkppnjnjnjnjnjgjgiiuiwiviFiviHiGhxnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaiaNaNaNaNaNaNaNaNaNpypzpApzpzpzpzpCoOJboOoOoOoOmkppnjnjnjnjnjgjiIiwiviJiSiKiviHiTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaNaNaNaNaNaNaNaNaNaNpFaVoBpvpvpvoCnjpHmfmfmfoOoOmkppoBpvpvpvpvpvpviviJiSiUiSiKiviTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaNaNaNaNaNaNaNaNaNaNaNaWaNaiababaXnjpRpSpTpSjOoOpUpViWiViViXiViViWiFiSiYjjjiiSiFiTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjaYabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaZabaonjqfqgqhqiqjoOoOoOoBpvpvpvpvpvpviviJiSjkiSiSiviTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaNaNaNaNaNaNaNaNaNaNaNaNaNaNalabaonjnjppqtqrqunjqwoOnjnjnjnjnjgjiIjsiviJiSiKivjtiTnjaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjababaNaNaNaNaNaNaNaNaNaNaNaNaNaNanabababnjnjnjnjnjnjqDqDqEqFqGqHnjgjjvjujsivjwivjtjxjynjaNaNaNatatatatatatatatatatatatatatatatatatatatataNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaiabababbababbaXnjqLqMqMqMqMqMnjjzgjjvjJjJjKjJjJjyjznjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNalababacababaoqXqMqMqMqMqMqYnjnjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNalababacababaoqXqMqMqMqMqMmlnjnjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNalababadbcakamnjrerererererfnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNalababaonjnjnjnjnjnjnjnjnjnjnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckckaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNnjabaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbdabababnjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1459,12 +1493,12 @@ aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqsqsqsqsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqsrssstsqsqsqsqsusvsvsvsqsqsqsqsqsqsqsqsqsqsqsqsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqswsssssxsyszsAsBsCsDsEsEsysysqsFsGsHsIsqsJsKsLsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqsqsqsqsqsysEsDsMsNsDsEsEsOsPsqsQsQsQsQsqsRsSsTsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqswsssssxsyszmmsBsCmnsEsEsysysqsFsGsHsIsqsJsKsLsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsqsqsqsqsqsysEmnsMsNmnsEsEsOmosqsQsQsQsQsqsRsSsTsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsvsEsEsEsEsEsEsEsEsysysqsQsUsVsVsqsqsWsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsqaNaNaNsvsEsEsEsEsEsEsEsEsEsEsusQsYsYsQsQsQsQsZsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXtatbtctdtdtesqsqsqsqsqsEsEsDsMsCsDsEsEsEsEsEsQsQsQsQtfsQsQtgsqsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNthtitititititititititjtktitititjtltmtntdtdtdsqsrssstsqtosEsDsMtpsDsEsEsEsEsutqsQsQsQtrsQsQtssqsqsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsqaNaNaNsvsEsEsEsEsEsEsEsEsEsEsusQmpmpsQsQsQsQsZsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXtatbtctdtdtesqsqsqsqsqsEsEmnsMsCmnsEsEsEsEsEsQsQsQsQtfsQsQtgsqsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNthtitititititititititjtktitititjtltmtntdtdtdsqsrssstsqtosEmnsMtpmnsEsEsEsEsutqsQsQsQtrsQsQtssqsqsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXtatttutdtdtdsqswsssssxsEsEsEsEsEsEsEsEsEsEsqsusususususususqsqdWdXsqsqsqsqsqsqsqsqsqsqsqsqsqdVaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNthtitititititititititvtktitititvtwtmtntdtdtdsqsqsqsqsqsqsqtxsqsqsqsqsEsEtysqtztztztztztztzsudZdYebeasuecegefeieheCemeTeSeVeUeWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXtatttutdtdtAsqtBtCtDsqtEtFtFtFtFtGsqsEsEtHsqtztztztztztztzsufbfatLfcsufdflfefnfmfpfofrfqfEfsfFaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1482,7 +1516,7 @@ aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXvkvkvkvxujujujvyvyujujujvzvdvAvBvCbesXvEtTuEtRtRvFtRtRtZsqsqsusususususqsqtQtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXvGvHsXvIvJujujujujvLujsXvdvMvNvOvPsXvQtRtRtRtZsutQtRtStTtTtTtTtTtTtTtTtTuEtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNsXsXsXsXsXsXsXsXbfbfsXsXsXvSvTvUvVvdsXvWtRtRtRvXsutQtRtRtRtRtRtRtRtRtRtRtRtRtRtZsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwbwcwdwbwesXwfwgwhwiwjsXwkudududwlsuwmudududududuetRucudududududwnsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwbwcwdwbwesXiDwgwhwiwjsXwkudududwlsuwmudududududuetRucudududududwnsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwrwswtwrwesXsXsXsXsXsXsXsqsqsqsqsqsqsqsqsqsqsqsqsqwusqsqsqsqsqsqsqsqaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwCwDwEwFwGwCwHwIwJwKwLwMwNwOwPwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwCwCwCwIwIwIwIwIwIwKxcxdxexdxfwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1496,9 +1530,9 @@ aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbW aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNxdxmxXxYwNxXxYxfyGytyGwNwNwNyHxzxzxzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyiyvyvyKyLyMyNyMyOyMyNyMyPyKyvyvyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKxyyQyQyQyRwNxfypxdwKyqwNwNwNwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNySyFyvyTyMyNyNyNyNyNyNyNyMyTyvywyUaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKwKwKwKxdxdwKwKxmwNxfxdxLwKwNwNwNwNwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNySylyoyWyXyYyZyNzazbyNzcykylyUaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKzdzezfzgzezewKxmwNxfypxdwKyqwNwNwNwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizhzizjzkyNzazbyNyyyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKzlzezmzgzezeznxmwNxfyGytyGwNwNwNygxzxzxzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizqzrzryZyNzazbyNyMyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKztzezuzgzezewKxyyQzvwKwKwKyqwNwNyrcnytcnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizxzrzrzyyNyMyMyNyNaBaCaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKzdzezfmqzezewKxmwNxfypxdwKyqwNwNwNwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizhzizjzkyNzazbyNyyyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKzlzezmmqzezeznxmwNxfyGytyGwNwNwNygxzxzxzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizqzrzryZyNzazbyNyMyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKztzezumqzezewKxyyQzvwKwKwKyqwNwNyrcnytcnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizxzrzrzyyNyMyMyNyNaBaCaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNwKztzezezezezewKwKzBwKwKxLwKwNwNwNyHxzxzxzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNykylylylyoyNzazbyNzHyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcjcjcjcjcjcjcjcjcjcjcjcjcjcjcjytytytwKxLwKxZxZxZxZwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNyizOzOzPzQyNzazbyNzRyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNcjcpcpcpcpcpcpcpcpcpcpcpcpcpcqytytytwKxLwKxzxzxzxzwKaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNzVzWzWzWzXyNzazbyNyMyiaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1536,34 +1570,34 @@ aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbW aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtaNaNaNaNaNDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDtDwDxDyDyDyDzDwDuDvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDADBDCDDDEDFDGDHDADuaNaNaNaNaNaNDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDJDKDKDKDKDKDLDADwDMDwDMDwDMDwDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDODKDPcQDRDKDSDADTDKDUDKDVDWDXDYDADuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDZDKEaEbEcDKEdDADKDKDKDKDKDKDKEeDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfEgEhDKDKDKEhEiDAEjDKEkDKElDWDXDYEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwDKDKDKDwDwDADKDKDKDKDKDKDKEmDAEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDuaNDADwDwDMEoDMDwDwDwDwDwDMEpDMDwDwDwEnaNDtDwEqErErEsDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwEtDKDKDKDKDKDKDKDKDKDKDKDKEuDAEnaNDtDwEvEwExEyEwEzDwEAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEBDKECDKDKDKDKDKDKDKDKDKDKDKDKDKDKDAaNaNaNEDEEEFEwEwEwEGEDaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwDwDwDwDMEHDMDwDwDwDwDwEIDKDKDAaNaNaNEJEKEwEwEwEwELEJaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEnaNEMDAENEOEPDKDKEQERESETEuDADKDKDAaNaNDtDAEUEwEVEWEwEXDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWjLbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKDKDKDKDKDKDKEYDKDKDADwEZDwDwDwFaDwDwFaDwDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFbFcFdDKDKDKFeFeFeDKEHDKDKDAFfEwEwdfDADKDAFhFiFjDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKDKFkDwDwDwDwDADKDKDAEwEwFlFmDADKDAFnFoFpDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFqFrFsDKFtDAFuFvFwFxDADKDKDAFyEwEwFzDADKDAFAFBFCDNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKFDDAFEFvFvFvFFDKDKDAFGEwEwFHDADKDKDKDKDKEfaNaNaNaNDtDwFIFJFKDwDuaNaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFMFNFODKFPDAFQFvFRFSDADKDKDAFTFUEwEwFVDKDKDKDKDKDAaNaNaNDtDwFWFXFXFXFYDwDuaNaNaNaNaNaN -aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwDwDwDwDwDwDwDwGaDKDKGbDwDwDwDwDwDwDwDwGcDwDADuaNDtDwFWFXFXFXFXFXFYDADuaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDAGdGeGfGgGhGiGjGbDAGaDKDKDKDKDKDKGbDwDwDwDwDwGaDKGbDwDwGkDwFWFXFXFXGlFXFXFXFYDAaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIGmDKDKGnDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXFXGrGsGtFXFXFXGuaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNGvGwDKDKDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXGxGyGrGrGxFXFXGzaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfGADKDKGBDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKFkDwDwGkDwGCFXFXGxGxGxFXFXGDDAaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDAGEGFGGGHGIGJGKFkDAEIDKDKDKDKDKDKFkDwDwEIDKFkDwDwDwDAEnaNEMDwGCFXFXFXFXFXGDDAEnaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDwDwDwDwDwDwDwDwDwEIDKDKFkDwDwDwDwDwGLDwDwDwDADAaNaNaNEMDwGCFXFXFXGDDwEnaNaNaNaNaNaN -aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMaNaNaNaNaNaNaNaNaNDvDAGMGMDAaNDAFvGNFvFvFvGNFvDADAaNaNaNaNEMDwFIFJFKDwEnaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDtDwDxDyDyDyDzDwiEaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDADBDCDDDEDFDGDHDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDJDKDKDKDKDKDLDADuaNaNaNaNaNaNDvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDODKDPcQDRDKDSDADwDMDwDMDwDMDwDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDZDKDKDKDKDKEdDADTDKDUDKDVDWDXDYDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfEgDKEaEbEcDKEiDADKDKDKDKDKDKDKEeDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNiQDAiRDKDKDKDKDKjfDAEjDKEkDKElDWDXDYEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAjGEhDKDKDKEhjHDADKDKDKDKDKDKDKEmDADvaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDuaNDADwDwDMEoDMDwDwDwDwDwDMEpDMDwDwDwEnaNDtDwEqErErEsDwDuaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwEtDKDKDKDKDKDKDKDKDKDKDKDKEuDAEnaNDvDwEvEwExEyEwEzDwjIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEBDKECDKDKDKDKDKDKDKDKDKDKDKDKDKDKDAaNaNaNEDEEEFEwEwEwEGEDaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWnnbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDADwDwDwDwDwDMEHDMDwDwDwDwDwEIDKDKDAaNaNaNEJEKEwEwEwEwELEJaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEnaNEMDAENEOEPDKDKEQERESETEuDADKDKDAiEaNDtDAEUEwEVEWEwEXDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWjLbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKDKDKDKDKDKDKEYDKDKDADwEZDwDwDwFaDwDwFaDwDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFbFcFdDKDKDKFeFeFeDKEHDKDKDAFfEwEwdfDADKDAFhFiFjDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYDKDKDKDKkhFkDwDwDwDwDADKDKDAEwEwFlFmDADKDAFnFoFpDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFqFrFsDKFtDAFuFvFwFxDADKDKDAFyEwEwFzDADKDAFAFBFCDNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEYlfDKDKDKFDDAFEFvFvFvFFDKDKDAFGEwEwFHDADKDKDKDKDKEfaNaNaNaNDtDwFIFJFKDwDuaNaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAFMFNFODKFPDAFQFvFRFSDADKDKDAFTFUEwEwFVDKDKDKDKDKDAaNaNaNDtDwFWFXFXFXFYDwDuaNaNaNaNaNaN +aNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwDwDwDwDwDwDwDwDwGaDKDKGbDwDwDwDwDwDwDwDwGcDwDADuaNDtDwFWFXFXFXFXFXFYDADuaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDAGaGdGeGfGgGhGiGjGbDAGaDKDKDKDKDKDKGbDwDwDwDwDwGaDKGbDwDwGkDwFWFXFXFXGlFXFXFXFYDAaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIGmlhDKDKlvDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXFXGrGsGtFXFXFXGuaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNDKlwDKDKDKDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKDKGqFXFXFXFXFXGxGyGrGrGxFXFXGzaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfGAGvDKDKlJDKDKDKDKDKGoDKDKGpGpGpGpDKDKDKDKDKDKDKDKDKFkDwDwGkDwGCFXFXGxGxGxFXFXGDDAaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDAEIGEGFGGGHGIGJGKFkDAEIDKDKDKDKDKDKFkDwDwEIDKFkDwDwDwDAEnaNEMDwGCFXFXFXFXFXGDDAEnaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDwDwDwDwDwDwDwDwDwDwEIDKDKFkDwDwDwDwDwGLDwDwDwDADAaNaNaNEMDwGCFXFXFXGDDwEnaNaNaNaNaNaN +aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDvDAGMGMDAaNDAFvGNFvFvFvGNFvDADAaNaNaNaNEMDwFIFJFKDwEnaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDtDwDwDwDwGaDKDKDAaNDAGOFvFvGPFvFvGQDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKDKDKDKDAaNDAGRGPFvFvFvGPGSDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfDKDKDKDKDKDKDKDAaNDAGTFvFvGPFvFvGUDADAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN @@ -1580,7 +1614,7 @@ aNaNaNaNaNaNHjdHdHdHdHdHHjIdIeIeIeIeIeIeIeIeIeIeIeIeIeIfHjdIdIdIdIdIHjaNaNaNaNaN aNaNaNaNHjHjHjIhIhIhIhIhjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaIhIhIhIhIhHjHjHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNjUjWlLlNlMkajZaNjUjWlOlQlPkajZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfDKDKDKDKDKDKFkDAEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIkIkIkIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIoIoIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkwlRkxkxkxkAkzaNkwlSkxkxkxkAkzaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwDwDMIqDMDwDwEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIrIkIrIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIsIoIsIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkEkGlTkIlUkNkMaNkEkGlVkIlYkNkMaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDAItDKDKDKIuDAaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNHjIiIjIkIkIvIkIkIlImjcjcjcjcjcIwIxIwjcjcjcjcjcInIlIoIoIyIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkQkRkxkxkxkAkSaNkQkRkxkxkxkAkSaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKDKDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNHjIiIjIkIkIvIkIkIlImjcjcjcjcjcIwIxIwjcjcjcjcjcInIlIoIoIyIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkQkRkxkxkxkAkSaNkQkRkxkxkxkAkSaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDIDKDKDKDKlKDIaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIrIkIrIkIlImjcjcjcjcjcIwIzIwjcjcjcjcjcInIlIoIsIoIsIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNkUlikVlkljlmllaNkUlikVlkljlmllaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNDNIADKDKDKIBDNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjIiIjIkIkIkIkIkIlImjcjcjcjcjcjcjcjcjcjcjcjcjcInIlIoIoIoIoIoIjIpHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNlylnlAlzlFaNaNaNlylnlAlzlFaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEfICDKDKDKIDEfaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNHjHjHjIEIEIEIEIEjajbjcjcjcjcjcjcjcjcjcjcjcjcjcjbjaIEIEIEIEIEHjHjHjaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNFLFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFZFLaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNEMDwIFIGIHIIIJDwEnaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN diff --git a/_maps/map_files/cyberiad/z6.dmm b/_maps/map_files/cyberiad/z6.dmm index 104c590cccc..da5594a4405 100644 --- a/_maps/map_files/cyberiad/z6.dmm +++ b/_maps/map_files/cyberiad/z6.dmm @@ -648,7 +648,7 @@ "mx" = (/obj/structure/table,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot) "my" = (/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/engine,/area/syndicate_depot) "mz" = (/turf/simulated/floor/engine,/area/syndicate_depot) -"mA" = (/obj/structure/closet/crate{name = "munitions crate"},/obj/item/weapon/storage/box/donkpockets,/obj/item/ammo_box/magazine/m762,/obj/item/weapon/gun/projectile/automatic/m90,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot) +"mA" = (/obj/structure/closet/crate{name = "munitions crate"},/obj/item/weapon/storage/box/donkpockets,/obj/item/ammo_box/magazine/mm556x45,/obj/item/weapon/gun/projectile/automatic/m90,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot) "mB" = (/obj/machinery/door/window{base_state = "right"; dir = 8; icon_state = "right"; name = "Telepad"; req_access_txt = "0"},/turf/simulated/floor/engine,/area/syndicate_depot) "mC" = (/obj/machinery/telepad,/turf/simulated/floor/engine,/area/syndicate_depot) "mD" = (/obj/structure/closet/crate{name = "munitions crate"},/obj/item/ammo_box/magazine/m12g/dragon,/obj/item/ammo_box/magazine/m12g/dragon,/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate,/obj/item/weapon/storage/firstaid/tactical,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index bf620aad6e3..ca293307099 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -53,3 +53,11 @@ #define AI_ON 1 #define AI_IDLE 2 #define AI_OFF 3 + +//Gun Stuff + #define SAWN_INTACT 0 + #define SAWN_OFF 1 + + #define WEAPON_LIGHT 0 + #define WEAPON_MEDIUM 1 + #define WEAPON_HEAVY 2 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/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index d375f63dd39..d36405db5d1 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -251,3 +251,7 @@ 0.3, 0.3, 0.3, 0,\ 0.3, 0.3, 0.3, 0,\ 0, 0, 0, 1) +//Gun trigger guards +#define TRIGGER_GUARD_ALLOW_ALL -1 +#define TRIGGER_GUARD_NONE 0 +#define TRIGGER_GUARD_NORMAL 1 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 96ae9ea6281..12722c0a2bb 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -27,6 +27,7 @@ #define ROLE_HOG_GOD "hand of god: god" // We're prolly gonna port this one day or another #define ROLE_HOG_CULTIST "hand of god: cultist" #define ROLE_RAIDER "vox raider" +#define ROLE_TRADER "trader" #define ROLE_VAMPIRE "vampire" #define ROLE_MUTINEER "mutineer" // Role tags for EVERYONE! @@ -71,4 +72,5 @@ var/global/list/special_roles = list( ROLE_REVENANT, ROLE_GUARDIAN, ROLE_MORPH, + ROLE_TRADER, ) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index aeabb8c5f6a..8b0c544c8cc 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) all_cults = typesof(/datum/cult_info) 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/ai.dm b/code/_onclick/ai.dm index b44ba964628..db5a0bbcd0f 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -45,7 +45,7 @@ if(modifiers["middle"]) MiddleClickOn(A) if(controlled_mech) //Are we piloting a mech? Placed here so the modifiers are not overridden. - controlled_mech.click_action(A, src) //Override AI normal click behavior. + controlled_mech.click_action(A, src, params) //Override AI normal click behavior. return if(modifiers["shift"]) ShiftClickOn(A) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index d135e62ae69..fa1d696a067 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -74,7 +74,7 @@ if(!locate(/turf) in list(A,A.loc)) // Prevents inventory from being drilled return var/obj/mecha/M = loc - return M.click_action(A,src) + return M.click_action(A, src, params) if(restrained()) changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow @@ -167,9 +167,8 @@ animals lunging, etc. */ /mob/proc/RangedAttack(var/atom/A, var/params) - if(ishuman(src) && (istype(src:gloves, /obj/item/clothing/gloves/color/yellow/power)) && a_intent == I_HARM) - PowerGlove(A) - if(!mutations.len) return + if(!mutations.len) + return if((LASER in mutations) && a_intent == I_HARM) LaserEyes(A) // moved into a proc below return @@ -319,61 +318,8 @@ LE.current = T LE.yo = U.y - T.y LE.xo = U.x - T.x - spawn(1) - LE.process() + LE.fire() -/mob/proc/PowerGlove(atom/A) - return - -/mob/living/carbon/human/PowerGlove(atom/A) - var/obj/item/clothing/gloves/color/yellow/power/G = src:gloves - var/time = 100 - var/turf/T = get_turf(src) - var/turf/U = get_turf(A) - var/obj/structure/cable/cable = locate() in T - if(!cable || !istype(cable)) - to_chat(src, "There is no cable here to power the gloves.") - return - if(world.time < G.next_shock) - to_chat(src, "[G] aren't ready to shock again!") - return - src.visible_message("[name] fires an arc of electricity!", \ - "You fire an arc of electricity!", \ - "You hear the loud crackle of electricity!") - var/datum/powernet/PN = cable.get_powernet() - var/available = 0 - var/obj/item/projectile/beam/lightning/L = new /obj/item/projectile/beam/lightning/(get_turf(src)) - if(PN) - available = PN.avail - L.damage = PN.get_electrocute_damage() - if(available >= 5000000) - L.damage = 205 - if(L.damage >= 200) - time = 200 - else if(L.damage >= 100) - time = 150 - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - if(L.damage <= 0) - qdel(L) - if(L) - playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1) - L.tang = L.adjustAngle(get_angle(U,T)) - L.icon = midicon - L.icon_state = "[L.tang]" - L.firer = usr - L.def_zone = get_organ_target() - L.original = src - L.current = U - L.starting = U - L.yo = U.y - T.y - L.xo = U.x - T.x - spawn( 1 ) - L.process() - - next_move = world.time + 12 - G.next_shock = world.time + time // Simple helper to face what you clicked on, in case it should be needed in more than one place /mob/proc/face_atom(var/atom/A) @@ -419,4 +365,4 @@ else var/turf/T = screen_loc2turf(modifiers["screen-loc"], get_turf(usr)) T.Click(location, control, params) - return 1 \ No newline at end of file + return 1 diff --git a/code/_onclick/click_override.dm b/code/_onclick/click_override.dm index 092398ee174..d37b7368b8f 100644 --- a/code/_onclick/click_override.dm +++ b/code/_onclick/click_override.dm @@ -40,4 +40,29 @@ newObject.loc = get_turf(A) to_chat(user, "You release the power you had stored up, summoning \a [newObject.name]! ") usr.loc.visible_message("[user] waves \his hand and summons \a [newObject.name]") - ..() \ No newline at end of file + ..() + +/datum/middleClickOverride/power_gloves + var/last_shocked = 0 + var/shock_delay = 120 + +/datum/middleClickOverride/power_gloves/onClick(var/atom/A, var/mob/living/user) + if(user.incapacitated()) + return + if(world.time < last_shocked + shock_delay) + to_chat(user, "The gloves are still recharging.") + return + if(!isliving(A)) + to_chat(user, "Shocking an inanimate object would be pointless.") + return + var/mob/living/L = A + var/turf/T = get_turf(user) + var/obj/structure/cable/C = locate() in T + if(!C || !istype(C)) + to_chat(user, "There is no cable here to power the gloves.") + return + user.visible_message("[user.name] fires an arc of electricity at [L]!", "You fire an arc of electricity at [L]!", "You hear the loud crackle of electricity!") + var/datum/powernet/PN = C.get_powernet() + user.Beam(L,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + electrocute_mob(L, PN, user) + last_shocked = world.time diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index 233add211f6..4744b789712 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -217,11 +217,25 @@ check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE|AB_CHECK_INSIDE /datum/action/item_action/CheckRemoval(mob/living/user) - return !(target in user) + return get(target, /mob/living) != user /datum/action/item_action/hands_free check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE +// for clothing accessories like holsters +/datum/action/item_action/accessory + check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE + +/datum/action/item_action/accessory/Checks() + . = ..() + if(!.) + return 0 + if(target.loc == owner) + return 1 + if(istype(target.loc, /obj/item/clothing/under) && target.loc.loc == owner) + return 1 + return 0 + ///prset for organ actions /datum/action/item_action/organ_action check_flags = AB_CHECK_ALIVE 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/oldcode.dm b/code/_onclick/oldcode.dm index b3f2c1dde05..89b1131a6f0 100644 --- a/code/_onclick/oldcode.dm +++ b/code/_onclick/oldcode.dm @@ -369,8 +369,7 @@ A.current = T A.yo = U.y - T.y A.xo = U.x - T.x - spawn( 1 ) - A.process() + A.fire() usr.next_move = world.time + 6 return 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/spells/dumbfire.dm b/code/datums/spells/dumbfire.dm index c1eb4889a93..7b5c77b7d21 100644 --- a/code/datums/spells/dumbfire.dm +++ b/code/datums/spells/dumbfire.dm @@ -79,8 +79,11 @@ qdel(trail) current_loc = projectile.loc + var/matrix/M = new + M.Turn(dir2angle(projectile.dir)) + projectile.transform = M sleep(proj_step_delay) if(projectile) - qdel(projectile) \ No newline at end of file + qdel(projectile) diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 247d481f1be..be25ea14f1f 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -234,9 +234,9 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /datum/supply_packs/security/taser name = "Stun Guns Crate" - contains = list(/obj/item/weapon/gun/energy/advtaser, - /obj/item/weapon/gun/energy/advtaser, - /obj/item/weapon/gun/energy/advtaser) + contains = list(/obj/item/weapon/gun/energy/gun/advtaser, + /obj/item/weapon/gun/energy/gun/advtaser, + /obj/item/weapon/gun/energy/gun/advtaser) cost = 15 containername = "stun gun crate" diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 08c418778a3..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" @@ -410,6 +410,13 @@ var/list/uplink_items = list() item = /obj/item/weapon/twohanded/chainsaw cost = 13 +/datum/uplink_item/dangerous/batterer + name = "Mind Batterer" + desc = "A device that has a chance of knocking down people around you for a long amount of time. 50% chance per person. The user is unaffected. Has 5 charges." + reference = "BTR" + item = /obj/item/device/batterer + cost = 5 + /datum/uplink_item/dangerous/manhacks name = "Viscerator Delivery Grenade" desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred any non-operatives in the area." @@ -605,10 +612,10 @@ var/list/uplink_items = list() gamemodes = list(/datum/game_mode/nuclear) /datum/uplink_item/ammo/machinegun - name = "Box Magazine - 7.62x51mm" - desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machine gun. By the time you need to use this, you'll already be on a pile of corpses." + name = "Box Magazine - 5.56x45mm" + desc = "A 50-round magazine of 5.56x45mm ammunition for use in the L6 SAW machine gun. By the time you need to use this, you'll already be on a pile of corpses." reference = "762" - item = /obj/item/ammo_box/magazine/m762 + item = /obj/item/ammo_box/magazine/mm556x45 cost = 12 gamemodes = list(/datum/game_mode/nuclear) surplus = 0 @@ -686,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 @@ -1016,7 +1023,7 @@ var/list/uplink_items = list() /datum/uplink_item/implants/uplink name = "Uplink Implant" - desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement." + desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 10 telecrystals. The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement." reference = "UI" item = /obj/item/weapon/implanter/uplink cost = 14 diff --git a/code/defines/vox_sounds.dm b/code/defines/vox_sounds.dm index 6f9bcf122fd..98442569e5b 100644 --- a/code/defines/vox_sounds.dm +++ b/code/defines/vox_sounds.dm @@ -16,6 +16,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "across" = 'sound/vox_fem/across.ogg', "activate" = 'sound/vox_fem/activate.ogg', "activated" = 'sound/vox_fem/activated.ogg', +"active" = 'sound/vox_fem/active.ogg', "activity" = 'sound/vox_fem/activity.ogg', "adios" = 'sound/vox_fem/adios.ogg', "administration" = 'sound/vox_fem/administration.ogg', @@ -24,7 +25,9 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "after" = 'sound/vox_fem/after.ogg', "agent" = 'sound/vox_fem/agent.ogg', "ai" = 'sound/vox_fem/ai.ogg', +"airlock" = 'sound/vox_fem/airlock.ogg', "alarm" = 'sound/vox_fem/alarm.ogg', +"alcohol" = 'sound/vox_fem/alcohol.ogg', "alert" = 'sound/vox_fem/alert.ogg', "alien" = 'sound/vox_fem/alien.ogg', "aligned" = 'sound/vox_fem/aligned.ogg', @@ -51,6 +54,8 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "armory" = 'sound/vox_fem/armory.ogg', "array" = 'sound/vox_fem/array.ogg', "arrest" = 'sound/vox_fem/arrest.ogg', +"arrival" = 'sound/vox_fem/arrival.ogg', +"arrivals" = 'sound/vox_fem/arrivals.ogg', "asimov" = 'sound/vox_fem/asimov.ogg', "ass" = 'sound/vox_fem/ass.ogg', "asshole" = 'sound/vox_fem/asshole.ogg', @@ -74,8 +79,10 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "base" = 'sound/vox_fem/base.ogg', "bay" = 'sound/vox_fem/bay.ogg', "be" = 'sound/vox_fem/be.ogg', +"becoming" = 'sound/vox_fem/becoming.ogg', "been" = 'sound/vox_fem/been.ogg', "before" = 'sound/vox_fem/before.ogg', +"between" = 'sound/vox_fem/between.ogg', "beyond" = 'sound/vox_fem/beyond.ogg', "biohazard" = 'sound/vox_fem/biohazard.ogg', "biological" = 'sound/vox_fem/biological.ogg', @@ -86,6 +93,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "bizwarn" = 'sound/vox_fem/bizwarn.ogg', "black" = 'sound/vox_fem/black.ogg', "blast" = 'sound/vox_fem/blast.ogg', +"blob" = 'sound/vox_fem/blob.ogg', "blocked" = 'sound/vox_fem/blocked.ogg', "bloop" = 'sound/vox_fem/bloop.ogg', "blue" = 'sound/vox_fem/blue.ogg', @@ -104,6 +112,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "breached" = 'sound/vox_fem/breached.ogg', "break" = 'sound/vox_fem/break.ogg', "bridge" = 'sound/vox_fem/bridge.ogg', +"briefing" = 'sound/vox_fem/briefing.ogg', "brig" = 'sound/vox_fem/brig.ogg', "bust" = 'sound/vox_fem/bust.ogg', "but" = 'sound/vox_fem/but.ogg', @@ -115,6 +124,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "cage" = 'sound/vox_fem/cage.ogg', "call" = 'sound/vox_fem/call.ogg', "called" = 'sound/vox_fem/called.ogg', +"camp" = 'sound/vox_fem/camp.ogg', "can" = 'sound/vox_fem/can.ogg', "canal" = 'sound/vox_fem/canal.ogg', "cancer" = 'sound/vox_fem/cancer.ogg', @@ -130,11 +140,13 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "center" = 'sound/vox_fem/center.ogg', "centi" = 'sound/vox_fem/centi.ogg', "central" = 'sound/vox_fem/central.ogg', +"chair" = 'sound/vox_fem/chair.ogg', "chamber" = 'sound/vox_fem/chamber.ogg', "changed" = 'sound/vox_fem/changed.ogg', "changeling" = 'sound/vox_fem/changeling.ogg', "changelings" = 'sound/vox_fem/changelings.ogg', "changer" = 'sound/vox_fem/changer.ogg', +"chapel" = 'sound/vox_fem/chapel.ogg', "charlie" = 'sound/vox_fem/charlie.ogg', "check" = 'sound/vox_fem/check.ogg', "checkpoint" = 'sound/vox_fem/checkpoint.ogg', @@ -147,6 +159,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "clear" = 'sound/vox_fem/clear.ogg', "clearance" = 'sound/vox_fem/clearance.ogg', "close" = 'sound/vox_fem/close.ogg', +"closet" = 'sound/vox_fem/closet.ogg', "clown" = 'sound/vox_fem/clown.ogg', "clowns" = 'sound/vox_fem/clowns.ogg', "cmo" = 'sound/vox_fem/cmo.ogg', @@ -179,6 +192,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "cryogenic" = 'sound/vox_fem/cryogenic.ogg', "cunt" = 'sound/vox_fem/cunt.ogg', "cunts" = 'sound/vox_fem/cunts.ogg', +"cyberiad" = 'sound/vox_fem/cyberiad.ogg', "cyborg" = 'sound/vox_fem/cyborg.ogg', "cyborgs" = 'sound/vox_fem/cyborgs.ogg', "d" = 'sound/vox_fem/d.ogg', @@ -190,6 +204,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "deactivated" = 'sound/vox_fem/deactivated.ogg', "dead" = 'sound/vox_fem/dead.ogg', "death" = 'sound/vox_fem/death.ogg', +"declared" = 'sound/vox_fem/declared.ogg', "decompression" = 'sound/vox_fem/decompression.ogg', "decontamination" = 'sound/vox_fem/decontamination.ogg', "deeoo" = 'sound/vox_fem/deeoo.ogg', @@ -206,11 +221,13 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "destroyed" = 'sound/vox_fem/destroyed.ogg', "detain" = 'sound/vox_fem/detain.ogg', "detected" = 'sound/vox_fem/detected.ogg', +"detective" = 'sound/vox_fem/detective.ogg', "detonation" = 'sound/vox_fem/detonation.ogg', "device" = 'sound/vox_fem/device.ogg', "did" = 'sound/vox_fem/did.ogg', "die" = 'sound/vox_fem/die.ogg', "dimensional" = 'sound/vox_fem/dimensional.ogg', +"diona" = 'sound/vox_fem/diona.ogg', "dirt" = 'sound/vox_fem/dirt.ogg', "disengaged" = 'sound/vox_fem/disengaged.ogg', "dish" = 'sound/vox_fem/dish.ogg', @@ -218,12 +235,18 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "distance" = 'sound/vox_fem/distance.ogg', "distortion" = 'sound/vox_fem/distortion.ogg', "do" = 'sound/vox_fem/do.ogg', +"dock" = 'sound/vox_fem/dock.ogg', +"docked" = 'sound/vox_fem/docked.ogg', +"docking" = 'sound/vox_fem/docking.ogg', +"docks" = 'sound/vox_fem/docks.ogg', "doctor" = 'sound/vox_fem/doctor.ogg', "doctors" = 'sound/vox_fem/doctors.ogg', "doop" = 'sound/vox_fem/doop.ogg', "door" = 'sound/vox_fem/door.ogg', "dorms" = 'sound/vox_fem/dorms.ogg', "down" = 'sound/vox_fem/down.ogg', +"drask" = 'sound/vox_fem/drask.ogg', +"drunk" = 'sound/vox_fem/drunk.ogg', "dual" = 'sound/vox_fem/dual.ogg', "duct" = 'sound/vox_fem/duct.ogg', "e" = 'sound/vox_fem/e.ogg', @@ -240,6 +263,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "elevator" = 'sound/vox_fem/elevator.ogg', "eleven" = 'sound/vox_fem/eleven.ogg', "eliminate" = 'sound/vox_fem/eliminate.ogg', +"emag" = 'sound/vox_fem/emag.ogg', "emergency" = 'sound/vox_fem/emergency.ogg', "energy" = 'sound/vox_fem/energy.ogg', "engage" = 'sound/vox_fem/engage.ogg', @@ -251,9 +275,11 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "enter" = 'sound/vox_fem/enter.ogg', "entry" = 'sound/vox_fem/entry.ogg', "environment" = 'sound/vox_fem/environment.ogg', +"equipment" = 'sound/vox_fem/equipment.ogg', "error" = 'sound/vox_fem/error.ogg', "escape" = 'sound/vox_fem/escape.ogg', "evacuate" = 'sound/vox_fem/evacuate.ogg', +"evacuation" = 'sound/vox_fem/evacuation.ogg', "every" = 'sound/vox_fem/every.ogg', "everywhere" = 'sound/vox_fem/everywhere.ogg', "exchange" = 'sound/vox_fem/exchange.ogg', @@ -262,6 +288,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "expect" = 'sound/vox_fem/expect.ogg', "experiment" = 'sound/vox_fem/experiment.ogg', "experimental" = 'sound/vox_fem/experimental.ogg', +"experimentor" = 'sound/vox_fem/experimentor.ogg', "explode" = 'sound/vox_fem/explode.ogg', "explosion" = 'sound/vox_fem/explosion.ogg', "exposure" = 'sound/vox_fem/exposure.ogg', @@ -310,6 +337,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "fuel" = 'sound/vox_fem/fuel.ogg', "g" = 'sound/vox_fem/g.ogg', "gas" = 'sound/vox_fem/gas.ogg', +"gateway" = 'sound/vox_fem/gateway.ogg', "get" = 'sound/vox_fem/get.ogg', "glory" = 'sound/vox_fem/glory.ogg', "go" = 'sound/vox_fem/go.ogg', @@ -332,6 +360,8 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "hacker" = 'sound/vox_fem/hacker.ogg', "hackers" = 'sound/vox_fem/hackers.ogg', "hacking" = 'sound/vox_fem/hacking.ogg', +"hail" = 'sound/vox_fem/hail.ogg', +"hallway" = 'sound/vox_fem/hallway.ogg', "handling" = 'sound/vox_fem/handling.ogg', "hangar" = 'sound/vox_fem/hangar.ogg', "happening" = 'sound/vox_fem/happening.ogg', @@ -352,6 +382,8 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "highest" = 'sound/vox_fem/highest.ogg', "hit" = 'sound/vox_fem/hit.ogg', "hole" = 'sound/vox_fem/hole.ogg', +"holoparasite" = 'sound/vox_fem/holoparasite.ogg', +"honk" = 'sound/vox_fem/honk.ogg', "hop" = 'sound/vox_fem/hop.ogg', "hos" = 'sound/vox_fem/hos.ogg', "hostile" = 'sound/vox_fem/hostile.ogg', @@ -359,6 +391,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "hotel" = 'sound/vox_fem/hotel.ogg', "hour" = 'sound/vox_fem/hour.ogg', "hours" = 'sound/vox_fem/hours.ogg', +"hull" = 'sound/vox_fem/hull.ogg', "human" = 'sound/vox_fem/human.ogg', "humans" = 'sound/vox_fem/humans.ogg', "hundred" = 'sound/vox_fem/hundred.ogg', @@ -367,10 +400,12 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "hydroponics" = 'sound/vox_fem/hydroponics.ogg', "i" = 'sound/vox_fem/i.ogg', "iaa" = 'sound/vox_fem/iaa.ogg', +"ian" = 'sound/vox_fem/ian.ogg', "idiot" = 'sound/vox_fem/idiot.ogg', "illegal" = 'sound/vox_fem/illegal.ogg', "immediate" = 'sound/vox_fem/immediate.ogg', "immediately" = 'sound/vox_fem/immediately.ogg', +"imminent" = 'sound/vox_fem/imminent.ogg', "in" = 'sound/vox_fem/in.ogg', "inches" = 'sound/vox_fem/inches.ogg', "india" = 'sound/vox_fem/india.ogg', @@ -380,7 +415,9 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "inspection" = 'sound/vox_fem/inspection.ogg', "inspector" = 'sound/vox_fem/inspector.ogg', "interchange" = 'sound/vox_fem/interchange.ogg', +"interested" = 'sound/vox_fem/interested.ogg', "intruder" = 'sound/vox_fem/intruder.ogg', +"intruders" = 'sound/vox_fem/intruders.ogg', "invalid" = 'sound/vox_fem/invalid.ogg', "invasion" = 'sound/vox_fem/invasion.ogg', "is" = 'sound/vox_fem/is.ogg', @@ -390,6 +427,8 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "juliet" = 'sound/vox_fem/juliet.ogg', "k" = 'sound/vox_fem/k.ogg', "key" = 'sound/vox_fem/key.ogg', +"kida" = 'sound/vox_fem/kida.ogg', +"kidan" = 'sound/vox_fem/kidan.ogg', "kill" = 'sound/vox_fem/kill.ogg', "killed" = 'sound/vox_fem/killed.ogg', "killing" = 'sound/vox_fem/killing.ogg', @@ -398,6 +437,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "kitchen" = 'sound/vox_fem/kitchen.ogg', "l" = 'sound/vox_fem/l.ogg', "lab" = 'sound/vox_fem/lab.ogg', +"labor" = 'sound/vox_fem/labor.ogg', "lambda" = 'sound/vox_fem/lambda.ogg', "laser" = 'sound/vox_fem/laser.ogg', "last" = 'sound/vox_fem/last.ogg', @@ -411,6 +451,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "legal" = 'sound/vox_fem/legal.ogg', "level" = 'sound/vox_fem/level.ogg', "lever" = 'sound/vox_fem/lever.ogg', +"library" = 'sound/vox_fem/library.ogg', "lie" = 'sound/vox_fem/lie.ogg', "lieutenant" = 'sound/vox_fem/lieutenant.ogg', "life" = 'sound/vox_fem/life.ogg', @@ -457,8 +498,13 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "military" = 'sound/vox_fem/military.ogg', "milli" = 'sound/vox_fem/milli.ogg', "million" = 'sound/vox_fem/million.ogg', +"mime" = 'sound/vox_fem/mime.ogg', +"mimes" = 'sound/vox_fem/mimes.ogg', "minefield" = 'sound/vox_fem/minefield.ogg', +"miner" = 'sound/vox_fem/miner.ogg', +"miners" = 'sound/vox_fem/miners.ogg', "minimum" = 'sound/vox_fem/minimum.ogg', +"mining" = 'sound/vox_fem/mining.ogg', "minus" = 'sound/vox_fem/minus.ogg', "minutes" = 'sound/vox_fem/minutes.ogg', "mister" = 'sound/vox_fem/mister.ogg', @@ -473,6 +519,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "must" = 'sound/vox_fem/must.ogg', "my" = 'sound/vox_fem/my.ogg', "n" = 'sound/vox_fem/n.ogg', +"n2o" = 'sound/vox_fem/n2o.ogg', "nanotrasen" = 'sound/vox_fem/nanotrasen.ogg', "nearest" = 'sound/vox_fem/nearest.ogg', "negative" = 'sound/vox_fem/negative.ogg', @@ -488,20 +535,25 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "not" = 'sound/vox_fem/not.ogg', "november" = 'sound/vox_fem/november.ogg', "now" = 'sound/vox_fem/now.ogg', +"nuke" = 'sound/vox_fem/nuke.ogg', "number" = 'sound/vox_fem/number.ogg', "o" = 'sound/vox_fem/o.ogg', "objective" = 'sound/vox_fem/objective.ogg', "observation" = 'sound/vox_fem/observation.ogg', "obtain" = 'sound/vox_fem/obtain.ogg', "of" = 'sound/vox_fem/of.ogg', +"office" = 'sound/vox_fem/office.ogg', "officer" = 'sound/vox_fem/officer.ogg', "ok" = 'sound/vox_fem/ok.ogg', "on" = 'sound/vox_fem/on.ogg', "one" = 'sound/vox_fem/one.ogg', +"op" = 'sound/vox_fem/op.ogg', "open" = 'sound/vox_fem/open.ogg', "operating" = 'sound/vox_fem/operating.ogg', +"operational" = 'sound/vox_fem/operational.ogg', "operations" = 'sound/vox_fem/operations.ogg', "operative" = 'sound/vox_fem/operative.ogg', +"ops" = 'sound/vox_fem/ops.ogg', "option" = 'sound/vox_fem/option.ogg', "or" = 'sound/vox_fem/or.ogg', "order" = 'sound/vox_fem/order.ogg', @@ -526,7 +578,10 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "plasma" = 'sound/vox_fem/plasma.ogg', "platform" = 'sound/vox_fem/platform.ogg', "please" = 'sound/vox_fem/please.ogg', +"pod" = 'sound/vox_fem/pod.ogg', +"pods" = 'sound/vox_fem/pods.ogg', "point" = 'sound/vox_fem/point.ogg', +"poly" = 'sound/vox_fem/poly.ogg', "port" = 'sound/vox_fem/port.ogg', "portal" = 'sound/vox_fem/portal.ogg', "power" = 'sound/vox_fem/power.ogg', @@ -540,6 +595,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "propulsion" = 'sound/vox_fem/propulsion.ogg', "prosecute" = 'sound/vox_fem/prosecute.ogg', "protective" = 'sound/vox_fem/protective.ogg', +"pun" = 'sound/vox_fem/pun.ogg', "push" = 'sound/vox_fem/push.ogg', "q" = 'sound/vox_fem/q.ogg', "qm" = 'sound/vox_fem/qm.ogg', @@ -569,10 +625,12 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "released" = 'sound/vox_fem/released.ogg', "remaining" = 'sound/vox_fem/remaining.ogg', "removal" = 'sound/vox_fem/removal.ogg', +"renault" = 'sound/vox_fem/renault.ogg', "renegade" = 'sound/vox_fem/renegade.ogg', "repair" = 'sound/vox_fem/repair.ogg', "report" = 'sound/vox_fem/report.ogg', "reports" = 'sound/vox_fem/reports.ogg', +"representative" = 'sound/vox_fem/representative.ogg', "request" = 'sound/vox_fem/request.ogg', "requested" = 'sound/vox_fem/requested.ogg', "required" = 'sound/vox_fem/required.ogg', @@ -591,6 +649,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "room" = 'sound/vox_fem/room.ogg', "round" = 'sound/vox_fem/round.ogg', "run" = 'sound/vox_fem/run.ogg', +"runtime" = 'sound/vox_fem/runtime.ogg', "s" = 'sound/vox_fem/s.ogg', "safe" = 'sound/vox_fem/safe.ogg', "safety" = 'sound/vox_fem/safety.ogg', @@ -601,6 +660,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "science" = 'sound/vox_fem/science.ogg', "scream" = 'sound/vox_fem/scream.ogg', "screen" = 'sound/vox_fem/screen.ogg', +"scrubbers" = 'sound/vox_fem/scrubbers.ogg', "search" = 'sound/vox_fem/search.ogg', "second" = 'sound/vox_fem/second.ogg', "secondary" = 'sound/vox_fem/secondary.ogg', @@ -612,6 +672,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "select" = 'sound/vox_fem/select.ogg', "selected" = 'sound/vox_fem/selected.ogg', "sensors" = 'sound/vox_fem/sensors.ogg', +"sequencer" = 'sound/vox_fem/sequencer.ogg', "service" = 'sound/vox_fem/service.ogg', "seven" = 'sound/vox_fem/seven.ogg', "seventeen" = 'sound/vox_fem/seventeen.ogg', @@ -642,6 +703,9 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "sixteen" = 'sound/vox_fem/sixteen.ogg', "sixty" = 'sound/vox_fem/sixty.ogg', "skipjack" = 'sound/vox_fem/skipjack.ogg', +"skree" = 'sound/vox_fem/skree.ogg', +"skrek" = 'sound/vox_fem/skrek.ogg', +"skrell" = 'sound/vox_fem/skrell.ogg', "slime" = 'sound/vox_fem/slime.ogg', "slow" = 'sound/vox_fem/slow.ogg', "smoke" = 'sound/vox_fem/smoke.ogg', @@ -654,6 +718,9 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "son" = 'sound/vox_fem/son.ogg', "sorry" = 'sound/vox_fem/sorry.ogg', "south" = 'sound/vox_fem/south.ogg', +"space" = 'sound/vox_fem/space.ogg', +"spider" = 'sound/vox_fem/spider.ogg', +"spiders" = 'sound/vox_fem/spiders.ogg', "squad" = 'sound/vox_fem/squad.ogg', "square" = 'sound/vox_fem/square.ogg', "ss13" = 'sound/vox_fem/ss13.ogg', @@ -664,8 +731,10 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "status" = 'sound/vox_fem/status.ogg', "sterile" = 'sound/vox_fem/sterile.ogg', "sterilization" = 'sound/vox_fem/sterilization.ogg', +"still" = 'sound/vox_fem/still.ogg', "storage" = 'sound/vox_fem/storage.ogg', "stuck" = 'sound/vox_fem/stuck.ogg', +"stupid" = 'sound/vox_fem/stupid.ogg', "sub" = 'sound/vox_fem/sub.ogg', "subsurface" = 'sound/vox_fem/subsurface.ogg', "sudden" = 'sound/vox_fem/sudden.ogg', @@ -679,7 +748,10 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "surrender" = 'sound/vox_fem/surrender.ogg', "surround" = 'sound/vox_fem/surround.ogg', "surrounded" = 'sound/vox_fem/surrounded.ogg', +"swarmer" = 'sound/vox_fem/swarmer.ogg', +"swarmers" = 'sound/vox_fem/swarmers.ogg', "switch" = 'sound/vox_fem/switch.ogg', +"sword" = 'sound/vox_fem/sword.ogg', "syndicate" = 'sound/vox_fem/syndicate.ogg', "system" = 'sound/vox_fem/system.ogg', "systems" = 'sound/vox_fem/systems.ogg', @@ -692,13 +764,19 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "tank" = 'sound/vox_fem/tank.ogg', "target" = 'sound/vox_fem/target.ogg', "team" = 'sound/vox_fem/team.ogg', +"technology" = 'sound/vox_fem/technology.ogg', "telecomms" = 'sound/vox_fem/telecomms.ogg', +"teleport" = 'sound/vox_fem/teleport.ogg', +"teleported" = 'sound/vox_fem/teleported.ogg', +"teleporter" = 'sound/vox_fem/teleporter.ogg', +"teleporting" = 'sound/vox_fem/teleporting.ogg', "temperature" = 'sound/vox_fem/temperature.ogg', "temporal" = 'sound/vox_fem/temporal.ogg', "ten" = 'sound/vox_fem/ten.ogg', "terminal" = 'sound/vox_fem/terminal.ogg', "terminated" = 'sound/vox_fem/terminated.ogg', "termination" = 'sound/vox_fem/termination.ogg', +"tesla" = 'sound/vox_fem/tesla.ogg', "test" = 'sound/vox_fem/test.ogg', "that" = 'sound/vox_fem/that.ogg', "the" = 'sound/vox_fem/the.ogg', @@ -716,6 +794,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "tide" = 'sound/vox_fem/tide.ogg', "time" = 'sound/vox_fem/time.ogg', "to" = 'sound/vox_fem/to.ogg', +"tool" = 'sound/vox_fem/tool.ogg', "top" = 'sound/vox_fem/top.ogg', "topside" = 'sound/vox_fem/topside.ogg', "touch" = 'sound/vox_fem/touch.ogg', @@ -735,6 +814,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "twenty" = 'sound/vox_fem/twenty.ogg', "two" = 'sound/vox_fem/two.ogg', "u" = 'sound/vox_fem/u.ogg', +"unathi" = 'sound/vox_fem/unathi.ogg', "unauthorized" = 'sound/vox_fem/unauthorized.ogg', "under" = 'sound/vox_fem/under.ogg', "uniform" = 'sound/vox_fem/uniform.ogg', @@ -753,13 +833,16 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "used" = 'sound/vox_fem/used.ogg', "user" = 'sound/vox_fem/user.ogg', "v" = 'sound/vox_fem/v.ogg', +"vacant" = 'sound/vox_fem/vacant.ogg', "vacate" = 'sound/vox_fem/vacate.ogg', "valid" = 'sound/vox_fem/valid.ogg', "vampire" = 'sound/vox_fem/vampire.ogg', "vampires" = 'sound/vox_fem/vampires.ogg', "vapor" = 'sound/vox_fem/vapor.ogg', +"vault" = 'sound/vox_fem/vault.ogg', "vent" = 'sound/vox_fem/vent.ogg', "ventilation" = 'sound/vox_fem/ventilation.ogg', +"vents" = 'sound/vox_fem/vents.ogg', "victor" = 'sound/vox_fem/victor.ogg', "violated" = 'sound/vox_fem/violated.ogg', "violation" = 'sound/vox_fem/violation.ogg', @@ -767,6 +850,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "voltage" = 'sound/vox_fem/voltage.ogg', "vox" = 'sound/vox_fem/vox.ogg', "vox_login" = 'sound/vox_fem/vox_login.ogg', +"vulpkanin" = 'sound/vox_fem/vulpkanin.ogg', "w" = 'sound/vox_fem/w.ogg', "walk" = 'sound/vox_fem/walk.ogg', "wall" = 'sound/vox_fem/wall.ogg', @@ -783,12 +867,15 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "weapon" = 'sound/vox_fem/weapon.ogg', "weed" = 'sound/vox_fem/weed.ogg', "welcome" = 'sound/vox_fem/welcome.ogg', +"weld" = 'sound/vox_fem/weld.ogg', "west" = 'sound/vox_fem/west.ogg', "whiskey" = 'sound/vox_fem/whiskey.ogg', "white" = 'sound/vox_fem/white.ogg', "wiggle" = 'sound/vox_fem/wiggle.ogg', "wilco" = 'sound/vox_fem/wilco.ogg', "will" = 'sound/vox_fem/will.ogg', +"window" = 'sound/vox_fem/window.ogg', +"windows" = 'sound/vox_fem/windows.ogg', "with" = 'sound/vox_fem/with.ogg', "without" = 'sound/vox_fem/without.ogg', "wizard" = 'sound/vox_fem/wizard.ogg', @@ -807,6 +894,7 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "year" = 'sound/vox_fem/year.ogg', "yellow" = 'sound/vox_fem/yellow.ogg', "yes" = 'sound/vox_fem/yes.ogg', +"yet" = 'sound/vox_fem/yet.ogg', "you" = 'sound/vox_fem/you.ogg', "your" = 'sound/vox_fem/your.ogg', "yourself" = 'sound/vox_fem/yourself.ogg', diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 1706763b824..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" @@ -438,6 +442,14 @@ var/list/ghostteleportlocs = list() name = "Syndicate Infiltrator" icon_state = "shuttle" +/area/shuttle/trade + name = "Trade Shuttle" + icon_state = "shuttle" + requires_power = 0 + +/area/shuttle/trade/sol + name = "Sol Freighter" + /area/airtunnel1/ // referenced in airtunnel.dm:759 /area/dummy/ // Referenced in engine.dm:261 @@ -675,6 +687,14 @@ var/list/ghostteleportlocs = list() icon_state = "southeast" requires_power = 0 +/area/trader_station + name = "Trade Base" + icon_state = "yellow" + requires_power = 0 + +/area/trader_station/sol + name = "Jupiter Station 6" + /area/vox_station/mining name = "\improper Nearby Mining Asteroid" icon_state = "north" diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 92c894cba10..b169deeee10 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -331,4 +331,4 @@ /atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5) if(buckled_mob == mover) return 1 - return ..() \ No newline at end of file + return ..() 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/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index 229b35660a3..d60748f8dae 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -91,6 +91,8 @@ loc.visible_message("The corpse of [H.name] suddenly rises!") /mob/living/simple_animal/hostile/blob/blobspore/death() + ..() + // On death, create a small smoke of harmful gas (s-Acid) var/datum/effect/system/chem_smoke_spread/S = new var/turf/location = get_turf(src) @@ -108,7 +110,6 @@ S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud S.start() - ghostize() qdel(src) /mob/living/simple_animal/hostile/blob/blobspore/Destroy() 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/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 803a7ba0d80..3c8b96935ec 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -72,7 +72,7 @@ rcd light flash thingy on matter drain if(T.z in config.station_levels) // Increase health by 37.5% of original max, decrease delays between shots to 66% turret.health += initial(turret.health) * 3 / 8 - turret.eprojectile = /obj/item/projectile/beam/heavylaser //Once you see it, you will know what it means to FEAR. + turret.eprojectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR. turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' to_chat(src, "Turrets upgraded.") /datum/AI_Module/large/destroy_rcd diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 5107ff7cab4..930ec3df35d 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -14,7 +14,7 @@ origin_tech = "materials=5;biotech=4;powerstorage=5;abductor=3" armor = list(melee = 15, bullet = 15, laser = 15, energy = 15, bomb = 15, bio = 15, rad = 15) action_button_name = "Activate" - action_button_is_hands_free = 1 + action_button_custom_type = /datum/action/item_action/hands_free var/mode = VEST_STEALTH var/stealth_active = 0 var/combat_cooldown = 10 @@ -308,14 +308,7 @@ icon_state = "alienpistol" item_state = "alienpistol" origin_tech = "combat=5;materials=4;powerstorage=3;abductor=3" - -/obj/item/weapon/gun/energy/decloner/alien/special_check(user) - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(H.get_species() != "Abductor") - to_chat(user, "UNAUTHORIZED -- UNAUTHORIZED") - return 0 - return 1 + restricted_species = list("Abductor") /obj/item/weapon/paper/abductor name = "Dissection Guide" @@ -631,4 +624,4 @@ Congratulations! You are now trained for xenobiology research!"} icon_state = "abductor" icon_closed = "abductor" icon_opened = "abductoropen" - material_drop = /obj/item/stack/sheet/mineral/abductor \ No newline at end of file + material_drop = /obj/item/stack/sheet/mineral/abductor diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 1a0d7770a1a..91c2bddb74c 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -33,10 +33,7 @@ return 0 return B.host.say_understands(other, speaking) -/mob/living/captive_brain/emote(var/message) - return - -/mob/living/captive_brain/resist_borer() +/mob/living/captive_brain/resist() var/mob/living/simple_animal/borer/B = loc to_chat(src, "You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).") 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 25b3727ec3a..19d725f8677 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -247,10 +247,11 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ return 1 return 0 +/datum/objective/protect/mindslave //subytpe for mindslave implants /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) @@ -310,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() @@ -667,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 @@ -796,12 +797,52 @@ 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 \ No newline at end of file + completed = 1 + +// Traders + +/datum/objective/trade // Yes, I know there's no check_completion. The objectives exist only to tell the traders what to get. +/datum/objective/trade/proc/choose_target(var/station) + return + +/datum/objective/trade/stock // Stock or spare parts. + var/target_rating = 1 +/datum/objective/trade/stock/choose_target(var/station) + var/itemname + switch(rand(1,8)) + if(1) + target = /obj/item/weapon/stock_parts/cell + target_amount = 10 + target_rating = 3 + itemname = "ten high-capacity power cells" + if(2) + target = /obj/item/weapon/stock_parts/manipulator + target_amount = 20 + itemname = "twenty micro manipulators" + if(3) + target = /obj/item/weapon/stock_parts/matter_bin + target_amount = 20 + itemname = "twenty matter bins" + if(4) + target = /obj/item/weapon/stock_parts/micro_laser + target_amount = 15 + itemname = "fifteen micro-lasers" + if(5) + target = /obj/item/weapon/stock_parts/capacitor + target_amount = 15 + itemname = "fifteen capacitors" + if(6) + target = /obj/item/weapon/stock_parts/subspace/filter + target_amount = 4 + itemname = "four hyperwave filters" + if(7) + target = /obj/item/solar_assembly + target_amount = 10 + itemname = "ten solar panel assemblies" + if(8) + target = /obj/item/device/flash + target_amount = 6 + itemname = "six flashes" + explanation_text = "We are running low on spare parts. Trade for [itemname]." \ No newline at end of file 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 fd648b05c7d..d81b50c1922 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -35,7 +35,7 @@ /datum/theft_objective/hoslaser name = "the head of security's recreated antique laser gun" - typepath = /obj/item/weapon/gun/energy/hos + typepath = /obj/item/weapon/gun/energy/gun/hos protected_jobs = list("Head Of Security") /datum/theft_objective/hand_tele @@ -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 @@ -244,4 +244,4 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/device/aicard/C) typepath = /obj/item/stack/sheet/mineral/uranium min=10 max=30 - step=5 \ No newline at end of file + step=5 diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 97f2d301472..76a47e82749 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -366,10 +366,11 @@ traitor_mind.special_role = null traitor_mind.som = null slaved.leave_serv_hud(traitor_mind) + for(var/datum/objective/protect/mindslave/MS in traitor_mind.objectives) + traitor_mind.objectives -= MS update_traitor_icons_removed(traitor_mind) -// to_chat(world, "Removed [traitor_mind.current.name] from traitor shit") - to_chat(traitor_mind.current, "\red The fog clouding your mind clears. You remember nothing from the moment you were implanted until now.(You don't remember who implanted you)") + to_chat(traitor_mind.current, "You are no longer a mindslave; you have complete and free control of your own faculties, once more!") /datum/game_mode/proc/assign_exchange_role(var/datum/mind/owner) //set faction 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/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 79d644b2132..0d5ec7afcc4 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -351,8 +351,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha vampire_mind.som = null slaved.leave_serv_hud(vampire_mind) update_vampire_icons_removed(vampire_mind) -// to_chat(world, "Removed [vampire_mind.current.name] from vampire shit") - to_chat(vampire_mind.current, "\red The fog clouding your mind clears. You remember nothing from the moment you were enthralled until now.") + vampire_mind.current.visible_message("[vampire_mind.current] looks as though a burden has been lifted!", "The dark fog in your mind clears as you regain control of your own faculties, you are no longer a vampire thrall!") if(vampire_mind.current.hud_used) vampire_mind.current.hud_used.remove_vampire_hud() diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index bc7ba9276f5..8e04d98504b 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -267,6 +267,10 @@ W.destroy() playsound(usr.loc, 'sound/effects/creepyshriek.ogg', 100, 1) + +/proc/isvampirethrall(mob/living/M as mob) + return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.vampire_enthralled) + /obj/effect/proc_holder/spell/vampire/targetted/enthrall name = "Enthrall (300)" desc = "You use a large portion of your power to sway those loyal to none to be loyal to you only." diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm index eb1e8bce930..f2c10d7fc10 100644 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ b/code/game/gamemodes/wizard/rightandwrong.dm @@ -20,7 +20,7 @@ if(!summon_type) switch (randomizeguns) if("taser") - new /obj/item/weapon/gun/energy/advtaser(get_turf(H)) + new /obj/item/weapon/gun/energy/gun/advtaser(get_turf(H)) if("egun") new /obj/item/weapon/gun/energy/gun(get_turf(H)) if("laser") @@ -34,7 +34,7 @@ if("gyrojet") new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H)) if("pulse") - new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H)) + new /obj/item/weapon/gun/energy/pulse(get_turf(H)) if("suppressed") new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H)) new /obj/item/weapon/suppressor(get_turf(H)) @@ -71,7 +71,7 @@ if("turret") new /obj/item/weapon/gun/energy/gun/turret(get_turf(H)) if("pulsecarbine") - new /obj/item/weapon/gun/energy/pulse_rifle/carbine(get_turf(H)) + new /obj/item/weapon/gun/energy/pulse/carbine(get_turf(H)) if("decloner") new /obj/item/weapon/gun/energy/decloner(get_turf(H)) if("mindflayer") diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index c7435a29df9..c1ab67a3f03 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -98,6 +98,10 @@ /var/const/access_syndicate_leader = 151//Nuke Op Leader Access /var/const/access_vox = 152//Vox Access +//Trade Stations + +var/const/access_trade_sol = 160 + //MONEY /var/const/access_crate_cash = 200 diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 3b13ceb6b64..31c82b2a203 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -77,7 +77,7 @@ H.equip_or_collect(new /obj/item/clothing/glasses/hud/security/sunglasses(H), slot_glasses) // H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) - H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_s_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) H.equip_or_collect(new /obj/item/weapon/restraints/handcuffs(H), slot_l_hand) @@ -175,7 +175,7 @@ H.equip_to_slot_or_del(new /obj/item/clothing/head/helmet(H), slot_head) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/gloves/color/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_s_store) H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) @@ -249,7 +249,7 @@ H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/gloves/color/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_s_store) H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 2475df770b3..d0281c4b7c1 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -174,10 +174,10 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/deathimp(H), slot_r_hand) - H.equip_or_collect(new /obj/item/weapon/gun/energy/blueshield(H), slot_l_hand) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/blueshield(H), slot_l_hand) else H.equip_or_collect(new /obj/item/weapon/storage/box/deathimp(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/gun/energy/blueshield(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/blueshield(H.back), slot_in_backpack) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 @@ -263,4 +263,4 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) L.imp_in = H L.implanted = 1 H.sec_hud_set_implants() - return 1 \ No newline at end of file + return 1 diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 210edd98c98..12f01822cde 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -244,6 +244,10 @@ H.equip_or_collect(new /obj/item/toy/crayon/rainbow(H), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/reagent_containers/spray/waterflower(H), slot_in_backpack) + if(H.get_species() == "Machine") + var/obj/item/organ/internal/cyberimp/brain/clown_voice/implant + implant = new + implant.insert(H) H.mutations.Add(CLUMSY) H.dna.SetSEState(COMICBLOCK,1,1) genemutcheck(H,COMICBLOCK,null,MUTCHK_FORCED) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 873e08030a7..9aa7cfe2c7b 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -151,6 +151,9 @@ qdel(src) return else if(istype(W, /obj/item/device/analyzer) && panel_open) //XRay + if(!user.unEquip(W)) + to_chat(user, "[W] is stuck!") + return if(!isXRay()) upgradeXRay() qdel(W) @@ -158,14 +161,19 @@ else to_chat(user, "[msg2]") - else if(istype(W, /obj/item/stack/sheet/mineral/plasma) && panel_open) + else if(istype(W, /obj/item/stack/sheet/mineral/plasma) && panel_open) + if(!user.unEquip(W)) + to_chat(user, "[W] is stuck!") + return if(!isEmpProof()) upgradeEmpProof() to_chat(user, "[msg]") qdel(W) else to_chat(user, "[msg2]") - else if(istype(W, /obj/item/device/assembly/prox_sensor) && panel_open) + else if(istype(W, /obj/item/device/assembly/prox_sensor) && panel_open) + if(!user.unEquip(W)) + return if(!isMotion()) upgradeMotion() to_chat(user, "[msg]") diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 5b77c8f00fc..5b7d035d461 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -20,10 +20,9 @@ 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades) */ -/obj/item/weapon/camera_assembly/attackby(obj/item/W as obj, mob/living/user as mob, params) +/obj/item/weapon/camera_assembly/attackby(obj/item/W, mob/living/user, params) switch(state) - if(0) // State 0 if(iswrench(W) && isturf(src.loc)) @@ -116,7 +115,6 @@ return else if(iswirecutter(W)) - new/obj/item/stack/cable_coil(get_turf(src), 2) playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You cut the wires from the circuits.") @@ -125,9 +123,12 @@ // Upgrades! if(is_type_in_list(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. + if(!user.unEquip(W)) + to_chat(user, "[W] is stuck!") + return to_chat(user, "You attach \the [W] into the assembly inner circuits.") upgrades += W - user.drop_item(W) + user.drop_item() W.loc = src return diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index a4577a355cc..7fc6f4cc372 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 @@ -291,6 +292,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) @@ -372,7 +380,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/computer/communications.dm b/code/game/machinery/computer/communications.dm index 90b415c99bf..73779c170e0 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -273,6 +273,17 @@ src.emagged = 0 setMenuState(usr,COMM_SCREEN_MAIN) + if("AcceptDocking") + to_chat(usr, "Docking request accepted!") + trade_dock_timelimit = world.time + 1200 + trade_dockrequest_timelimit = 0 + command_announcement.Announce("Docking request for trading ship approved, please dock at port bay 4.", "Docking Request") + if("DenyDocking") + to_chat(usr, "Docking requeset denied!") + trade_dock_timelimit = 0 + trade_dockrequest_timelimit = 0 + command_announcement.Announce("Docking request for trading ship denied.", "Docking request") + nanomanager.update_uis(src) return 1 @@ -358,6 +369,11 @@ data["shuttle"] = shuttle + if(trade_dockrequest_timelimit > world.time) + data["dock_request"] = 1 + else + data["dock_request"] = 0 + // update the ui if it exists, returns null if no ui is passed/found ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) if (!ui) 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/gameboard.dm b/code/game/machinery/gameboard.dm index 5657d62f65f..a19f34af99b 100644 --- a/code/game/machinery/gameboard.dm +++ b/code/game/machinery/gameboard.dm @@ -2,11 +2,12 @@ name = "Virtual Gameboard" icon = 'icons/obj/stationobjs.dmi' icon_state = "gboard_on" - desc = "A holographic table allowing the crew to have funâ„¢ on boring shifts! One player per board." + desc = "A holographic table allowing the crew to have fun(TM) on boring shifts! One player per board." density = 1 anchored = 1 use_power = 1 var/cooling_down = 0 + light_color = LIGHT_COLOR_LIGHTBLUE /obj/machinery/gameboard/New() ..() @@ -20,6 +21,10 @@ /obj/machinery/gameboard/power_change() . = ..() update_icon() + if(stat & NOPOWER) + set_light(0) + else + set_light(3, 3) /obj/machinery/gameboard/update_icon() if(stat & NOPOWER) @@ -34,6 +39,9 @@ if(src.in_use) to_chat(user, "This gameboard is already in use!") return + if(!anchored) + to_chat(user, "The gameboard is not secured!") + return interact(user) /obj/machinery/gameboard/interact(mob/user) @@ -68,10 +76,10 @@ /obj/machinery/gameboard/Topic(var/href, var/list/href_list) . = ..() var/prize = /obj/item/stack/tickets - if (.) + if(.) return - if (href_list["checkmate"]) + if(href_list["checkmate"]) if(cooling_down) message_admins("Too many checkmates on chessboard, possible HREF exploits: [key_name_admin(usr)] on [src] (JMP)") return @@ -82,5 +90,11 @@ spawn(600) cooling_down = 0 - if (href_list["close"]) + if(href_list["close"]) close_game() + +/obj/machinery/gameboard/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob, params) + if(istype(G, /obj/item/weapon/wrench)) + default_unfasten_wrench(user, G) + else if(istype(G, /obj/item/weapon/crowbar)) + default_deconstruction_crowbar(G, ignore_panel = 1) 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/portable_turret.dm b/code/game/machinery/portable_turret.dm index eab12bb22d5..fb1ef8c8740 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -99,13 +99,12 @@ one_access = 0 /obj/machinery/porta_turret/proc/setup() - var/obj/item/weapon/gun/energy/E = installation //All energy-based weapons are applicable - if(istext(installation)) E = text2path(installation) - //var/obj/item/ammo_casing/shottype = E.projectile_type + var/obj/item/weapon/gun/energy/E= new installation //All energy-based weapons are applicable + var/obj/item/ammo_casing/shottype = E.ammo_type[1] - projectile = initial(E.projectile_type) + projectile = shottype.projectile_type eprojectile = projectile - shot_sound = initial(E.fire_sound) + shot_sound = shottype.fire_sound eshot_sound = shot_sound weapon_setup(installation) @@ -561,9 +560,6 @@ var/list/turret_icons if(get_dist(src, L) > 7) //if it's too far away, why bother? return TURRET_NOT_TARGET - if(!check_trajectory(L, src)) //check if we have true line of sight - return TURRET_NOT_TARGET - if(emagged) // If emagged not even the dead get a rest return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET @@ -670,6 +666,8 @@ var/list/turret_icons return /obj/machinery/porta_turret/proc/shootAt(var/mob/living/target) + if(!raised) //the turret has to be raised in order to fire - makes sense, right? + return //any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power! if(!emagged) //if it hasn't been emagged, it has to obey a cooldown rate if(last_fired || !raised) //prevents rapid-fire shooting, unless it's been emagged @@ -684,10 +682,6 @@ var/list/turret_icons if(!istype(T) || !istype(U)) return - if(!raised) //the turret has to be raised in order to fire - makes sense, right? - return - - update_icon() var/obj/item/projectile/A if(emagged || lethal) @@ -698,18 +692,17 @@ var/list/turret_icons if(projectile) A = new projectile(loc) playsound(loc, shot_sound, 75, 1) - A.original = target // Lethal/emagged turrets use twice the power due to higher energy beams // Emagged turrets again use twice as much power due to higher firing rates use_power(reqpower * (2 * (emagged || lethal)) * (2 * emagged)) - //Shooting Code: + A.original = target A.current = T A.yo = U.y - T.y A.xo = U.x - T.x - spawn(1) - A.process() + A.fire() + return A /datum/turret_checks var/enabled diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 92bca16c5b7..a1559c4fb3a 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -203,7 +203,8 @@ if(istype(O,/obj/item/weapon/gun/energy/disabler/cyborg)) var/obj/item/weapon/gun/energy/disabler/cyborg/D = O if(D.power_supply.charge < D.power_supply.maxcharge) - D.power_supply.give(D.charge_cost) + var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select] + D.power_supply.give(E.e_cost) D.update_icon() else D.charge_tick = 0 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/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 9d9481aba04..290e3352ea8 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -387,7 +387,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() src.receive_information(signal, src) // Try sending it! - var/list/try_send = list("/obj/machinery/telecomms/server", "/obj/machinery/telecomms/hub", "/obj/machinery/telecomms/broadcaster", "/obj/machinery/telecomms/bus") + var/list/try_send = list("/obj/machinery/telecomms/server", "/obj/machinery/telecomms/hub", "/obj/machinery/telecomms/broadcaster") var/i = 0 for(var/send in try_send) if(i) diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 82060d47bc2..f0b6ce34ef7 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -227,15 +227,15 @@ if(1) A = new /obj/item/projectile/beam(loc) if(2) - A = new /obj/item/projectile/beam/heavylaser(loc) + A = new /obj/item/projectile/beam/laser/heavylaser(loc) if(3) A = new /obj/item/projectile/beam/pulse(loc) if(4) A = new /obj/item/projectile/magic/change(loc) if(5) - A = new /obj/item/projectile/lasertag/blue(loc) + A = new /obj/item/projectile/beam/lasertag/bluetag(loc) if(6) - A = new /obj/item/projectile/lasertag/red(loc) + A = new /obj/item/projectile/beam/lasertag/redtag(loc) A.original = target use_power(500) else @@ -248,8 +248,7 @@ A.current = T A.yo = U.y - T.y A.xo = U.x - T.x - spawn( 0 ) - A.process() + A.fire() return diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 29880e519ec..e022e0c6a4b 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -849,7 +849,7 @@ product_ads = "Float like an astronaut, sting like a bullet!;Express your second amendment today!;Guns don't kill people, but you can!;Who needs responsibilities when you have guns?" vend_reply = "Remember the name: Liberation Station!" products = list(/obj/item/weapon/gun/projectile/automatic/pistol/deagle/gold = 2,/obj/item/weapon/gun/projectile/automatic/pistol/deagle/camo = 2, - /obj/item/weapon/gun/projectile/automatic/pistol/m2411 = 2,/obj/item/weapon/gun/projectile/automatic/proto = 2, + /obj/item/weapon/gun/projectile/automatic/pistol/m1911 = 2,/obj/item/weapon/gun/projectile/automatic/proto = 2, /obj/item/weapon/gun/projectile/shotgun/automatic/combat = 2,/obj/item/weapon/gun/projectile/automatic/gyropistol = 1, /obj/item/weapon/gun/projectile/shotgun = 2,/obj/item/weapon/gun/projectile/automatic/ar = 2) premium = list(/obj/item/ammo_box/magazine/smgm9mm = 2,/obj/item/ammo_box/magazine/m50 = 4,/obj/item/ammo_box/magazine/m45 = 2,/obj/item/ammo_box/magazine/m75 = 2) diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index f79c43068ee..05b3dac0e63 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -384,7 +384,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun name = "Syringe Gun" desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/projectile.dmi' icon_state = "syringegun" item_state = "syringegun" lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' @@ -666,4 +666,4 @@ for(var/reagent in S.processed_reagents) S.reagents.add_reagent(reagent,amount) S.chassis.use_power(energy_drain) - return 1 \ No newline at end of file + return 1 diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index d95cbaff799..ae5595d69e5 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -5,6 +5,10 @@ var/projectile var/fire_sound var/size=0 + var/projectiles_per_shot = 1 + var/variance = 0 + var/randomspread = 0 //use random spread for machineguns, instead of shotgun scatter + var/projectile_delay = 0 /obj/item/mecha_parts/mecha_equipment/weapon/can_attach(var/obj/mecha/combat/M as obj) if(..()) @@ -16,32 +20,51 @@ return 1 return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/proc/get_shot_amount() + return projectiles_per_shot -/obj/item/mecha_parts/mecha_equipment/weapon/energy - name = "General Energy Weapon" - size = 2 - action(target) - if(!action_checks(target)) return - var/turf/curloc = chassis.loc - var/atom/targloc = get_turf(target) - if (!targloc || !istype(targloc, /turf) || !curloc) - return - if (targloc == curloc) - return - set_ready_state(0) - playsound(chassis, fire_sound, 50, 1) +/obj/item/mecha_parts/mecha_equipment/weapon/action(target, params) + if(!action_checks(target)) + return 0 + + var/turf/curloc = get_turf(chassis) + var/turf/targloc = get_turf(target) + if (!targloc || !istype(targloc) || !curloc) + return 0 + if (targloc == curloc) + return 0 + + set_ready_state(0) + for(var/i=1 to get_shot_amount()) var/obj/item/projectile/A = new projectile(curloc) A.firer = chassis.occupant A.original = target A.current = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - chassis.use_power(energy_drain) - A.process() - chassis.log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return + var/spread = 0 + if(variance) + if(randomspread) + spread = round((rand() - 0.5) * variance) + else + spread = round((i / projectiles_per_shot - 0.5) * variance) + A.preparePixelProjectile(target, targloc, chassis.occupant, params, spread) + + chassis.use_power(energy_drain) + A.fire() + playsound(chassis, fire_sound, 50, 1) + + sleep(max(0, projectile_delay)) + set_ready_state(0) + log_message("Fired from [name], targeting [target].") + var/turf/T = get_turf(src) + msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") + log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/energy + name = "General Energy Weapon" + size = 2 /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser equip_cooldown = 8 @@ -56,7 +79,7 @@ name = "CH-LC \"Solaris\" Laser Cannon" icon_state = "mecha_laser" energy_drain = 40 - projectile = /obj/item/projectile/beam/heavylaser + projectile = /obj/item/projectile/beam/laser/heavylaser fire_sound = 'sound/weapons/lasercannonfire.ogg' /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion @@ -82,25 +105,25 @@ icon_state = "pulse1_bl" var/life = 20 - Bump(atom/A) - A.bullet_act(src, def_zone) - src.life -= 10 - if(ismob(A)) - var/mob/M = A - if(istype(firer, /mob)) - M.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]" - firer.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]" - log_attack("[firer] ([firer.ckey]) shot [M] ([M.ckey]) with a [src]") - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer +/obj/item/projectile/beam/pulse/heavy/Bump(atom/A) + A.bullet_act(src, def_zone) + life -= 10 + if(ismob(A)) + var/mob/M = A + if(istype(firer, /mob)) + M.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]" + firer.attack_log += "\[[time_stamp()]\] [firer]/[firer.ckey] shot [M]/[M.ckey] with a [src]" + log_attack("[firer] ([firer.ckey]) shot [M] ([M.ckey]) with a [src]") + if(!iscarbon(firer)) + M.LAssailant = null else - M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a [src]" - log_attack("UNKNOWN shot [M] ([M.ckey]) with a [src]") - if(life <= 0) - qdel(src) - return + M.LAssailant = firer + else + M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a [src]" + log_attack("UNKNOWN shot [M] ([M.ckey]) with a [src]") + if(life <= 0) + qdel(src) + return /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser @@ -119,89 +142,89 @@ equip_cooldown = 150 range = MELEE|RANGED - can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 +/obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target, params) + if(!chassis) + return 0 + if(energy_drain && chassis.get_charge() < energy_drain) + return 0 + if(!equip_ready) return 0 - action(target) - if(!chassis) - return 0 - if(energy_drain && chassis.get_charge() < energy_drain) - return 0 - if(!equip_ready) - return 0 + playsound(chassis, 'sound/items/AirHorn.ogg', 100, 1) + chassis.occupant_message("HONK") + for(var/mob/living/carbon/M in ohearers(6, chassis)) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) + continue + to_chat(M, "HONK") + M.sleeping = 0 + M.stuttering = 20 + M.ear_deaf = 30 + M.Weaken(3) + if(prob(30)) + M.Stun(10) + M.Paralyse(4) + else + M.Jitter(500) + ///else the mousetraps are useless + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(isobj(H.shoes)) + var/thingy = H.shoes + H.unEquip(H.shoes) + walk_away(thingy,chassis,15,2) + spawn(20) + if(thingy) + walk(thingy,0) + for(var/obj/mecha/combat/recitence/R in oview(6, chassis)) + R.occupant_message("\The [R] has protected you from [chassis]'s HONK at the cost of some power.") + R.use_power(R.get_charge() / 4) - playsound(chassis, 'sound/items/AirHorn.ogg', 100, 1) - chassis.occupant_message("HONK") - for(var/mob/living/carbon/M in ohearers(6, chassis)) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) - continue - to_chat(M, "HONK") - M.sleeping = 0 - M.stuttering = 20 - M.ear_deaf = 30 - M.Weaken(3) - if(prob(30)) - M.Stun(10) - M.Paralyse(4) - else - M.Jitter(500) - ///else the mousetraps are useless - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(isobj(H.shoes)) - var/thingy = H.shoes - H.unEquip(H.shoes) - walk_away(thingy,chassis,15,2) - spawn(20) - if(thingy) - walk(thingy,0) - for(var/obj/mecha/combat/recitence/R in oview(6, chassis)) - R.occupant_message("\The [R] has protected you from [chassis]'s HONK at the cost of some power.") - R.use_power(R.get_charge() / 4) - - chassis.use_power(energy_drain) - log_message("Honked from [src.name]. HONK!") - var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] used a Mecha Honker in ([T.x], [T.y], [T.z] - JMP)") - log_game("[key_name(chassis.occupant)] used a Mecha Honker in [T.x], [T.y], [T.z]") - do_after_cooldown() - return + chassis.use_power(energy_drain) + log_message("Honked from [name]. HONK!") + var/turf/T = get_turf(src) + msg_admin_attack("[key_name_admin(chassis.occupant)] used a Mecha Honker in ([T.x], [T.y], [T.z] - JMP)") + log_game("[key_name(chassis.occupant)] used a Mecha Honker in [T.x], [T.y], [T.z]") + do_after_cooldown() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic name = "General Ballisic Weapon" var/projectiles var/projectile_energy_cost size = 2 - action_checks(atom/target) - if(..()) - if(projectiles > 0) - return 1 - return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action_checks(atom/target) + if(..()) + if(projectiles > 0) + return 1 + return 0 - get_equip_info() - return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info() + return "[..()]\[[projectiles]\][(projectiles < initial(projectiles))?" - Rearm":null]" - proc/rearm() - if(projectiles < initial(projectiles)) - var/projectiles_to_add = initial(projectiles) - projectiles - while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add) - projectiles++ - projectiles_to_add-- - chassis.use_power(projectile_energy_cost) - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - log_message("Rearmed [src.name].") - return +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/proc/rearm() + if(projectiles < initial(projectiles)) + var/projectiles_to_add = initial(projectiles) - projectiles + while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add) + projectiles++ + projectiles_to_add-- + chassis.use_power(projectile_energy_cost) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + log_message("Rearmed [name].") + return - Topic(href, href_list) - ..() - if (href_list["rearm"]) - src.rearm() - return +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/Topic(href, href_list) + ..() + if (href_list["rearm"]) + rearm() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine name = "FNX-66 Carbine" @@ -211,41 +234,6 @@ fire_sound = 'sound/weapons/Gunshot.ogg' projectiles = 24 projectile_energy_cost = 15 - var/projectiles_per_shot = 1 - var/deviation = 0.0 - - action(atom/target) - if(!action_checks(target)) return - var/turf/targloc = get_turf(target) - var/target_x = targloc.x - var/target_y = targloc.y - var/target_z = targloc.z - targloc = null - spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) - if(!chassis) break - var/turf/curloc = get_turf(chassis) - targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) - if (!targloc || !curloc) - continue - if (targloc == curloc) - continue - - playsound(chassis, fire_sound, 50, 1) - var/obj/item/projectile/A = new projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - A.process() - sleep(2) - set_ready_state(0) - log_message("Fired from [src.name], targeting [target].") - var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") - log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") - do_after_cooldown() - return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine/silenced name = "\improper S.H.H. \"Quietus\" Carbine" @@ -270,36 +258,8 @@ fire_sound = 'sound/weapons/Gunshot.ogg' projectiles = 40 projectile_energy_cost = 25 - var/projectiles_per_shot = 4 - var/deviation = 0.7 - - action(atom/target) - if(!action_checks(target)) return - var/turf/curloc = get_turf(chassis) - var/turf/targloc = get_turf(target) - if(!curloc || !targloc) return - var/target_x = targloc.x - var/target_y = targloc.y - var/target_z = targloc.z - targloc = null - for(var/i=1 to min(projectiles, projectiles_per_shot)) - targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) - if(!targloc || targloc == curloc) - break - playsound(chassis, fire_sound, 80, 1) - var/obj/item/projectile/A = new projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - set_ready_state(0) - A.process() - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return - - + projectiles_per_shot = 4 + variance = 25 /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg name = "Ultra AC 2" @@ -309,38 +269,9 @@ fire_sound = 'sound/weapons/Gunshot.ogg' projectiles = 300 projectile_energy_cost = 20 - var/projectiles_per_shot = 3 - var/deviation = 0.3 - - action(atom/target) - if(!action_checks(target)) return - var/turf/targloc = get_turf(target) - var/target_x = targloc.x - var/target_y = targloc.y - var/target_z = targloc.z - targloc = null - spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) - if(!chassis) break - var/turf/curloc = get_turf(chassis) - targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) - if (!targloc || !curloc) - continue - if (targloc == curloc) - continue - - playsound(chassis, fire_sound, 50, 1) - var/obj/item/projectile/A = new projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - A.process() - sleep(2) - set_ready_state(0) - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return + projectiles_per_shot = 3 + variance = 6 + projectile_delay = 2 /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack name = "SRM-8 Missile Rack" @@ -353,20 +284,21 @@ var/missile_speed = 2 var/missile_range = 30 - action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/missile/M = new projectile(chassis.loc) - M.primed = 1 - playsound(chassis, fire_sound, 50, 1) - M.throw_at(target, missile_range, missile_speed, chassis) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - var/turf/T = get_turf(src) - msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") - log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") - do_after_cooldown() +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/action(target, params) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/missile/M = new projectile(chassis.loc) + M.primed = 1 + playsound(chassis, fire_sound, 50, 1) + M.throw_at(target, missile_range, missile_speed, chassis) + projectiles-- + log_message("Fired from [name], targeting [target].") + var/turf/T = get_turf(src) + msg_admin_attack("[key_name_admin(chassis.occupant)] fired a [src] in ([T.x], [T.y], [T.z] - JMP)") + log_game("[key_name(chassis.occupant)] fired a [src] in [T.x], [T.y], [T.z]") + do_after_cooldown() + return /obj/item/missile @@ -375,13 +307,13 @@ var/primed = null throwforce = 15 - throw_impact(atom/hit_atom) - if(primed) - explosion(hit_atom, 0, 0, 2, 4, 0) - qdel(src) - else - ..() - return +/obj/item/missile/throw_impact(atom/hit_atom) + if(primed) + explosion(hit_atom, 0, 0, 2, 4, 0) + qdel(src) + else + ..() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang name = "SGL-6 Grenade Launcher" @@ -394,18 +326,19 @@ equip_cooldown = 60 var/det_time = 20 size=1 - action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc) - playsound(chassis, fire_sound, 50, 1) - F.throw_at(target, missile_range, missile_speed, chassis) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - spawn(det_time) - F.prime() - do_after_cooldown() +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/action(target, params) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc) + playsound(chassis, fire_sound, 50, 1) + F.throw_at(target, missile_range, missile_speed, chassis) + projectiles-- + log_message("Fired from [name], targeting [target].") + spawn(det_time) + F.prime() + do_after_cooldown() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang//Because I am a heartless bastard -Sieve name = "SOB-3 Grenade Launcher" @@ -417,7 +350,7 @@ size=1 /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload - return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]" + return "* [chassis.selected==src?"":""][name][chassis.selected==src?"":""]\[[projectiles]\]" /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/rearm() return//Extra bit of security @@ -432,22 +365,23 @@ projectile_energy_cost = 100 equip_cooldown = 20 - can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 - action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/bananapeel/B = new projectile(chassis.loc) - playsound(chassis, fire_sound, 60, 1) - B.throw_at(target, missile_range, missile_speed, chassis) - projectiles-- - log_message("Bananed from [src.name], targeting [target]. HONK!") - do_after_cooldown() +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/action(target, params) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/bananapeel/B = new projectile(chassis.loc) + playsound(chassis, fire_sound, 60, 1) + B.throw_at(target, missile_range, missile_speed, chassis) + projectiles-- + log_message("Bananed from [name], targeting [target]. HONK!") + do_after_cooldown() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar @@ -460,23 +394,24 @@ projectile_energy_cost = 100 equip_cooldown = 10 - can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 - action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/device/assembly/mousetrap/M = new projectile(chassis.loc) - M.secured = 1 - playsound(chassis, fire_sound, 60, 1) - M.throw_at(target, missile_range, missile_speed, chassis) - projectiles-- - log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") - do_after_cooldown() +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/action(target, params) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/device/assembly/mousetrap/M = new projectile(chassis.loc) + M.secured = 1 + playsound(chassis, fire_sound, 60, 1) + M.throw_at(target, missile_range, missile_speed, chassis) + projectiles-- + log_message("Launched a mouse-trap from [name], targeting [target]. HONK!") + do_after_cooldown() + return /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas name = "PCMK-6 Bolas Launcher" @@ -489,23 +424,24 @@ projectile_energy_cost = 50 equip_cooldown = 10 - can_attach(obj/mecha/combat/gygax/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/can_attach(obj/mecha/combat/gygax/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 - action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/legcuffs/bolas/M = new projectile(chassis.loc) - playsound(chassis, fire_sound, 50, 1) - M.thrown_from = src - M.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/action(target, params) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/legcuffs/bolas/M = new projectile(chassis.loc) + playsound(chassis, fire_sound, 50, 1) + M.thrown_from = src + M.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Fired from [name], targeting [target].") + do_after_cooldown() + return /obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma equip_cooldown = 20 diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index ceeca47f72e..fcfccd1f9b6 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -219,7 +219,7 @@ // return ..() */ -/obj/mecha/proc/click_action(atom/target,mob/user) +/obj/mecha/proc/click_action(atom/target, mob/user, params) if(!src.occupant || src.occupant != user ) return if(user.stat || !user.canmove) return @@ -239,9 +239,9 @@ return if(!target.Adjacent(src)) if(selected && selected.is_ranged()) - selected.action(target) + selected.action(target, params) else if(selected && selected.is_melee()) - selected.action(target) + selected.action(target, params) else if(internal_damage&MECHA_INT_CONTROL_LOST) target = safepick(oview(1,src)) @@ -1991,4 +1991,4 @@ /obj/mecha/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list()) - flick_overlay(image('icons/mob/talk.dmi', bubble_loc, bubble_state,MOB_LAYER+1), bubble_recipients, 30) \ No newline at end of file + flick_overlay(image('icons/mob/talk.dmi', bubble_loc, bubble_state,MOB_LAYER+1), bubble_recipients, 30) 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/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index a916172118a..d88d5a309d1 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -118,3 +118,41 @@ /obj/item/weapon/relic = 3, "" = 11 ) + +/obj/effect/spawner/lootdrop/trade_sol_rare + name = "trader rare item spawner" + lootdoubles = 0 + color = "#00FFFF" + + loot = list( + /obj/item/weapon/card/emag_broken = 2, + /obj/item/weapon/defibrillator/compact/loaded = 2, + /obj/item/weapon/gun/energy/laser/retro = 2, + /obj/item/weapon/rcd/combat = 1, + /obj/item/weapon/rcd = 2, + ) + +/obj/effect/spawner/lootdrop/trade_sol_common + name = "trader common item spawner" + lootdoubles = 0 + color = "#00FFFF" + + loot = list( + /obj/item/weapon/tank/anesthetic = 2, + /obj/item/weapon/weldingtool/hugetank = 2, + /obj/item/weapon/pickaxe/diamond = 1, + /obj/item/device/spacepod_equipment/weaponry/mining_laser = 1, + /obj/item/device/paicard = 2, + /obj/item/weapon/gun/projectile/automatic/pistol = 2, + /obj/item/device/megaphone = 2, + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/weapon/stock_parts/cell/high = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/scanning_module = 1, + /obj/item/weapon/spacecash/c200 = 1, + /obj/item/weapon/airlock_electronics = 1, + /obj/item/weapon/gun/energy/kinetic_accelerator/super = 1, + /obj/item/pizzabox = 3, + ) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 417ad82d46b..2a3fe4a2a03 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -31,7 +31,7 @@ //If this is set, The item will make an action button on the player's HUD when picked up. var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button. - var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for + var/action_button_custom_type = null var/datum/action/item_action/action = null var/list/materials = list() 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/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 2a1bc41970b..f05b179e62a 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -27,35 +27,34 @@ effective or pretty fucking useless. origin_tech = "magnets=3;combat=3;syndicate=3" var/times_used = 0 //Number of times it's been used. - var/max_uses = 2 + var/max_uses = 5 - -/obj/item/device/batterer/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) - if(!user) return +/obj/item/device/batterer/examine(mob/user) + ..(user) if(times_used >= max_uses) - to_chat(user, "\red The mind batterer has been burnt out!") + to_chat(user, "[src] is out of charge.") + if(times_used < max_uses) + to_chat(user, "[src] has [max_uses-times_used] charges left.") + +/obj/item/device/batterer/attack_self(mob/living/carbon/user, flag = 0, emp = 0) + if(!user) + return + if(times_used >= max_uses) + to_chat(user, "The mind batterer has been burnt out!") return - user.attack_log += text("\[[time_stamp()]\] Used [src] to knock down people in the area.") - for(var/mob/living/carbon/human/M in orange(10, user)) - spawn() - if(prob(50)) + for(var/mob/living/carbon/human/M in oview(7, user)) + if(prob(50)) + M.Weaken(rand(4,7)) + add_logs(M, user, "stunned", src) + to_chat(M, "You feel a tremendous, paralyzing wave flood your mind.") + else + to_chat(M, "You feel a sudden, electric jolt travel through your head.") - M.Weaken(rand(10,20)) - if(prob(25)) - M.Stun(rand(5,10)) - to_chat(M, "\red You feel a tremendous, paralyzing wave flood your mind.") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - else - to_chat(M, "\red You feel a sudden, electric jolt travel through your head.") - - playsound(src.loc, 'sound/misc/interference.ogg', 50, 1) - to_chat(user, "\blue You trigger [src].") - times_used += 1 + playsound(loc, 'sound/misc/interference.ogg', 50, 1) + times_used++ + to_chat(user, "You trigger [src]. It has [max_uses-times_used] charges left.") if(times_used >= max_uses) icon_state = "battererburnt" diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 9e4d83592b0..5b4afe8095c 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -9,6 +9,7 @@ var/mob/attacher = null var/valve_open = 0 var/toggle = 1 + origin_tech = "materials=1;engineering=1" /obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D) @@ -187,7 +188,7 @@ attacher_name = "[key_name_admin(attacher)]" var/mob/mob = get_mob_by_key(src.fingerprintslast) - + bombers += "Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]" message_admins("Bomb valve opened at [A.name] (JMP) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name_admin(mob)]") log_game("Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]") 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/policetape.dm b/code/game/objects/items/policetape.dm index 9b1f27dea1b..ad46a511641 100644 --- a/code/game/objects/items/policetape.dm +++ b/code/game/objects/items/policetape.dm @@ -147,17 +147,14 @@ var/list/tape_roll_applications = list() tape_roll_applications[F] |= direction return -/obj/item/tape/Bumped(M as mob) - if(src.allowed(M)) - var/turf/T = get_turf(src) - M:loc = T - /obj/item/tape/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(!density) return 1 if(air_group || (height==0)) return 1 if ((mover.pass_flags & PASSTABLE || istype(mover, /obj/effect/meteor) || mover.throwing == 1) ) return 1 + else if(ismob(mover) && allowed(mover)) + return 1 else return 0 diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index bfb90de8cac..512baa30703 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -125,13 +125,13 @@ to_chat(usr, "This robot has had its disabler removed!") return 0 - if(T.recharge_time <= 2) + if(T.charge_delay <= 2) to_chat(R, "Maximum cooling achieved for this hardpoint!") to_chat(usr, "There's no room for another cooling unit!") return 0 else - T.recharge_time = max(2 , T.recharge_time - 4) + T.charge_delay = max(2 , T.charge_delay - 4) return 1 @@ -214,4 +214,4 @@ return 0 R.emagged = 1 - return 1 \ No newline at end of file + return 1 diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index c71f2e14182..fd3f5505f4f 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -114,7 +114,7 @@ bmark.pixel_x-- bmark.pixel_y-- - if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/practice)) + if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) bmark.icon_state = "scorch" bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design @@ -178,4 +178,4 @@ b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) - Target.bulletholes.Add(src) \ No newline at end of file + Target.bulletholes.Add(src) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index e41457f0c38..efba4f62a77 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -80,7 +80,7 @@ return to_chat(usr, "\blue Assembling grille...") - if (!do_after(usr, 10, target = src)) + if (!do_after(usr, 10, target = user)) return var /obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc ) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 2abf2dd36f5..9ed7ddc87d0 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -145,7 +145,6 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("bookcase", /obj/structure/bookcase, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \ - new/datum/stack_recipe("crossbow frame", /obj/item/weapon/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0), \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("easel", /obj/structure/easel, 3, one_per_turf = 1, on_floor = 1), \ diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 41c2946a0c1..bd799640122 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -130,7 +130,7 @@ return if (R.time) to_chat(usr, "\blue Building [R.title] ...") - if (!do_after(usr, R.time, target = src)) + if (!do_after(usr, R.time, target = usr)) return if (src.amount < R.req_amount*multiplier) return @@ -194,20 +194,24 @@ /obj/item/stack/proc/get_max_amount() return max_amount +/obj/item/stack/proc/split(mob/user, amt) + var/obj/item/stack/F = new type(user, amt) + F.copy_evidences(src) + if(isliving(user)) + add_fingerprint(user) + F.add_fingerprint(user) + use(amt) + return F + /obj/item/stack/attack_hand(mob/user as mob) if (user.get_inactive_hand() == src) - var/obj/item/stack/F = new src.type( user, 1) - F.copy_evidences(src) + var/obj/item/stack/F = split(user, 1) user.put_in_hands(F) - src.add_fingerprint(user) - F.add_fingerprint(user) - use(1) - if (src && usr.machine==src) - spawn(0) src.interact(usr) + if(src && usr.machine == src) + spawn(0) + interact(usr) else ..() - update_icon() - return /obj/item/stack/attackby(obj/item/W as obj, mob/user as mob, params) ..() diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 25ade73eb38..f2f07174ec5 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1318,7 +1318,7 @@ obj/item/toy/cards/deck/syndicate/black /obj/item/toy/russian_revolver name = "russian revolver" desc = "for fun and games!" - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/projectile.dmi' icon_state = "detective_gold" item_state = "gun" lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm index e0ac96c4feb..b0a1c45622d 100644 --- a/code/game/objects/items/weapons/chrono_eraser.dm +++ b/code/game/objects/items/weapons/chrono_eraser.dm @@ -41,12 +41,11 @@ icon = 'icons/obj/chronos.dmi' icon_state = "chronogun" item_state = "chronogun" - w_class = 3.0 - projectile_type = "/obj/item/projectile/energy/chrono_beam" - fire_sound = 'sound/weapons/Laser.ogg' - charge_cost = 0 - fire_delay = 50 + w_class = 3 flags = NODROP + ammo_type = list(/obj/item/ammo_casing/energy/chrono_beam) + can_charge = 0 + fire_delay = 50 var/obj/item/weapon/chrono_eraser/TED = null var/obj/effect/chrono_field/field = null var/turf/startpos = null @@ -60,12 +59,13 @@ qdel(src) /obj/item/weapon/gun/energy/chrono_gun/dropped() + ..() qdel(src) /obj/item/weapon/gun/energy/chrono_gun/update_icon() return -/obj/item/weapon/gun/energy/chrono_gun/Fire() +/obj/item/weapon/gun/energy/chrono_gun/process_fire() if(field) field_disconnect(field) ..() @@ -125,18 +125,23 @@ nodamage = 1 var/obj/item/weapon/gun/energy/chrono_gun/gun = null -/obj/item/projectile/energy/chrono_beam/process() +/obj/item/projectile/energy/chrono_beam/fire() gun = firer.get_active_hand() if(istype(gun)) return ..() else return 0 -/obj/item/projectile/energy/chrono_beam/on_hit(var/atom/target) +/obj/item/projectile/energy/chrono_beam/on_hit(atom/target) if(target && gun && isliving(target)) var/obj/effect/chrono_field/F = new(target.loc, target, gun) gun.field_connect(F) +/obj/item/ammo_casing/energy/chrono_beam + name = "eradication beam" + projectile_type = /obj/item/projectile/energy/chrono_beam + icon_state = "chronobolt" + e_cost = 0 /obj/effect/chrono_field name = "eradication field" @@ -256,4 +261,4 @@ #undef CHRONO_BEAM_RANGE -#undef CHRONO_FRAME_COUNT \ No newline at end of file +#undef CHRONO_FRAME_COUNT diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 73eda279b3d..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 @@ -368,8 +370,26 @@ update_icon() return if(H.heart_attack) - H.heart_attack = 0 - if(H.stat == 2) + if(!H.get_int_organ(/obj/item/organ/internal/heart) && !H.get_int_organ(/obj/item/organ/internal/brain/slime)) //prevents defibing someone still alive suffering from a heart attack attack if they lack a heart + user.visible_message("[defib] buzzes: Resuscitation failed - Failed to pick up any heart electrical activity.") + playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0) + busy = 0 + update_icon() + return + else + H.heart_attack = 0 + user.visible_message("[defib] pings: Cardiac arrhythmia corrected.") + M.visible_message("[M]'s body convulses a bit.") + playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1) + playsound(get_turf(src), "bodyfall", 50, 1) + playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0) + defib.deductcharge(revivecost) + busy = 0 + cooldown = 1 + update_icon() + defib.cooldowncheck(user) + return + if(H.stat == DEAD) var/health = H.health M.visible_message("[M]'s body convulses a bit.") playsound(get_turf(src), "bodyfall", 50, 1) @@ -377,7 +397,7 @@ for(var/obj/item/organ/external/O in H.organs) total_brute += O.brute_dam total_burn += O.burn_dam - if(total_burn <= 180 && total_brute <= 180 && !H.suiciding && !ghost && tplus < tlimit && !(NOCLONE in H.mutations)) + if(total_burn <= 180 && total_brute <= 180 && !H.suiciding && !ghost && tplus < tlimit && !(NOCLONE in H.mutations) && (H.get_int_organ(/obj/item/organ/internal/heart) || H.get_int_organ(/obj/item/organ/internal/brain/slime))) tobehealed = min(health + threshold, 0) // It's HILARIOUS without this min statement, let me tell you tobehealed -= 5 //They get 5 of each type of damage healed so excessive combined damage will not immediately kill them after they get revived H.adjustOxyLoss(tobehealed) @@ -452,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") @@ -481,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/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 879e82f9ee0..b56e103233e 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -90,7 +90,7 @@ item_state = "claymore" name = "holy claymore" desc = "A weapon fit for a crusade!" - w_class = 5 + w_class = 4 slot_flags = SLOT_BACK|SLOT_BELT sharp = 1 edge = 1 @@ -134,6 +134,13 @@ item_state = "katana" slot_flags = SLOT_BELT | SLOT_BACK +/obj/item/weapon/nullrod/claymore/multiverse + name = "extradimensional blade" + desc = "Once the harbringer of a interdimensional war, now a dormant souvenir. Still sharp though." + icon_state = "multiverse" + item_state = "multiverse" + slot_flags = SLOT_BELT + /obj/item/weapon/nullrod/claymore/saber name = "light energy sword" hitsound = 'sound/weapons/blade1.ogg' @@ -148,6 +155,12 @@ item_state = "swordred" desc = "Woefully ineffective when used on steep terrain." +/obj/item/weapon/nullrod/claymore/saber/pirate + name = "nautical energy sword" + icon_state = "cutlass1" + item_state = "cutlass1" + desc = "Convincing HR that your religion involved piracy was no mean feat." + /obj/item/weapon/nullrod/sord name = "\improper UNREAL SORD" desc = "This thing is so unspeakably HOLY you are having a hard time even holding it." @@ -179,6 +192,49 @@ desc = "Bad references are the DNA of the soul." attack_verb = list("chopped", "sliced", "cut", "zandatsu'd") +/obj/item/weapon/nullrod/scythe/talking + icon_state = "talking_sword" + item_state = "talking_sword" + name = "possessed blade" + desc = "When the station falls into chaos, it's nice to have a friend by your side." + attack_verb = list("chopped", "sliced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + var/possessed = FALSE + +/obj/item/weapon/nullrod/scythe/talking/attack_self(mob/living/user) + if(possessed) + return + + to_chat(user, "You attempt to wake the spirit of the blade...") + + possessed = TRUE + + var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, 0, 100) + var/mob/dead/observer/theghost = null + + if(candidates.len) + theghost = pick(candidates) + var/mob/living/simple_animal/shade/S = new(src) + S.real_name = name + S.name = name + S.ckey = theghost.ckey + var/input = stripped_input(S,"What are you named?", ,"", MAX_NAME_LEN) + + if(src && input) + name = input + S.real_name = input + S.name = input + else + to_chat(user, "The blade is dormant. Maybe you can try again later.") + possessed = FALSE + +/obj/item/weapon/nullrod/scythe/talking/Destroy() + for(var/mob/living/simple_animal/shade/S in contents) + to_chat(S, "You were destroyed!") + S.ghostize() + qdel(S) + return ..() + /obj/item/weapon/nullrod/hammmer icon_state = "hammeron" item_state = "hammeron" @@ -326,3 +382,75 @@ hitsound = 'sound/weapons/bladeslice.ogg' sharp = 1 edge = 1 + +/obj/item/weapon/nullrod/rosary + icon_state = "rosary" + item_state = null + name = "prayer beads" + desc = "A set of prayer beads used by many of the more traditional religions in space.
Vampires and other unholy abominations have learned to fear these." + force = 0 + throwforce = 0 + var/praying = 0 + +/obj/item/weapon/nullrod/rosary/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/nullrod/rosary/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M)) + return ..() + + if(!user.mind || user.mind.assigned_role != "Chaplain") + to_chat(user, "You are not close enough with [ticker.Bible_deity_name] to use [src].") + return + + if(praying) + to_chat(user, "You are already using [src].") + + user.visible_message("[user] kneels[M == user ? null : " next to [M]"] and begins to utter a prayer to [ticker.Bible_deity_name].", \ + "You kneel[M == user ? null : " next to [M]"] and begin a prayer to [ticker.Bible_deity_name].") + + praying = 1 + if(do_after(user, 150, target = M)) + if(istype(M, /mob/living/carbon/human)) // This probably should not work on vulps. They're unholy abominations. + var/mob/living/carbon/human/target = M + + if(target.mind) + if(iscultist(target)) + ticker.mode.remove_cultist(target.mind) // This proc will handle message generation. + praying = 0 + return + + if(target.mind.vampire && !target.mind.vampire.get_ability(/datum/vampire_passive/full)) // Getting a full prayer off on a vampire will interrupt their powers for a large duration. + target.mind.vampire.nullified = max(120, target.mind.vampire.nullified + 120) + to_chat(target, "[user]'s prayer to [ticker.Bible_deity_name] has interfered with your power!") + praying = 0 + return + + if(prob(25)) + to_chat(target, "[user]'s prayer to [ticker.Bible_deity_name] has eased your pain!") + target.adjustToxLoss(-5) + target.adjustOxyLoss(-5) + target.adjustBruteLoss(-5) + target.adjustFireLoss(-5) + + praying = 0 + + else + to_chat(user, "Your prayer to [ticker.Bible_deity_name] was interrupted.") + praying = 0 + +/obj/item/weapon/nullrod/rosary/process() + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/holder = loc + + if(src == holder.l_hand || src == holder.r_hand) // Holding this in your hand will + for(var/mob/living/carbon/human/M in range(5)) + if(M.mind.vampire && !M.mind.vampire.get_ability(/datum/vampire_passive/full)) + M.mind.vampire.nullified = max(5, M.mind.vampire.nullified + 2) + if(prob(10)) + to_chat(M, "Being in the presence of [holder]'s [src] is interfering with your powers!") + + + diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index c466c5ba811..67b52da31ec 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -2,7 +2,7 @@ name = "implant" icon = 'icons/obj/implants.dmi' icon_state = "generic" //Shows up as the action button icon - action_button_is_hands_free = 1 + action_button_custom_type = /datum/action/item_action/hands_free origin_tech = "materials=2;biotech=3;programming=2" var/activated = 1 //1 for implant types that can be activated, 0 for ones that are "always on" like loyalty implants diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index 547206da29c..78e63ddfae4 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -56,11 +56,11 @@ ticker.mode.traitors += H.mind H.mind.special_role = "traitor" to_chat(H, "You're now completely loyal to [user.name]! You now must lay down your life to protect them and assist in their goals at any cost.") - var/datum/objective/protect/p = new - p.owner = H.mind - p.target = user:mind - p.explanation_text = "Obey every order from and protect [user:real_name], the [user:mind:assigned_role=="MODE" ? (user:mind:special_role) : (user:mind:assigned_role)]." - H.mind.objectives += p + var/datum/objective/protect/mindslave/MS = new + MS.owner = H.mind + MS.target = user:mind + MS.explanation_text = "Obey every order from and protect [user:real_name], the [user:mind:assigned_role=="MODE" ? (user:mind:special_role) : (user:mind:assigned_role)]." + H.mind.objectives += MS for(var/datum/objective/objective in H.mind.objectives) to_chat(H, "Objective #1: [objective.explanation_text]") @@ -71,10 +71,16 @@ var/datum/mindslaves/slaved = user.mind.som H.mind.som = slaved slaved.serv += H - slaved.add_serv_hud(user.mind,"syndicate")//handles master servent icons - slaved.add_serv_hud(H.mind,"mindslave") + slaved.add_serv_hud(user.mind, "master") //handles master servent icons + slaved.add_serv_hud(H.mind, "mindslave") log_admin("[ckey(user.key)] has mind-slaved [ckey(H.key)].") activated = 1 return 1 - return 0 \ No newline at end of file + return 0 + +/obj/item/weapon/implant/traitor/removed(mob/target) + if(..()) + ticker.mode.remove_traitor_mind(target.mind) + return 1 + return 0 \ No newline at end of file diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 3a371b8191e..b580a024b91 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -1815,18 +1815,6 @@

-

Atmospherics Technician


-
    -
  1. Atmospheric Technicians are permitted to completely repipe the Atmospherics Piping Setup, provided they do not pump harmful gases into anywhere except the Turbine;
  2. -
  3. Atmospheric Technicians are not permitted to create volatile mixes using Plasma and Oxygen, nor are they permitted to create any potentially harmful mixes with Carbon Dioxide and/or Nitrous Oxide. An exception is made when working with the Turbine;
  4. -
  5. Atmospheric Technicians are permitted to cool Plasma and store it for later use in Radiation Collectors. Likewise, they are permitted to cool Nitrogen or Carbon Dioxide and store it for use as coolant for the Supermatter Engine;
  6. -
  7. Atmospheric Technicians are not permitted to take the axe out of its case unless there is an immediate and urgent threat to their life or urgent access to crisis locations is necessary. The axe must be returned to the case afterwards, and the case locked;
  8. -
  9. Atmospheric Technicians are not permitted to tamper with the default values on Air Alarms. They are, however, permitted to create small, acclimatized rooms for species that require special atmospheric conditions (such as Plasmamen and Vox), provided they receive express permission from the Chief Engineer;
  10. -
  11. Atmospheric Technicians must periodically check on the Central Alarms Computer, in periods of, at most, thirty (30) minutes;
  12. -
  13. Atmospheric Technicians must respond promptly to piping and station breaches. Failure to report within fifteen (15) minutes will be considered a breach of Standard Operating Procedure, unless there are no spare Atmospheric Technicians to report, or an Engineer has arrived on scene first. All Hazard Zones must be cordoned off with Engineering Tape, for the sake of everyone else
  14. -
-

-

Shaft Miner


  1. Shaft Miners are not permitted to bring Gibtonite aboard the station;
  2. @@ -2412,7 +2400,104 @@
  3. Demotion of Chief Engineer and reparation of Engine if no threat manifests.


  4. - + + + + + "} + +/obj/item/weapon/book/manual/sop_command + name = "Command Standard Operating Procedures" + desc = "A set of guidelines aiming at the safe conduct of all Command activities." + icon_state = "book4" + author = "Nanotrasen" + title = "Command Standard Operating Procedures" + dat = {" + + + + + + + + +

    Contents

    +
      +
    1. Foreword
    2. +
    3. Captain
    4. +
    5. Head of Personnel
    6. +
    7. NanoTrasen Representative
    8. +
    9. Blueshield Officer
    10. +
    11. AI
    12. +
    +

    + +

    FOREWORD


    + Job SOP should not be a considered a checklist of conditions to fire someone over, and should not be rigidly followed to the letter in detriment of circumstances and context. + As always, SOP can be malleable if the situation so requires, and the decision to punish a crewmember for breaching it ultimately falls onto the relevant Head of Staff, + for Department Members, or Captain, for the Head of Staff.

    + +

    Captain


    +
      +
    1. The Captain is not permitted to perform regular Security Duty. However, they may still assist Security if they are understaffed, or if they see a crime being committed. However, the Captain is not permitted to take items from the Armory under normal circumstances, unless authorized by the Head of Security. In addition, the Captain may not requisition weaponry for themselves from Cargo and/or Science, unless there's an immediate threat to station and/or crew;
    2. +
    3. If a Department lacks a Head of Staff, the Captain should make reasonable efforts to appoint an Acting Head of Staff, if there are available personnel to fill the position;
    4. +
    5. The Captain is to ensure that Space Law is being correctly applied. This should be done in cooperation with the Head of Security;
    6. +
    7. The Captain is not to leave the NSS Cyberiad unless given specific permission by Central Command, or it happens to be the end of the shift. This includes via space or via the Gateway. To do so is to be considered abandoning their posts and is grounds for termination;
    8. +
    9. The Captain must keep the Nuclear Authentication Disk on their person at all times or, failing that, in the possession of the Head of Security or Blueshield;
    10. +
    11. The Captain is to attempt to resolve every issue that arises in Command locally before contacting Central Command;
    12. +
    13. The Captain is not permitted to carry their Antique Laser Gun or Space Armor unless there's an immediate emergency that requires attending to;
    14. +
    15. The Captain, despite being in charge of the Cyberiad, is not independent from NanoTrasen. Any attempts to disregard general company policy are to be considered an instant condition for contract termination;
    16. +
    17. The Captain may only promote personnel to a Acting Head of Staff position if there is no assigned Head of Staff associated with the Department. Said Acting Head of Staff must be a member of the Department they are to lead. See below for more information on Chain of Command;
    18. +
    19. The Captain may not fire any Head of Staff without reasonable justification (ie, incompetency, criminal activity, or otherwise any action that endangers/compromises the station and/or crew). The Captain may not fire any Central Command VIPs (ie, Blueshield, Magistrate, NanoTrasen Representative) without permission from Central Command, unless they are blatantly acting against the well-being and safety of the crew and station.
    20. +

    + +

    Head of Personnel


    +
      +
    1. The Head of Personnel may not transfer any personnel to another Department without authorization from the relevant Head of Staff. If no Head of Staff is available, the Head of Personnel may make a judgement call. This does not apply to Security, which always requires authorization from the Head of Security, or Genetics, which requires both Chief Medical Officer and Research Director approval. If there is no Head of Security active, no transfers are allowed to Security without authorization from the Captain;
    2. +
    3. The Head of Personnel may not give any personnel increased access without authorization from the relevant Head of Staff. This includes the Head of Personnel. In addition, the Head of Personnel may only give Captain-Level access to someone if they are the Acting Captain. This access is to be removed when a proper Captain arrives on the station;
    4. +
    5. The Head of Personnel may not increase any Job Openings unless the relevant Head of Staff approves;
    6. +
    7. The Head of Personnel may not fire any personnel without authorization from the relevant Head of Staff, unless other conditions apply (see Space Law and General Standard Operating Procedure);
    8. +
    9. The Head of Personnel may not promote any personnel to the following Jobs without authorization from Central Command: Barber, Brig Physician, NanoTrasen Representative, Blueshield, Security Pod Pilot, Mechanic and Magistrate; (This is due to them being karma locked. Do not promote people to these positions without approval from the Administrators);
    10. +
    11. The Head of Personnel is free to utilize paperwork at their discretion. However, during major station emergencies, expediency should take precedence over bureaucracy;
    12. +
    13. The Head of Personnel may not leave their office unmanned if there are personnel waiting in line. Failure to respond to personnel with a legitimate request within ten (10) minutes, either via radio or in person, is to be considered a breach of Standard Operating Procedure;
    14. +
    15. Despite nominally being in charge of Supply, the Head of Personnel should allow the Quartermaster to run the Department, unless they prove themselves to be incompetent/dangerous;
    16. +
    17. The Head of Personnel is bound to the same rules regarding ordering Cargo Crates as the Quartermaster and Cargo Technicians. In addition, the Head of Personnel may not order unneeded, non-essential items against the wishes of Cargo;
    18. +
    19. The Head of Personnel is not permitted to perform Security duty. The Head of Personnel is permitted to carry an Energy Gun, for self-defence only.
    20. +

    + +

    NanoTrasen Representative


    +
      +
    1. The NanoTrasen Representative is to ensure that every Department is following Standard Operating Procedure, up to and including the respective Head of Staff. If a Head of Staff is not available for a Department, the NanoTrasen Representative must ensure that the Captain appoints an Acting Head of Staff for said Department;
    2. +
    3. The NanoTrasen Representative must attempt to resolve any breach of Standard Operating Procedure locally before contacting Central Command. This is an imperative: Standard Operating Procedure should always be followed unless there is a very good reason not to;
    4. +
    5. The NanoTrasen Representative must, together with the Magistrate and Head of Security, ensure that Space Law is being followed and correctly applied;
    6. +
    7. The NanoTrasen Representative may not threaten the use of a fax in order to gain leverage over any personnel, up to and including Command. In addition they may not threaten to fire, or have Central Command, fire anyone, unless they actually possess a demotion note;
    8. +
    9. The NanoTrasen Representative is permitted to carry their Stun-Cane, or a Telescopic Baton if the Stun-Cane is lost.
    10. +

    + +

    Blueshield Officer


    +
      +
    1. The Blueshield may not conduct arrests under the same conditions as Security. However, they may apprehend any personnel that trespass on a Head of Staff Office or Command Area, any personnel that steal from those locations, or any personnel that steal from and/or injure any Head of Staff or Central Command VIP. However, all apprehended personnel are to be processed by Security personnel;
    2. +
    3. The Blueshield is to put the lives of Command over those of any other personnel, the Blueshield included. Their continued well-being is the Blueshield's top priority. This includes applying basic first aid and making sure they are revived if killed;
    4. +
    5. The Blueshield is to protect the lives of Command personnel, not follow their orders to a fault. The Blueshield is not to interfere with legal demotions or arrests. To do so is to place themselves under the Special Modifier Aiding and Abetting;
    6. +
    7. The Blueshield is not to apply Lethal Force unless there is a clear and present danger to their life, or to the life of a member of Command, and the assailant cannot be non-lethally detained.
    8. +

    + +

    AI


    + The following are procedures for AI Maintenance:
    +
      +
    1. Only the Captain or Research Director may enter the AI Upload to perform Law Changes (see below), and only the Captain, Research Director or Chief Engineer may enter the AI Core to perform a Carding (see below);
    2. +
    3. No Law Changes are to be performed without approval from the Captain and Research Director. The only Lawsets to be used are those provided by NanoTrasen. Failure to legally perform a Law Change is to be considered Sabotage. Command must be informed prior to the Law Change, and all objections must be taken into consideration. If the number of Command personnel opposing the Law Change is greater than the number of Command personnel in favour, the Law Change is not to be done. If the Law Change is performed, the crew is to be immediately informed of the new Law(s);
    4. +
    5. The AI may not be Carded unless it it clearly malfunctioning or subverted. However, any member of Command may card it if the AI agrees to it, either at the end of the shift, or due to external circumstances (such as massive damage to the AI Satellite);
    6. +
    7. The AI Upload and Minisat Antechamber Turrets are to be kept on Non-Lethal in Code Green and Code Blue. The AI Core Turrets are to be kept on Lethal at all times. If a legal Law Change or Carding is occurring, the Turrets are to be disabled;
    8. +
    9. If the AI Unit is not malfunctioning or subverted, any attempt at performing an illegal Carding or Law Change is to be responded to with non-lethal force. If the illegal attempts persist, and the perpetrator is demonstrably hostile, lethal force from Command/Security is permitted;
    10. +
    11. Freeform Laws are only to be added if absolutely necessary due to external circumstances (such as major station emergencies). Adding unnecessary Freeform Laws is not permitted. Exception is made if the AI Unit and majority of Command agree to the Freeform Law that is proposed;
    12. +
    13. Any use of the "Purge" Module is to be followed by the upload of a NanoTrasen-approved Lawset immediately. AI Units must be bound to a Lawset at all times.
    14. +

    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/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 62f60a91bc4..a34a8328457 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -128,7 +128,6 @@ materials = list() minor_fault = 1 - /obj/item/weapon/stock_parts/cell/high/slime name = "charged slime core" desc = "A yellow slime core infused with plasma, it crackles with power." @@ -138,6 +137,12 @@ materials = list() self_recharge = 1 // Infused slime cores self-recharge, over time +/obj/item/weapon/stock_parts/cell/pulse //200 pulse shots + name = "pulse rifle power cell" + maxcharge = 40000 + rating = 3 + chargerate = 1500 + /obj/item/weapon/stock_parts/cell/pulse/carbine name = "pulse carbine power cell" maxcharge = 4000 @@ -168,9 +173,3 @@ /obj/item/weapon/stock_parts/cell/emproof/corrupt() return - -/obj/item/weapon/stock_parts/cell/temperaturegun - name = "temperature gun cell" - desc = "A specially designed power cell for heating and cooling projectiles" - icon_state = "icell" - maxcharge = 900 \ No newline at end of file diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm index f7edba7e1c4..6e0500ffd38 100644 --- a/code/game/objects/items/weapons/stock_parts.dm +++ b/code/game/objects/items/weapons/stock_parts.dm @@ -131,7 +131,7 @@ name = "nano-manipulator" desc = "A tiny little manipulator used in the construction of certain devices." icon_state = "nano_mani" - origin_tech = "materials=3,programming=2" + origin_tech = "materials=3;programming=2" rating = 2 materials = list(MAT_METAL=30) @@ -173,7 +173,7 @@ name = "pico-manipulator" desc = "A tiny little manipulator used in the construction of certain devices." icon_state = "pico_mani" - origin_tech = "materials=5,programming=2" + origin_tech = "materials=5;programming=2" rating = 3 materials = list(MAT_METAL=30) 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/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index daefa0db457..07c8d836049 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -6,8 +6,17 @@ item_state = "utility" slot_flags = SLOT_BELT attack_verb = list("whipped", "lashed", "disciplined") + var/use_item_overlays = 0 // Do we have overlays for items held inside the belt? +/obj/item/weapon/storage/belt/update_icon() + if(use_item_overlays) + overlays.Cut() + for(var/obj/item/I in contents) + overlays += "[I.name]" + + ..() + /obj/item/weapon/storage/belt/proc/can_use() return is_equipped() @@ -35,6 +44,7 @@ desc = "Can hold various tools." icon_state = "utilitybelt" item_state = "utility" + use_item_overlays = 1 can_hold = list( "/obj/item/weapon/crowbar", "/obj/item/weapon/screwdriver", @@ -81,6 +91,7 @@ desc = "Can hold various medical equipment." icon_state = "medicalbelt" item_state = "medical" + use_item_overlays = 1 can_hold = list( "/obj/item/device/healthanalyzer", "/obj/item/weapon/dnainjector", @@ -120,6 +131,7 @@ desc = "Can hold various botanical supplies." icon_state = "botanybelt" item_state = "botany" + use_item_overlays = 1 can_hold = list( "/obj/item/device/analyzer/plant_analyzer", "/obj/item/weapon/minihoe", @@ -127,8 +139,8 @@ "/obj/item/weapon/reagent_containers/glass/fertilizer", "/obj/item/weapon/reagent_containers/glass/bottle", "/obj/item/weapon/plantspray", - "/obj/item/weapon/reagent_containers/syringe", - "/obj/item/weapon/reagent_containers/glass/beaker", +// "/obj/item/weapon/reagent_containers/syringe", +// "/obj/item/weapon/reagent_containers/glass/beaker", "/obj/item/weapon/lighter/zippo", "/obj/item/weapon/storage/fancy/cigarettes", "obj/item/weapon/rollingpaperpack", @@ -148,6 +160,7 @@ item_state = "security"//Could likely use a better one. storage_slots = 5 max_w_class = 3 + use_item_overlays = 1 can_hold = list( "/obj/item/weapon/grenade/flashbang", "/obj/item/weapon/grenade/chem_grenade/teargas", @@ -185,6 +198,7 @@ icon_state = "soulstonebelt" item_state = "soulstonebelt" storage_slots = 6 + use_item_overlays = 1 can_hold = list( "/obj/item/device/soulstone" ) @@ -230,6 +244,7 @@ item_state = "janibelt" storage_slots = 6 max_w_class = 4 // Set to this so the light replacer can fit. + use_item_overlays = 1 can_hold = list( "/obj/item/weapon/grenade/chem_grenade/cleaner", "/obj/item/device/lightreplacer", @@ -300,6 +315,21 @@ new /obj/item/ammo_casing/shotgun/beanbag(src) new /obj/item/ammo_casing/shotgun/beanbag(src) +/obj/item/weapon/storage/belt/bandolier/update_icon() + ..() + icon_state = "[initial(icon_state)]_[contents.len]" + +/obj/item/weapon/storage/belt/bandolier/attackby(obj/item/W, mob/user) + var/amount = contents.len + . = ..() + if(amount != contents.len) + update_icon() + +/obj/item/weapon/storage/belt/bandolier/remove_from_storage(obj/item/W as obj, atom/new_location) + ..() + update_icon() + + /obj/item/weapon/storage/belt/holster name = "shoulder holster" desc = "A holster to conceal a carried handgun. WARNING: Badasses only." @@ -318,6 +348,7 @@ icon_state = "soulstonebelt" item_state = "soulstonebelt" storage_slots = 6 + use_item_overlays = 1 can_hold = list( "/obj/item/weapon/gun/magic/wand" ) 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/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 3ab237084e6..29bcb4f8fe2 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -222,6 +222,10 @@ icon_state = "dualsaber0" /obj/item/weapon/twohanded/dualsaber/attack(target as mob, mob/living/user as mob) + if(HULK in user.mutations) + to_chat(user, "You grip the blade too hard and accidentally close it!") + unwield() + return ..() if((CLUMSY in user.mutations) && (wielded) &&prob(40)) to_chat(user, "\red You twirl around a bit before losing your balance and impaling yourself on the [src].") @@ -259,7 +263,10 @@ if(wielded) return 1 -/obj/item/weapon/twohanded/dualsaber/wield() +/obj/item/weapon/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. + if(HULK in M.mutations) + to_chat(M, "You lack the grace to wield this!") + return ..() hitsound = 'sound/weapons/blade1.ogg' 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 4a2ced79339..2b823041950 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -115,7 +115,7 @@ new /obj/item/weapon/melee/baton/loaded(src) new /obj/item/weapon/storage/belt/security/sec(src) new /obj/item/taperoll/police(src) - new /obj/item/weapon/gun/energy/hos(src) + new /obj/item/weapon/gun/energy/gun/hos(src) new /obj/item/weapon/door_remote/head_of_security(src) @@ -152,9 +152,10 @@ new /obj/item/weapon/storage/box/flashbangs(src) new /obj/item/weapon/reagent_containers/spray/pepper(src) new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/advtaser(src) + 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 9b5cb514558..dfeb734391d 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -50,6 +50,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/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 4062767a765..8bab5ac467b 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -212,7 +212,7 @@ if(!G.confirm()) return 0 G.affecting.forceMove(get_turf(src)) - G.affecting.Weaken(5) + G.affecting.Weaken(2) G.affecting.visible_message("[G.assailant] pushes [G.affecting] onto [src].", \ "[G.assailant] pushes [G.affecting] onto [src].") add_logs(G.affecting, G.assailant, "pushed onto a table") 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/response_team.dm b/code/game/response_team.dm index 241e317c24b..d9b8cfcc375 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -382,7 +382,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest/ert/security(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/advtaser(M), slot_s_store) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun/advtaser(M), slot_s_store) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/ert/security(M), slot_in_backpack) @@ -459,7 +459,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves) M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/ert/security(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/advtaser(M), slot_s_store) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun/advtaser(M), slot_s_store) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/ert/security(M), slot_in_backpack) @@ -532,7 +532,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/weapon/rcd_ammo/large(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/rcd_ammo/large(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/rcd_ammo/large(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/pistol(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/device/t_scanner/extended_range(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(M), slot_r_store) @@ -553,7 +553,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/flashbangs(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/ionrifle/carbine(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/carbine(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/carbine(M), slot_r_hand) if("Medic") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat/swat(M), slot_shoes) @@ -566,7 +566,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/ert/medical(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/sechailer/swat(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/surgery(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/pistol(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/hypospray/combat/nanites(src), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(M), slot_r_store) @@ -585,7 +585,7 @@ var/send_emergency_team M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/sechailer/swat(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/restraints/handcuffs(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/storage/lockbox/loyalty(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/pistol(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(M), slot_l_store) M.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(M), slot_r_store) @@ -610,4 +610,4 @@ var/send_emergency_team new /obj/item/device/radio/centcom( src ) new /obj/item/weapon/reagent_containers/food/pill/salicylic( src ) new /obj/item/weapon/reagent_containers/food/pill/patch/synthflesh( src ) - return \ No newline at end of file + return diff --git a/code/game/sound.dm b/code/game/sound.dm index cecf12c657d..1890a0966e7 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -9,8 +9,9 @@ var/list/jackboot_sound = list('sound/effects/jackboot1.ogg','sound/effects/jack var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') -//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') +var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') var/list/computer_ambience = list('sound/goonstation/machines/ambicomp1.ogg', 'sound/goonstation/machines/ambicomp2.ogg', 'sound/goonstation/machines/ambicomp3.ogg') +var/list/ricochet = list('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg','sound/weapons/effects/ric3.ogg','sound/weapons/effects/ric4.ogg','sound/weapons/effects/ric5.ogg') /proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/pitch) @@ -107,17 +108,32 @@ var/const/FALLOFF_SOUNDS = 0.5 /proc/get_sfx(soundin) if(istext(soundin)) switch(soundin) - if ("shatter") soundin = pick(shatter_sound) - if ("explosion") soundin = pick(explosion_sound) - if ("sparks") soundin = pick(spark_sound) - if ("rustle") soundin = pick(rustle_sound) - if ("bodyfall") soundin = pick(bodyfall_sound) - if ("punch") soundin = pick(punch_sound) - if ("clownstep") soundin = pick(clown_sound) - if ("jackboot") soundin = pick(jackboot_sound) - if ("swing_hit") soundin = pick(swing_hit_sound) - if ("hiss") soundin = pick(hiss_sound) - if ("pageturn") soundin = pick(page_sound) - //if ("gunshot") soundin = pick(gun_sound) - if("computer_ambience") soundin = pick(computer_ambience) + if ("shatter") + soundin = pick(shatter_sound) + if ("explosion") + soundin = pick(explosion_sound) + if ("sparks") + soundin = pick(spark_sound) + if ("rustle") + soundin = pick(rustle_sound) + if ("bodyfall") + soundin = pick(bodyfall_sound) + if ("punch") + soundin = pick(punch_sound) + if ("clownstep") + soundin = pick(clown_sound) + if ("jackboot") + soundin = pick(jackboot_sound) + if ("swing_hit") + soundin = pick(swing_hit_sound) + if ("hiss") + soundin = pick(hiss_sound) + if ("pageturn") + soundin = pick(page_sound) + if ("gunshot") + soundin = pick(gun_sound) + if("computer_ambience") + soundin = pick(computer_ambience) + if("ricochet") + soundin = pick(ricochet) return soundin 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 47ab4399eac..92eafe2c245 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 b1c4e387907..90413949bc9 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)) @@ -1662,10 +1666,109 @@ message_admins("[key_name_admin(src.owner)] replied to [key_name_admin(H)]'s Centcom message with: \"[input]\"") to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows. [input]. Message ends.\"") + else if(href_list["EvilFax"]) + if(!check_rights(R_ADMIN)) + return + var/mob/living/carbon/human/H = locate(href_list["EvilFax"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + var/etypes = list("borging","corgifying","firedeath","braindeath","honktumor","demotion") + var/eviltype = input(src.owner, "Which type of evil fax do you wish to send [H]?","Its good to be baaaad...", "") as null|anything in etypes + if(!(eviltype in etypes)) + return + var/customname = input(src.owner, "Pick a title for the evil fax.", "Fax Title") as text|null + if(!customname) + customname = "paper" + var/obj/item/weapon/paper/evilfax/P = new /obj/item/weapon/paper/evilfax(null) + var/obj/machinery/photocopier/faxmachine/fax = locate(href_list["originfax"]) + + P.name = "Central Command - [customname]" + P.info = "A reminder: per the terms of your contract, stupid faxes will get you demoted, or worse." + P.myeffect = eviltype + P.mytarget = H + if(alert("Do you want the Evil Fax to activate automatically if [H] tries to ignore it?",,"Yes", "No") == "Yes") + P.activate_on_timeout = 1 + P.x = rand(-2, 0) + P.y = rand(-1, 2) + P.offset_x += P.x + P.offset_y += P.y + P.update_icon() + var/stampvalue = "cent" + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-[stampvalue]" + stampoverlay.pixel_x = P.x + stampoverlay.pixel_y = P.y + P.stamped = list() + P.stamped += /obj/item/weapon/stamp/centcom + if(!P.ico) + P.ico = new + P.ico += "paper_stamp-[stampvalue]" + P.overlays += stampoverlay + P.stamps += "
    " + P.update_icon() + //fax.receivefax(P) // this does not work, it does not preserve the type, we have to physically teleport the fax paper instead + P.loc = fax.loc + if(istype(H) && H.stat == CONSCIOUS && (istype(H.l_ear, /obj/item/device/radio/headset) || istype(H.r_ear, /obj/item/device/radio/headset))) + to_chat(H, "Your headset pings, notifying you that a reply to your fax has arrived.") + to_chat(src.owner, "You sent a [eviltype] fax to [H]") + log_admin("[key_name(src.owner)] sent [key_name(H)] a [eviltype] fax") + message_admins("[key_name_admin(src.owner)] replied to [key_name_admin(H)] with a [eviltype] fax") + else if(href_list["FaxReplyTemplate"]) + if(!check_rights(R_ADMIN)) + return + var/mob/living/carbon/human/H = locate(href_list["FaxReplyTemplate"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(null) + var/obj/machinery/photocopier/faxmachine/fax = locate(href_list["originfax"]) + P.name = "Central Command - paper" + var/stypes = list("handle it yourself","illegible","not signed","sorry, not right now","stop wasting our time") + var/stype = input(src.owner, "Which type of standard reply do you wish to send to [H]?","Choose your paperwork", "") as null|anything in stypes + var/tmsg = "



    NanoTrasen Science Station Cyberiad


    NAS Trurl Communications Department Report


    " + if(stype == "handle it yourself") + tmsg += "Greetings, esteemed crewmember. Your fax has been DECLINED automatically by NAS Trurl Fax Registration.

    Please proceed in accordance with Standard Operating Procedure and/or Space Law. You are fully trained to handle this situation without Central Command intervention." + else if(stype == "illegible") + tmsg += "Greetings, esteemed crewmember. Your fax has been DECLINED automatically by NAS Trurl Fax Registration.

    Your fax was too poorly written for our system to interpret." + else if(stype == "not signed") + tmsg += "Greetings, esteemed crewmember. Your fax has been DECLINED automatically by NAS Trurl Fax Registration.

    Your fax was not properly signed and/or stamped." + else if(stype == "sorry, not right now") + tmsg += "Greetings, esteemed crewmember. Unfortunately, we are unable to spare the resources to assist you at this time." + else if(stype == "stop wasting our time") + tmsg += "Stop wasting our time." + else + return + tmsg += "
    " + P.info = tmsg + P.x = rand(-2, 0) + P.y = rand(-1, 2) + P.offset_x += P.x + P.offset_y += P.y + P.update_icon() + var/stampvalue = "cent" + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-[stampvalue]" + stampoverlay.pixel_x = P.x + stampoverlay.pixel_y = P.y + P.stamped = list() + P.stamped += /obj/item/weapon/stamp/centcom + if(!P.ico) + P.ico = new + P.ico += "paper_stamp-[stampvalue]" + P.overlays += stampoverlay + P.stamps += "
    " + P.update_icon() + fax.receivefax(P) + if(istype(H) && H.stat == CONSCIOUS && (istype(H.l_ear, /obj/item/device/radio/headset) || istype(H.r_ear, /obj/item/device/radio/headset))) + to_chat(H, "Your headset pings, notifying you that a reply to your fax has arrived.") + to_chat(src.owner, "You sent a standard '[stype]' fax to [H]") + log_admin("[key_name(src.owner)] sent [key_name(H)] a standard '[stype]' fax") + message_admins("[key_name_admin(src.owner)] replied to [key_name_admin(H)] with a standard '[stype]' fax") + else if(href_list["SyndicateReply"]) if(!check_rights(R_ADMIN)) return - var/mob/living/carbon/human/H = locate(href_list["SyndicateReply"]) if(!istype(H)) to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") @@ -1676,10 +1779,9 @@ if(!istype(H.l_ear, /obj/item/device/radio/headset) && !istype(H.r_ear, /obj/item/device/radio/headset)) to_chat(usr, "The person you are trying to contact is not wearing a headset") return - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from The Syndicate", "") - if(!input) return - + if(!input) + return to_chat(src.owner, "You sent [input] to [H] via a secure channel.") log_admin("[src.owner] replied to [key_name(H)]'s Syndicate message with the message [input].") to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from your benefactor. Message as follows, agent. [input]. Message ends.\"") @@ -2255,6 +2357,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) @@ -2474,7 +2577,7 @@ for(var/obj/item/W in world) if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/weapon/disk) || istype(W, /obj/item/weapon/tank)) continue - W.icon = 'icons/obj/gun.dmi' + W.icon = 'icons/obj/guns/projectile.dmi' W.icon_state = "revolver" W.item_state = "gun" message_admins("[key_name_admin(usr)] made every item look like a gun") @@ -2921,6 +3024,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 6b3c78cf954..b85d19451fe 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -690,7 +690,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(M), slot_wear_suit) M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/thunderdome(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/destroyer(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/destroyer(M), slot_r_hand) M.equip_to_slot_or_del(new /obj/item/weapon/kitchen/knife(M), slot_l_hand) M.equip_to_slot_or_del(new /obj/item/weapon/grenade/smokebomb(M), slot_r_store) @@ -881,7 +881,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(pda, slot_r_store) M.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) - M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse_rifle/pistol(M), slot_belt) + M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_belt) var/obj/item/weapon/card/id/centcom/W = new(M) W.name = "[M.real_name]'s ID Card (Nanotrasen Navy Officer)" @@ -904,7 +904,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_or_collect(pda, slot_r_store) M.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) - M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse_rifle/pistol(M), slot_belt) + M.equip_or_collect(new /obj/item/weapon/gun/energy/pulse/pistol(M), slot_belt) var/obj/item/weapon/card/id/centcom/W = new(M) W.name = "[M.real_name]'s ID Card (Nanotrasen Navy Captain)" @@ -967,7 +967,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/cyber(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/cohiba(M), slot_wear_mask) M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad/beret(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/pistol/m1911(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol/m1911(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/matches(M), slot_r_store) M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/dualsaber/red(M), slot_l_store) @@ -996,7 +996,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad/beret(M), slot_head) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/cyber(M), slot_glasses) M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/cohiba(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/pistol/m1911(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse/pistol/m1911(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/matches(M), slot_r_store) M.equip_or_collect(new /obj/item/weapon/melee/classic_baton/telescopic(M), slot_l_store) @@ -1233,4 +1233,14 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that assets.register() // Clear the user's cache so they get resent. - usr.client.cache = list() \ No newline at end of file + 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/honksquad.dm b/code/modules/admin/verbs/honksquad.dm index 75fc6af84d9..dd37a828302 100644 --- a/code/modules/admin/verbs/honksquad.dm +++ b/code/modules/admin/verbs/honksquad.dm @@ -121,7 +121,7 @@ var/global/sent_honksquad = 0 if(prob(50)) equip_to_slot_or_del(new /obj/item/weapon/gun/energy/clown(src), slot_in_backpack) else - equip_to_slot_or_del(new /obj/item/weapon/gun/grenadelauncher/piecannon(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/gun/throw/piecannon(src), slot_in_backpack) src.mutations.Add(CLUMSY) @@ -134,4 +134,4 @@ var/global/sent_honksquad = 0 W.registered_name = real_name equip_to_slot_or_del(W, slot_wear_id) - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index e28174b40d0..c4c09197d4e 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -484,6 +484,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!") @@ -496,9 +498,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 = "" @@ -507,17 +506,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) @@ -528,8 +531,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/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 0ef6a64373f..170d96754ea 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -18,7 +18,6 @@ for(var/client/X in admins) if(check_rights(R_EVENT,0,X.mob)) to_chat(X, msg) - to_chat(usr, "Your prayers have been received by the gods.") feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -27,41 +26,46 @@ /proc/Centcomm_announce(var/text , var/mob/Sender) var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN)) msg = "\blue CENTCOMM: [key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (RPLY): [msg]" - for(var/client/X in admins) if(R_EVENT & X.holder.rights) to_chat(X, msg) + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' /proc/Syndicate_announce(var/text , var/mob/Sender) var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN)) msg = "\blue SYNDICATE: [key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (REPLY): [msg]" - for(var/client/X in admins) if(check_rights(R_EVENT,0,X.mob)) to_chat(X, msg) + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' /proc/HONK_announce(var/text , var/mob/Sender) var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN)) msg = "\blue HONK: [key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (RPLY): [msg]" - for(var/client/X in admins) if(R_EVENT & X.holder.rights) to_chat(X, msg) + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' /proc/ERT_Announce(var/text , var/mob/Sender) var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN)) msg = "\blue ERT REQUEST: [key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (REPLY): [msg]" - for(var/client/X in admins) if(check_rights(R_EVENT,0,X.mob)) to_chat(X, msg) + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' /proc/Nuke_request(text , mob/Sender) var/nuke_code = get_nuke_code() var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN)) msg = "NUKE CODE REQUEST: [key_name(Sender)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (RPLY): [msg]" - for(var/client/X in admins) if(check_rights(R_EVENT,0,X.mob)) to_chat(X, msg) to_chat(X, "The nuke code is [nuke_code].") + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' \ No newline at end of file diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index a5b98bc888c..142bb8203cd 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -154,7 +154,7 @@ var/global/sent_strike_team = 0 equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double/full(src), slot_s_store) equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(src), slot_belt) - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) + equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse(src), slot_r_hand) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)//Here you go Deuryn @@ -170,4 +170,4 @@ var/global/sent_strike_team = 0 W.registered_name = real_name equip_to_slot_or_del(W, slot_wear_id) - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index 6131962b881..054b5469d9b 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -144,7 +144,7 @@ var/global/sent_syndicate_strike_team = 0 equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m762, slot_in_backpack) + equip_to_slot_or_del(new /obj/item/ammo_box/magazine/mm556x45) equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m45(src), slot_in_backpack) equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack) @@ -160,7 +160,7 @@ var/global/sent_syndicate_strike_team = 0 equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/saber(src), slot_l_store) equip_to_slot_or_del(new /obj/item/weapon/grenade/empgrenade(src), slot_r_store) equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double/full(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/pistol/m2411(src), slot_belt) + equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/pistol/m1911(src), slot_belt) equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/l6_saw(src), slot_r_hand) @@ -173,4 +173,4 @@ var/global/sent_syndicate_strike_team = 0 W.registered_name = real_name equip_to_slot_or_del(W, slot_wear_id) - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm index c5e370f06f7..b2cc9336bf5 100644 --- a/code/modules/admin/verbs/vox_raiders.dm +++ b/code/modules/admin/verbs/vox_raiders.dm @@ -18,7 +18,7 @@ var/global/vox_tick = 1 equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store) - var/obj/item/weapon/gun/launcher/spikethrower/W = new(src) + var/obj/item/weapon/gun/projectile/automatic/spikethrower/W = new(src) equip_to_slot_or_del(W, slot_r_hand) @@ -77,4 +77,4 @@ var/global/vox_tick = 1 vox_tick++ if (vox_tick > 4) vox_tick = 1 - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 3bf0775473c..3171755b34c 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -10,6 +10,7 @@ var/status = 0 //0 - not readied //1 - bomb finished with welder var/obj/item/device/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device var/obj/item/weapon/tank/bombtank = null //the second part of the bomb is a plasma tank + origin_tech = "materials=1;engineering=1" /obj/item/device/onetankbomb/examine(mob/user) ..(user) diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index 7e4fcc03453..5f644146c5e 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -61,10 +61,8 @@ */ //Captain's retro laser - Fires practice laser shots instead. obj/item/weapon/gun/energy/laser/retro/sc_retro - name ="retro laser" - icon_state = "retro" desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces." -// projectile_type = "/obj/item/projectile/practice" + ammo_type = list(/obj/item/ammo_casing/energy/laser/practice) clumsy_check = 0 //No sense in having a harmless gun blow up in the clowns face //Syndicate sub-machine guns. @@ -196,4 +194,4 @@ var/sc_safecode5 = "[rand(0,9)]" return /obj/singularity/narsie/sc_Narsie/ex_act() - return \ No newline at end of file + return diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 768de2a270b..756e5c6b156 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -316,9 +316,9 @@ send_resources() if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP - winset(src, "rpane.changelog", "background-color=#f4aa94;font-style=bold") - prefs.SetChangelog(src,changelog_hash) - to_chat(src, "Changelog has changed since your last visit.") + if(establish_db_connection()) + winset(src, "rpane.changelog", "background-color=#f4aa94;font-style=bold") + to_chat(src, "Changelog has changed since your last visit.") if(!void) void = new() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 6696e6e8ecd..eafc7b59bd6 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -258,8 +258,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
    " @@ -410,7 +410,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else dat += "Be [capitalize(i)]: [(i in src.be_special) ? "Yes" : "No"]
    " dat += "" - + dat += "
    " if(!IsGuestKey(user.key)) dat += "Undo - " @@ -984,16 +984,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") @@ -1010,10 +1011,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")) - s_tone = random_skin_tone() + if(species in list("Human", "Drask", "Vox")) + s_tone = random_skin_tone(species) 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) @@ -1037,7 +1038,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("age") var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null if(new_age) - age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) + age = max(min(round(text2num(new_age)), AGE_MAX),AGE_MIN) if("species") var/list/new_species = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin") @@ -1115,6 +1116,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 @@ -1159,7 +1165,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) @@ -1278,11 +1284,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() @@ -1367,11 +1374,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)) @@ -1381,7 +1391,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts g_skin = hex2num(copytext(new_skin, 4, 6)) b_skin = hex2num(copytext(new_skin, 6, 8)) - if("ooccolor") var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference", ooccolor) as color|null if(new_ooccolor) diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm index 07db4bf7128..15abdab0360 100644 --- a/code/modules/client/preferences_mysql.dm +++ b/code/modules/client/preferences_mysql.dm @@ -456,10 +456,12 @@ /datum/preferences/proc/SetChangelog(client/C,hash) lastchangelog=hash + winset(C, "rpane.changelog", "background-color=none;font-style=") var/DBQuery/query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") message_admins("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") + to_chat(C, "Couldn't update your last seen changelog, please try again later.") return return 1 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/gloves/color.dm b/code/modules/clothing/gloves/color.dm index db163ad3e59..a50e56382a1 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -6,8 +6,32 @@ siemens_coefficient = 0 permeability_coefficient = 0.05 item_color="yellow" - power - var/next_shock = 0 + +/obj/item/clothing/gloves/color/yellow/power + description_antag = "These are a pair of power gloves, and can be used to fire bolts of electricity while standing over powered power cables." + var/old_mclick_override + var/datum/middleClickOverride/power_gloves/mclick_override = new /datum/middleClickOverride/power_gloves + +/obj/item/clothing/gloves/color/yellow/power/equipped(mob/user, slot) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(slot == slot_gloves) + if(H.middleClickOverride) + old_mclick_override = H.middleClickOverride + H.middleClickOverride = mclick_override + to_chat(H, "You feel electricity begin to build up in [src].") + +/obj/item/clothing/gloves/color/yellow/power/dropped(mob/user, slot) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_gloves) == src && H.middleClickOverride == mclick_override) + if(old_mclick_override) + H.middleClickOverride = old_mclick_override + old_mclick_override = null + else + H.middleClickOverride = null /obj/item/clothing/gloves/color/yellow/fake desc = "These gloves will protect the wearer from electric shock. They don't feel like rubber..." @@ -167,4 +191,4 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT - strip_delay = 60 \ No newline at end of file + strip_delay = 60 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/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 364c4d808ac..1b7ea8fc4c9 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -95,13 +95,12 @@ src.icon_state = "orange" return -/obj/item/clothing/shoes/orange/attackby(H as obj, loc, params) +/obj/item/clothing/shoes/orange/attackby(obj/H, loc, params) ..() - if ((istype(H, /obj/item/weapon/restraints/handcuffs) && !( src.chained ))) - //H = null + if (istype(H, /obj/item/weapon/restraints/handcuffs) && !chained && !(H.flags & NODROP)) if (src.icon_state != "orange") return qdel(H) src.chained = 1 src.slowdown = 15 src.icon_state = "orange1" - return \ No newline at end of file + return diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index 4015f107e51..91824a9856e 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -34,8 +34,8 @@ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 100, rad = 60) allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank, /obj/item/device/t_scanner, /obj/item/weapon/rcd, /obj/item/weapon/crowbar, \ /obj/item/weapon/screwdriver, /obj/item/weapon/weldingtool, /obj/item/weapon/wirecutters, /obj/item/weapon/wrench, /obj/item/device/multitool, \ - /obj/item/device/radio, /obj/item/device/analyzer, /obj/item/weapon/gun/energy/laser, /obj/item/weapon/gun/energy/pulse_rifle, \ - /obj/item/weapon/gun/energy/advtaser, /obj/item/weapon/melee/baton, /obj/item/weapon/gun/energy/gun) + /obj/item/device/radio, /obj/item/device/analyzer, /obj/item/weapon/gun/energy/laser, /obj/item/weapon/gun/energy/pulse, \ + /obj/item/weapon/gun/energy/gun/advtaser, /obj/item/weapon/melee/baton, /obj/item/weapon/gun/energy/gun) strip_delay = 130 //Commander @@ -121,4 +121,4 @@ /obj/item/clothing/suit/space/rig/ert/paranormal/New() ..() - new /obj/item/weapon/nullrod(src) \ No newline at end of file + new /obj/item/weapon/nullrod(src) diff --git a/code/modules/clothing/spacesuits/rig/modules/combat.dm b/code/modules/clothing/spacesuits/rig/modules/combat.dm index 2473fd24eb8..16ddf2bdd69 100644 --- a/code/modules/clothing/spacesuits/rig/modules/combat.dm +++ b/code/modules/clothing/spacesuits/rig/modules/combat.dm @@ -119,7 +119,7 @@ gun.attack_self(holder.wearer) return 1 - gun.Fire(target,holder.wearer) + gun.process_fire(target,holder.wearer) return 1 /obj/item/rig_module/mounted/egun @@ -168,7 +168,7 @@ active_power_cost = 10 passive_power_cost = 0 - gun_type = /obj/item/weapon/gun/energy/crossbow/ninja + gun_type = /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/ninja /obj/item/rig_module/mounted/energy_blade/process() diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 7934d49a620..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." @@ -135,13 +195,13 @@ icon_state = "armor_reflec" item_state = "armor_reflec" blood_overlay_type = "armor" - var/hit_reflect_chance = 40 armor = list(melee = 10, bullet = 10, laser = 80, energy = 50, bomb = 0, bio = 0, rad = 0) + var/hit_reflect_chance = 40 /obj/item/clothing/suit/armor/laserproof/IsReflect(var/def_zone) if(!(def_zone in list("chest", "groin"))) //If not shot where ablative is covering you, you don't get the reflection bonus! - hit_reflect_chance = 0 - if (prob(hit_reflect_chance)) + return 0 + if(prob(hit_reflect_chance)) return 1 /obj/item/clothing/suit/armor/vest/det_suit @@ -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/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 5dc5cf02699..8b1d33d6ddb 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -10,6 +10,7 @@ var/slot = "decor" var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to var/image/inv_overlay = null //overlay used when attached to clothing. + action_button_custom_type = /datum/action/item_action/accessory /obj/item/clothing/accessory/New() ..() diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 0e2392ceff1..9533d7c4aae 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -256,7 +256,7 @@ /obj/item/clothing/under/suit_jacket/charcoal name = "charcoal suit" - desc = "A charcoal suit and red tie. Very professional." + desc = "A charcoal suit and blue tie. Very professional." icon_state = "charcoal_suit" item_state = "charcoal_suit" item_color = "charcoal_suit" diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index c578c452bbc..d8586b6c0d8 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -44,7 +44,7 @@ /obj/item/robot_parts/r_leg = 1, /obj/item/stack/sheet/metal = 5, /obj/item/stack/cable_coil = 5, - /obj/item/weapon/gun/energy/advtaser = 1, + /obj/item/weapon/gun/energy/gun/advtaser = 1, /obj/item/weapon/stock_parts/cell = 1, /obj/item/device/assembly/prox_sensor = 1, /obj/item/robot_parts/r_arm = 1) @@ -200,4 +200,29 @@ time = 15 reqs = list(/obj/item/stack/sheet/wood = 1, /obj/item/stack/cable_coil = 5) - tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles \ No newline at end of file + tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles + +/datum/table_recipe/makeshift_bolt + name = "Makeshift Bolt" + result = /obj/item/weapon/arrow/rod + time = 15 + reqs = list(/obj/item/stack/rods = 1) + tools = list(/obj/item/weapon/weldingtool) + +/datum/table_recipe/crossbow + name = "Powered Crossbow" + result = /obj/item/weapon/gun/throw/crossbow + time = 300 + reqs = list(/obj/item/stack/rods = 3, + /obj/item/stack/cable_coil = 10, + /obj/item/stack/sheet/mineral/plastic = 3, + /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/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 3cd6566e731..ab8670b3b05 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -67,8 +67,23 @@ target.update_markings() playsound(src.loc, 'sound/items/Welder2.ogg', 20, 1) - icon_state = "tatgun_used" used = 1 + update_icon() + +/obj/item/device/fluff/tattoo_gun/update_icon() + ..() + + overlays.Cut() + + if(!used) + var/image/ink = image(src.icon, src, "ink_overlay") + ink.icon += rgb(tattoo_r, tattoo_g, tattoo_b, 190) + overlays += ink + +/obj/item/device/fluff/tattoo_gun/New() + ..() + update_icon() + /obj/item/weapon/claymore/fluff // MrBarrelrolll: Maximus Greenwood name = "Greenwood's Blade" @@ -293,6 +308,16 @@ src.item_state = "[item_color]" usr.update_inv_w_uniform() +/obj/item/clothing/under/fluff/honourable // MrBarrelrolll: Maximus Greenwood + name = "Viridi Protegat" + desc = "A set of chainmail adorned with a hide mantle. \"Greenwood\" is engraved into the right breast." + icon = 'icons/obj/clothing/uniforms.dmi' + icon_state = "roman" + item_state = "maximus_armor" + item_color = "maximus_armor" + displays_id = 0 + strip_delay = 100 + //////////// Masks //////////// //////////// Shoes //////////// @@ -422,24 +447,34 @@ icon_state = "chaps" item_color = "combat_pants" -/obj/item/clothing/suit/jacket/fluff/windbreaker // DaveTheHeadcrab: Elliot Campbell +/obj/item/clothing/suit/jacket/fluff/elliot_windbreaker // DaveTheHeadcrab: Elliot Campbell name = "nylon windbreaker" desc = "A cheap nylon windbreaker, according to the tag it was manufactured in New Chiba, Earth.
    The color reminds you of a television tuned to a dead channel." icon = 'icons/obj/custom_items.dmi' - icon_state = "elliot_windbreaker" - item_state = "elliot_windbreaker" + icon_state = "elliot_windbreaker_open" + item_state = "elliot_windbreaker_open" adjust_flavour = "unzip" + suit_adjusted = 1 -/obj/item/clothing/ears/earring/fluff/industrial_piercing - name = "industrial piercing and stud earring" - desc = "A set of ear piercings containing an industrial rod and a small stud. They appear to be made out of some form of non-magnetic metal." - icon = 'icons/obj/custom_items.dmi' - icon_state = "elliot_earring" - -/obj/item/device/fluff/tattoo_gun/cybernetic_tat - desc = "A cheap plastic tattoo application pen.
    This one seems to have light blue ink." +/obj/item/device/fluff/tattoo_gun/elliot_cybernetic_tat + desc = "A cheap plastic tattoo application pen.
    This one seems heavily used." tattoo_name = "circuitry tattoo" tattoo_icon = "Elliot Circuit Tattoo" - tattoo_r = 100 - tattoo_g = 150 - tattoo_b = 255 \ No newline at end of file + tattoo_r = 48 + tattoo_g = 138 + tattoo_b = 176 + +/obj/item/device/fluff/tattoo_gun/elliot_cybernetic_tat/attack_self(mob/user as mob) + if(!used) + var/ink_color = input("Please select an ink color.", "Tattoo Ink Color", rgb(tattoo_r, tattoo_g, tattoo_b)) as color|null + if(ink_color && !(user.incapacitated() || used) ) + tattoo_r = hex2num(copytext(ink_color, 2, 4)) + tattoo_g = hex2num(copytext(ink_color, 4, 6)) + tattoo_b = hex2num(copytext(ink_color, 6, 8)) + + to_chat(user, "You change the color setting on the [src].") + + update_icon() + + else + to_chat(user, "The [src] is out of ink!") \ No newline at end of file diff --git a/code/modules/detective_work/scanner.dm b/code/modules/detective_work/scanner.dm index 59466282384..e959df37989 100644 --- a/code/modules/detective_work/scanner.dm +++ b/code/modules/detective_work/scanner.dm @@ -5,7 +5,8 @@ /obj/item/device/detective_scanner name = "forensic scanner" desc = "Used to remotely scan objects and biomass for DNA and fingerprints. Can print a report of the findings." - icon_state = "forensic1" + icon = 'icons/goonstation/objects/objects.dmi' + icon_state = "detscanner" w_class = 3.0 item_state = "electronic" flags = CONDUCT | NOBLUDGEON @@ -15,9 +16,56 @@ var/list/log = list() /obj/item/device/detective_scanner/attack_self(var/mob/user) + var/search = input(user, "Enter name, fingerprint or blood DNA.", "Find record", "") + + if (!search || user.stat || user.incapacitated()) + return + + search = lowertext(search) + + var/name + var/fingerprint + var/dna + + // I really, really wish I didn't have to split this into two seperate loops. But the datacore is awful. + + for (var/record in data_core.general) + var/datum/data/record/S = record + if(search == lowertext(S.fields["fingerprint"]) || search == lowertext(S.fields["name"])) + name = S.fields["name"] + fingerprint = S.fields["fingerprint"] + continue + + for (var/record in data_core.medical) + var/datum/data/record/M = record + if (search == lowertext(M.fields["b_dna"]) || name == M.fields["name"]) + dna = M.fields["b_dna"] + + if(!fingerprint) // We have searched by DNA, and do not have the relevant information from the security records. + name = M.fields["name"] + for (var/gen_record in data_core.general) + var/datum/data/record/S = gen_record + if(name == S.fields["name"]) + fingerprint = S.fields["fingerprint"] + continue + continue + + if(name && fingerprint && dna) + to_chat(user, "Match found in station records: [name]
    \ + Fingerprint: [fingerprint]
    \ + Blood DNA: [dna]") + return + + to_chat(user, "No match found in station records.") + + +/obj/item/device/detective_scanner/verb/print_scanner_report() + set name = "Print Scanner Report" + set category = "Object" + if(log.len && !scanning) scanning = 1 - to_chat(user, "Printing report, please wait...") + to_chat(usr, "Printing report, please wait...") playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1) spawn(100) @@ -38,7 +86,8 @@ log = list() scanning = 0 else - to_chat(user, "The scanner has no logs or is in use.") + to_chat(usr, "The scanner has no logs or is in use.") + /obj/item/device/detective_scanner/attack(mob/living/M as mob, mob/user as mob) return 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/event_container.dm b/code/modules/events/event_container.dm index 304abd3cd13..5955d60cbec 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -184,6 +184,7 @@ var/list/event_last_fired = list() new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 80, is_one_shot = 1), new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 0, is_one_shot = 1), ) 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/events/traders.dm b/code/modules/events/traders.dm new file mode 100644 index 00000000000..e4c7d95fb89 --- /dev/null +++ b/code/modules/events/traders.dm @@ -0,0 +1,87 @@ +var/global/list/unused_trade_stations = list("sol") + +// Traders event. +// Heavily copy-pasted from "heist" gamemode. + +/datum/event/traders + var/success_spawn = 0 + var/station = null + var/spawn_count = 3 + var/list/trader_objectives = list() + +/datum/event/traders/setup() + if(unused_trade_stations.len) + station = pick_n_take(unused_trade_stations) + +/datum/event/traders/start() + if(!station) // If there are no unused stations, just no. + return + var/list/spawnlocs = list() + for(var/obj/effect/landmark/landmark in landmarks_list) + if(landmark.name == "traderstart_[station]") + spawnlocs += get_turf(landmark) + if(!spawnlocs.len) + return + + trader_objectives = forge_trader_objectives() + + spawn() + var/list/candidates = pollCandidates("Do you want to play as a trader?", ROLE_TRADER, 1) + var/index = 1 + while(spawn_count > 0 && candidates.len > 0) + if(index > spawnlocs.len) + index = 1 + + var/turf/picked_loc = spawnlocs[index] + index++ + var/mob/C = pick_n_take(candidates) + if(C) + respawnable_list -= C.client + var/mob/living/carbon/human/M = create_trader(picked_loc) + M.ckey = C.ckey + M.mind.objectives += trader_objectives + greet_trader(M) + success_spawn = 1 + if(!success_spawn) + unused_trade_stations += station // Return the station to the list of usable stations. + +/datum/event/traders/proc/create_trader(var/turf/picked_loc) + var/mob/living/carbon/human/M + switch(station) + if("sol") + M = new /mob/living/carbon/human(picked_loc) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(M), slot_back) + var/obj/item/weapon/card/id/supply/W = new(M) + W.name = "[M.real_name]'s ID Card (Sol Trader)" + W.assignment = "Sol Trader" + W.registered_name = M.real_name + W.access = list(access_trade_sol, access_maint_tunnels, access_external_airlocks) + M.equip_to_slot_or_del(W, slot_wear_id) + return M + +/datum/event/traders/proc/greet_trader(var/mob/living/carbon/human/M) + to_chat(M, "You are a trader!") + to_chat(M, "You are currently docked at [get_area(M)].") + to_chat(M, "You are about to trade with NSS Cyberiad.") + to_chat(M, "Negotiate an agreement, and request docking.") + spawn(25) + show_objectives(M.mind) + +/datum/event/traders/proc/forge_trader_objectives() + var/i = 1 + var/max_objectives = pick(2, 2, 2, 2, 3, 3, 3, 4) + var/list/objs = list() + var/list/goals = list("stockparts") + while(i<= max_objectives) + var/goal = pick(goals) + var/datum/objective/trade/O + if(goal == "stockparts") + O = new /datum/objective/trade/stock(station) + O.choose_target() + objs += O + + i++ + return objs diff --git a/code/modules/examine/descriptions/weapons.dm b/code/modules/examine/descriptions/weapons.dm index 90929d31e08..264e0e99dfe 100644 --- a/code/modules/examine/descriptions/weapons.dm +++ b/code/modules/examine/descriptions/weapons.dm @@ -26,7 +26,7 @@ then click where you want to fire. Most energy weapons can fire through windows harmlessly. To switch between stun and lethal, click the weapon \ in your hand. To recharge this weapon, use a weapon recharger." -/obj/item/weapon/gun/energy/advtaser +/obj/item/weapon/gun/energy/gun/advtaser description_info = "This is an energy weapon. To fire the weapon, have your gun mode set to 'fire', \ then click where you want to fire. To recharge this weapon, use a weapon recharger. \ To switch between insta-stun and disabler beams, click the weapon in your hand. This weapon can only fire through glass if it is set to disabler beams." @@ -55,11 +55,6 @@ then click where you want to fire. After firing, you will need to pump the gun, by clicking on the gun in your hand. To reload, load more shotgun \ shells into the gun." -/obj/item/weapon/gun/projectile/heavysniper - description_info = "This is a ballistic weapon. To fire the weapon, have your gun mode set to 'fire', \ - then click where you want to fire. The gun's chamber can be opened or closed by using it in your hand. To reload, open the chamber, add a new bullet \ - then close it. To use the scope, use the appropriate verb in the object tab." - //******* //*Melee* //******* diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index c4088d9a53f..6229105a8b3 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -693,9 +693,10 @@ 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/gun.dmi' + halitem.icon = 'icons/obj/guns/projectile.dmi' halitem.icon_state = "revolver" halitem.name = "Revolver" if(2) //c4 @@ -780,4 +781,4 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite if(client) client.images += halbody spawn(rand(50,80)) //Only seen for a brief moment. if(client) client.images -= halbody - halbody = null \ No newline at end of file + halbody = null diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index 9102af9e0ab..3e9580ef14b 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -179,6 +179,7 @@ if(locked) if(istype(W, /obj/item/weapon/card/emag)) boom(user) + return 1 if(istype(W, /obj/item/device/multitool)) to_chat(user, "DECA-CODE LOCK REPORT:") if(attempts == 1) @@ -186,30 +187,24 @@ else to_chat(user, "* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts.") if(lastattempt != null) - var/guess = lastattempt var/bulls = 0 var/cows = 0 var/list/banned = list() - for(var/i; i <= length(lastattempt); i++) - var/list/a = strip_first(guess) - if(a[1] in banned) + for(var/i in 1 to codelen) + var/list/a = copytext(lastattempt, i, i + 1) + if(a in banned) continue - if(findtext(a[2], a[1])) - if(findtext(code, a[1], i, i+1)) + var/g = findtext(code, a) + if(g) + banned += a + if(g == i) ++bulls - banned += a[1] - else - var/g = findtext(code, a[1]) - if(g) - if(g == i) - ++bulls - else - ++cows - guess = a[2] + else + ++cows to_chat(user, "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.") - else ..() - else ..() + return 1 + return ..() /obj/structure/closet/crate/secure/loot/togglelock(mob/user) if(locked) 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/mining/security_recipes.dm b/code/modules/mining/security_recipes.dm index f08addbf4a0..9cbdeadc154 100644 --- a/code/modules/mining/security_recipes.dm +++ b/code/modules/mining/security_recipes.dm @@ -99,7 +99,7 @@ /datum/manufacture/taser name = "Advanced Taser" - item = /obj/item/weapon/gun/energy/advtaser + item = /obj/item/weapon/gun/energy/gun/advtaser cost1 = /obj/item/weapon/ore/iron cname1 = "Iron" amount1 = 15 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/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index afae056b99f..9311ab0592f 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -123,8 +123,8 @@ Doesn't work on other aliens/AI.*/ A.firer = src A.yo = U.y - T.y A.xo = U.x - T.x - spawn(1) - A.process() + A.fire() + A.newtonian_move(get_dir(U, T)) return /mob/living/carbon/alien/humanoid/proc/resin() // -- TLE @@ -185,4 +185,4 @@ Doesn't work on other aliens/AI.*/ adjustPlasma(-amount) return 1 - return 0 \ No newline at end of file + return 0 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/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 857546732d7..63eb38e607f 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -32,22 +32,6 @@ adjustToxLoss(3) updatehealth() -/mob/living/carbon/brain/handle_environment(datum/gas_mixture/environment) - if(!environment) - return - var/environment_heat_capacity = environment.heat_capacity() - if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - environment_heat_capacity = heat_turf.heat_capacity - - if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10))) - var/transfer_coefficient = 1 - - handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) - - if(stat == DEAD) - bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) - /mob/living/carbon/brain/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) if(status_flags & GODMODE) return @@ -94,3 +78,6 @@ see_in_dark = 2 see_invisible = SEE_INVISIBLE_LIVING handle_hud_icons_health() + +/mob/living/carbon/brain/breathe() + return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 5a641a81689..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 @@ -517,57 +518,39 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/throw_item(atom/target) throw_mode_off() - if(stat || !target) + if(!target || !isturf(loc)) return - if(target.type == /obj/screen) + if(istype(target, /obj/screen)) return - var/atom/movable/item = get_active_hand() + var/atom/movable/thrown_thing + var/obj/item/I = src.get_active_hand() - if(!item || (item.flags & NODROP)) + if(!I || (I.flags & NODROP)) return - if (istype(item, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = item - item = G.get_mob_if_throwable() //throw the person instead of the grab - if(ismob(item)) + if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + var/mob/throwable_mob = G.get_mob_if_throwable() //throw the person instead of the grab + qdel(G) //We delete the grab. + if(throwable_mob) + thrown_thing = throwable_mob var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors var/turf/end_T = get_turf(target) if(start_T && end_T) - var/mob/M = item var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" - M.attack_log += text("\[[time_stamp()]\] Has been thrown by [key_name(src)] from [start_T_descriptor] with the target [end_T_descriptor]") - attack_log += text("\[[time_stamp()]\] Has thrown [key_name(M)] from [start_T_descriptor] with the target [end_T_descriptor]") - msg_admin_attack("[key_name_admin(src)] has thrown [key_name_admin(M)] from [start_T_descriptor] with the target [end_T_descriptor]") + add_logs(throwable_mob, src, "thrown", addition="from [start_T_descriptor] with the target [end_T_descriptor]") - if(!iscarbon(src)) - M.LAssailant = null - else - M.LAssailant = src - - if(!item) - return //Grab processing has a chance of returning null - if(!ismob(item)) //Honk mobs don't have a dropped() proc honk - unEquip(item) - update_icons() - - if (istype(src, /mob/living/carbon)) //Check if a carbon mob is throwing. Modify/remove this line as required. - item.loc = loc - if(client) - client.screen -= item - if(istype(item, /obj/item)) - item:dropped(src) // let it know it's been dropped - - //actually throw it! - if (item) - item.layer = initial(item.layer) - visible_message("\red [src] has thrown [item].") + else if(!(I.flags & ABSTRACT)) //can't throw abstract items + thrown_thing = I + unEquip(I) + if(thrown_thing) + visible_message("[src] has thrown [thrown_thing].") newtonian_move(get_dir(target, src)) - - item.throw_at(target, item.throw_range, item.throw_speed, src) + thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src) /* /mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) ..() @@ -863,6 +846,12 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, //called when we get cuffed/uncuffed /mob/living/carbon/proc/update_handcuffed() if(handcuffed) + //we don't want problems with nodrop shit if there ever is more than one nodrop twohanded + var/obj/item/I = get_active_hand() + if(istype(I, /obj/item/weapon/twohanded)) + var/obj/item/weapon/twohanded/TH = I //FML + if(TH.wielded) + TH.unwield() drop_r_hand() drop_l_hand() stop_pulling() @@ -914,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 @@ -925,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) @@ -992,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 b1d7e356b39..00000000000 --- a/code/modules/mob/living/carbon/human/emote.dm +++ /dev/null @@ -1,884 +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") - if (species.name == "Machine") //Only Machines can beep, ping, and buzz - 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("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 7775830b4a0..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 @@ -1982,4 +2011,21 @@ . |= A.GetAccess() /mob/living/carbon/human/is_mechanical() - return ..() || (species.flags & ALL_RPARTS) != 0 \ No newline at end of file + return ..() || (species.flags & ALL_RPARTS) != 0 + +/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/gun/G) + . = ..() + + if(G.trigger_guard == TRIGGER_GUARD_NORMAL) + if(HULK in mutations) + to_chat(src, "Your meaty finger is much too large for the trigger guard!") + return 0 + if(species.flags & NOGUNS) + to_chat(src, "Your fingers don't fit in the trigger guard!") + return 0 + + if(martial_art && martial_art.name == "The Sleeping Carp") //great dishonor to famiry + to_chat(src, "Use of ranged weaponry would bring dishonor to the clan.") + return 0 + + return . diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 835f741be3d..3a935e5e449 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -27,7 +27,7 @@ emp_act P.current = curloc P.yo = new_y - curloc.y P.xo = new_x - curloc.x - P.Angle = ""//round(Get_Angle(P,P.original)) + P.Angle = null return -1 // complete projectile permutation @@ -46,7 +46,10 @@ emp_act if((P.embed && prob(20 + max(P.damage - armor, -10)))) var/obj/item/weapon/shard/shrapnel/SP = new() (SP.name) = "[P.name] shrapnel" - (SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]." + if(P.ammo_casing && P.ammo_casing.caliber) + (SP.desc) = "[SP.desc] It looks like it is a [P.ammo_casing.caliber] caliber round." + else + (SP.desc) = "[SP.desc] The round's caliber is unidentifiable." (SP.loc) = organ organ.embed(SP) diff --git a/code/modules/mob/living/carbon/human/interactive/functions.dm b/code/modules/mob/living/carbon/human/interactive/functions.dm index 0a220accc98..b0806e66241 100644 --- a/code/modules/mob/living/carbon/human/interactive/functions.dm +++ b/code/modules/mob/living/carbon/human/interactive/functions.dm @@ -693,7 +693,7 @@ best = R if(istype(R, /obj/item/weapon/gun)) var/obj/item/weapon/gun/G = R - if(G.can_fire()) + if(G.can_shoot()) best = R break // gun with ammo? screw the rest if(best && best != main_hand) @@ -727,22 +727,23 @@ if(main_hand.force != 0) if(istype(main_hand,/obj/item/weapon/gun)) var/obj/item/weapon/gun/G = main_hand - if(G.special_check(src)) + if(G.can_trigger_gun(src)) var/shouldFire = 1 if(istype(main_hand, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/P = main_hand var/stunning = 0 - if(ispath(text2path(P.projectile_type), /obj/item/projectile/energy/electrode)) - stunning = 1 + for(var/A in P.ammo_type) + if(ispath(A,/obj/item/ammo_casing/energy/electrode)) + stunning = 1 var/mob/stunCheck = TARGET if(stunning && stunCheck.stunned) shouldFire = 0 if(shouldFire) - if(!G.process_chambered()) - G.click_empty(src) + if(!G.can_shoot()) + G.shoot_with_empty_chamber(src) npcDrop(G, 1) else - G.Fire(TARGET, src) + G.process_fire(TARGET, src) else if(get_dist(src,TARGET) > 6) if(!walk2derpless(TARGET)) @@ -871,4 +872,4 @@ else A.stamp(S) custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they stamp \the [A] with \a [S]!") - return \ No newline at end of file + return 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/say.dm b/code/modules/mob/living/carbon/human/say.dm index 7162933349d..840b500de01 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -148,6 +148,9 @@ if(prob(braindam)) message = uppertext(message) verb = "yells loudly" + + if(locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) + message = "[message]" returns[1] = message returns[2] = verb diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm index 26ee19b0788..003e1969d33 100644 --- a/code/modules/mob/living/carbon/human/species/plasmaman.dm +++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm @@ -66,7 +66,7 @@ if("Warden","Security Officer","Security Pod Pilot") suit=/obj/item/clothing/suit/space/eva/plasmaman/security/ helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security/ - H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_in_backpack) if("Magistrate") suit=/obj/item/clothing/suit/space/eva/plasmaman/magistrate helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/magistrate diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 599857390d2..bc4851b9ec3 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/life.dm b/code/modules/mob/living/carbon/life.dm index 986ea2210d3..eb328291bf7 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -468,4 +468,4 @@ else healths.icon_state = "health6" else - healths.icon_state = "health7" \ No newline at end of file + healths.icon_state = "health7" 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 c3c64c1c696..82f865621da 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -59,6 +59,8 @@ if(get_nations_mode()) process_nations() + ..() + /mob/living/proc/handle_breathing() return @@ -112,6 +114,7 @@ handle_paralysed() handle_sleeping() handle_slowed() + handle_drunk() /mob/living/proc/handle_stunned() @@ -166,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 @@ -251,19 +259,17 @@ /mob/living/proc/give_action_button(var/obj/item/I, recursive = 0) if(I.action_button_name) if(!I.action) - if(istype(I, /obj/item/organ/internal)) - I.action = new/datum/action/item_action/organ_action - else if(I.action_button_is_hands_free) - I.action = new/datum/action/item_action/hands_free + if(I.action_button_custom_type) + I.action = new I.action_button_custom_type else - I.action = new/datum/action/item_action + I.action = new /datum/action/item_action I.action.name = I.action_button_name I.action.target = I I.action.Grant(src) if(recursive) for(var/obj/item/T in I) - give_action_button(I, recursive - 1) + give_action_button(T, recursive - 1) /mob/living/update_action_buttons() if(!hud_used) return @@ -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/living.dm b/code/modules/mob/living/living.dm index d00ed375c33..7185cfdb53b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -588,9 +588,6 @@ visible_message("[src] resists!") return 1 -/mob/living/proc/resist_borer() - return - /mob/living/proc/resist_buckle() spawn(0) resist_muzzle() @@ -855,3 +852,9 @@ tally += 10 return tally + +/mob/living/proc/can_use_guns(var/obj/item/weapon/gun/G) + if (G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser()) + to_chat(src, "You don't have the dexterity to do this!") + return 0 + return 1 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 4d994436489..cc50408148e 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -47,10 +47,6 @@ proj_sharp = 0 proj_edge = 0 - if(istype(P, /obj/item/projectile/beam/lightning)) //Stupid snowflake lightning gun. - if(P.damage >= 200) - src.dust() - if(!P.nodamage) apply_damage(P.damage, P.damage_type, def_zone, armor) return P.on_hit(src, armor, def_zone) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index d8ab75777d4..1b883f30c55 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -301,34 +301,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/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 3346882a488..812d2e8df58 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -814,7 +814,8 @@ var/list/ai_verbs_default = list( var/icon_list[] = list( "default", "floating face", - "xeno queen" + "xeno queen", + "eldritch" ) input = input("Please select a hologram:") as null|anything in icon_list if(input) @@ -826,6 +827,8 @@ var/list/ai_verbs_default = list( holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) if("xeno queen") holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) + if("eldritch") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) return /mob/living/silicon/ai/proc/corereturn() diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm deleted file mode 100644 index c70979c5947..00000000000 --- a/code/modules/mob/living/silicon/emote.dm +++ /dev/null @@ -1,121 +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") - //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("help") - to_chat(src, "yes, no, beep, ping, buzz") - - ..(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 97b15ecda1a..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)) @@ -246,4 +249,4 @@ if(!module) hands.icon_state = "nomod" else - hands.icon_state = lowertext(module.module_type) \ No newline at end of file + hands.icon_state = lowertext(module.module_type) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 12030e52773..7fb1ba0a8aa 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -337,7 +337,7 @@ src.modules += new /obj/item/device/flash/cyborg(src) src.modules += new /obj/item/borg/sight/thermal(src) src.modules += new /obj/item/weapon/melee/energy/sword/cyborg(src) - src.modules += new /obj/item/weapon/gun/energy/pulse_rifle/cyborg(src) + src.modules += new /obj/item/weapon/gun/energy/pulse/cyborg(src) src.modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src) src.modules += new /obj/item/weapon/crowbar(src) src.emag = null 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/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 2c2ca652d10..27bfe821502 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -158,7 +158,7 @@ return newname = "redtag ED-209 assembly" if("") - if(!istype(W, /obj/item/weapon/gun/energy/advtaser)) + if(!istype(W, /obj/item/weapon/gun/energy/gun/advtaser)) return newname = "taser ED-209 assembly" else diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 12dd032ba49..34888dd3488 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -365,7 +365,7 @@ Auto Patrol[]"}, new /obj/item/device/assembly/prox_sensor(Tsec) if(!lasercolor) - var/obj/item/weapon/gun/energy/advtaser/G = new /obj/item/weapon/gun/energy/advtaser(Tsec) + var/obj/item/weapon/gun/energy/gun/advtaser/G = new /obj/item/weapon/gun/energy/gun/advtaser(Tsec) G.power_supply.charge = 0 G.update_icon() else if(lasercolor == "b") @@ -403,7 +403,7 @@ Auto Patrol[]"}, shoot_sound = 'sound/weapons/laser.ogg' if(emagged == 2) if(lasercolor) - projectile = /obj/item/projectile/lasertag + projectile = /obj/item/projectile/beam/lasertag else projectile = /obj/item/projectile/beam else @@ -411,9 +411,9 @@ Auto Patrol[]"}, shoot_sound = 'sound/weapons/Taser.ogg' projectile = /obj/item/projectile/energy/electrode else if(lasercolor == "b") - projectile = /obj/item/projectile/lasertag/blue + projectile = /obj/item/projectile/beam/lasertag/bluetag else if(lasercolor == "r") - projectile = /obj/item/projectile/lasertag/red + projectile = /obj/item/projectile/beam/lasertag/redtag /mob/living/simple_animal/bot/ed209/proc/shootAt(mob/target) if(lastfired && world.time - lastfired < shot_delay) @@ -438,8 +438,7 @@ Auto Patrol[]"}, A.current = U A.yo = U.y - T.y A.xo = U.x - T.x - spawn(0) - A.process() + A.fire() /mob/living/simple_animal/bot/ed209/attack_alien(mob/living/carbon/alien/user) ..() @@ -491,10 +490,10 @@ Auto Patrol[]"}, if(!disabled) var/lasertag_check = 0 if((lasercolor == "b")) - if(istype(Proj, /obj/item/projectile/lasertag/red)) + if(istype(Proj, /obj/item/projectile/beam/lasertag/redtag)) lasertag_check++ else if((lasercolor == "r")) - if(istype(Proj, /obj/item/projectile/lasertag/blue)) + if(istype(Proj, /obj/item/projectile/beam/lasertag/bluetag)) lasertag_check++ if(lasertag_check) icon_state = "[lasercolor]ed2090" 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/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 4f8b7753caf..e8ba27fa07d 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -632,8 +632,7 @@ A.current = T A.yo = U.y - T.y A.xo = U.x - T.x - spawn( 0 ) - A.process() + A.fire() return /mob/living/simple_animal/pet/corgi/Ian/borgi/Life() @@ -657,4 +656,4 @@ s.start() respawnable_list += src qdel(src) - return \ No newline at end of file + return 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 418c30199d0..faf0cc0f9a3 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -260,20 +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 ) - A.process() - return + 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 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/living/simple_animal/vox.dm b/code/modules/mob/living/simple_animal/vox.dm index 3b34ddaf143..1a46e46e4e4 100644 --- a/code/modules/mob/living/simple_animal/vox.dm +++ b/code/modules/mob/living/simple_animal/vox.dm @@ -65,15 +65,26 @@ if ((O.client && !( O.blinded ))) to_chat(O, "\red [src] launches a razor-sharp quill at [target]!") - var/obj/item/weapon/arrow/quill/Q = new(loc) + var/obj/item/weapon/quill/Q = new(loc) Q.fingerprintslast = src.ckey Q.throw_at(target,10,30) + quills-- spawn(100) to_chat(src, "\red You feel a fresh quill slide into place.") quills++ +/obj/item/weapon/quill + name = "vox quill" + desc = "A wickedly barbed quill from some bizarre animal." + icon_state = "quill" + item_state = "quill" + throwforce = 5 + w_class = 3.0 + sharp = 1 + edge = 0 + /mob/living/simple_animal/vox/armalis/verb/message_mob() set category = "Alien" set name = "Commune with creature" @@ -155,4 +166,4 @@ desc = "A series of metallic lenses and chains." icon = 'icons/obj/clothing/hats.dmi' icon_state = "amp" - item_state = "amp" \ No newline at end of file + item_state = "amp" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 872350d6d9e..f41cef386aa 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() @@ -1094,6 +1097,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 87a7735c677..b223a775b1f 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 @@ -235,3 +236,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 98437a53ffd..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 @@ -93,13 +94,15 @@ hud.screen_loc = ui_rhand else hud.screen_loc = ui_lhand - + assailant.client.screen += hud /obj/item/weapon/grab/process() - if(!confirm()) return //If the confirm fails, the grab is about to be deleted. That means it shouldn't continue processing. + if(!confirm()) + return //If the confirm fails, the grab is about to be deleted. That means it shouldn't continue processing. if(assailant.client) - if(!hud) return //this somehow can runtime under the right circumstances + if(!hud) + return //this somehow can runtime under the right circumstances assailant.client.screen -= hud assailant.client.screen += hud @@ -136,12 +139,8 @@ hud.icon_state = "!reinforce" if(state >= GRAB_AGGRESSIVE) - var/h = affecting.hand - affecting.hand = 0 - affecting.drop_item() - affecting.hand = 1 - affecting.drop_item() - affecting.hand = h + affecting.drop_r_hand() + affecting.drop_l_hand() //var/announce = 0 @@ -440,7 +439,13 @@ affecting.pixel_y = 0 //used to be an animate, not quick enough for del'ing affecting.layer = initial(affecting.layer) affecting.grabbed_by -= src + affecting = null + if(assailant) + if(assailant.client) + assailant.client.screen -= hud + assailant = null qdel(hud) + hud = null return ..() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 0ec92783908..9cf0b902d35 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -299,26 +299,38 @@ ///Called by client/Move() ///Checks to see if you are being grabbed and if so attemps to break it /client/proc/Process_Grab() - if(locate(/obj/item/weapon/grab, locate(/obj/item/weapon/grab, mob.grabbed_by.len))) + if(mob.grabbed_by.len) var/list/grabbing = list() + if(istype(mob.l_hand, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = mob.l_hand grabbing += G.affecting + if(istype(mob.r_hand, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = mob.r_hand grabbing += G.affecting - for(var/obj/item/weapon/grab/G in mob.grabbed_by) - if((G.state == 1)&&(!grabbing.Find(G.assailant))) qdel(G) - if(G.state == 2) - move_delay = world.time + 10 - if(!prob(25)) return 1 - mob.visible_message("\red [mob] has broken free of [G.assailant]'s grip!") - qdel(G) - if(G.state == 3) - move_delay = world.time + 10 - if(!prob(5)) return 1 - mob.visible_message("\red [mob] has broken free of [G.assailant]'s headlock!") - qdel(G) + + for(var/X in mob.grabbed_by) + var/obj/item/weapon/grab/G = X + switch(G.state) + + if(GRAB_PASSIVE) + if(!grabbing.Find(G.assailant)) //moving always breaks a passive grab unless we are also grabbing our grabber. + qdel(G) + + if(GRAB_AGGRESSIVE) + move_delay = world.time + 10 + if(!prob(25)) + return 1 + mob.visible_message("[mob] has broken free of [G.assailant]'s grip!") + qdel(G) + + if(GRAB_NECK) + move_delay = world.time + 10 + if(!prob(5)) + return 1 + mob.visible_message("[mob] has broken free of [G.assailant]'s headlock!") + qdel(G) return 0 diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index bbb0211ce67..f7cff248519 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -34,10 +34,6 @@ verbs += /client/proc/readmin spawn(40) if(client) - if(client.prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP - winset(client, "rpane.changelog", "background-color=#f4aa94;font-style=bold") - client.prefs.SetChangelog(client,changelog_hash) - to_chat(src, "Changelog has changed since your last visit.") client.playtitlemusic() if(config.player_overflow_cap && config.overflow_server_url) //Overflow rerouting, if set, forces players to be moved to a different server once a player cap is reached. Less rough than a pure kick. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 60285b092fc..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

    " @@ -452,7 +453,7 @@ var/datum/language/chosen_language if(client.prefs.language) chosen_language = all_languages[client.prefs.language] - if((chosen_language == null && chosen_language != "None") || (chosen_language && chosen_language.flags & RESTRICTED)) + if((chosen_language == null && client.prefs.language != "None") || (chosen_language && chosen_language.flags & RESTRICTED)) log_debug("[src] had language [client.prefs.language], though they weren't supposed to. Setting to None.") client.prefs.language = "None" 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/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 23a0f3eec7e..c0e7a2bc468 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -260,9 +260,10 @@ var/list/alldepartments = list() visible_message("[src] beeps, \"Message transmitted successfully.\"") -/obj/machinery/photocopier/faxmachine/proc/message_admins(var/mob/sender, var/faxname, var/faxtype, var/obj/item/sent, font_colour="#006100") - var/msg = "\blue [faxname]: [key_name(sender, 1)] (PP) (VV) (SM) ([admin_jump_link(sender, "holder")]) (CA) (BSA) (REPLY): Receiving '[sent.name]' via secure connection... view message" - +/obj/machinery/photocopier/faxmachine/proc/message_admins(var/mob/sender, var/faxname, var/faxtype, var/obj/item/sent, font_colour="#9A04D1") + var/msg = "\blue [faxname]: [key_name(sender, 1)] (PP) (VV) (CA) ([admin_jump_link(sender, "holder")]) | REPLY: (RADIO) (FAX) (SM) | REJECT: (TEMPLATE) (BSA) (EVILFAX) : Receiving '[sent.name]' via secure connection... view message" for(var/client/C in admins) if(R_EVENT & C.holder.rights) to_chat(C, msg) + if(C.prefs.sound & SOUND_ADMINHELP) + C << 'sound/effects/adminhelp.ogg' diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index bf847a06c0a..11f864451b7 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) @@ -618,3 +620,85 @@ /obj/item/weapon/paper/crumpled/bloody icon_state = "scrap_bloodied" + +/obj/item/weapon/paper/evilfax + name = "Centcomm Reply" + info = "" + var/mytarget = null + var/myeffect = null + var/used = 0 + var/countdown = 60 + var/activate_on_timeout = 0 + +/obj/item/weapon/paper/evilfax/show_content(var/mob/user, var/forceshow = 0, var/forcestars = 0, var/infolinks = 0, var/view = 1) + if(user == mytarget) + if(istype(user, /mob/living/carbon)) + var/mob/living/carbon/C = user + evilpaper_specialaction(C) + ..() + else + // This should never happen, but just in case someone is adminbussing + evilpaper_selfdestruct() + else + if(mytarget) + to_chat(user,"This page appears to be covered in some sort of bizzare code. The only bit you recognize is the name of [mytarget]. Perhaps [mytarget] can make sense of it?") + else + evilpaper_selfdestruct() + + +/obj/item/weapon/paper/evilfax/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/paper/evilfax/Destroy() + processing_objects.Remove(src) + if(mytarget && !used) + var/mob/living/carbon/target = mytarget + target.ForceContractDisease(new /datum/disease/transformation/corgi(0)) + return ..() + + +/obj/item/weapon/paper/evilfax/process() + if(!countdown) + if(mytarget) + if(activate_on_timeout) + evilpaper_specialaction(mytarget) + else + message_admins("[mytarget] ignored an evil fax until it timed out.") + else + message_admins("Evil paper '[src]' timed out, after not being assigned a target.") + used = 1 + evilpaper_selfdestruct() + else + countdown-- + +/obj/item/weapon/paper/evilfax/proc/evilpaper_specialaction(var/mob/living/carbon/target) + spawn(30) + if(istype(target,/mob/living/carbon)) + if(myeffect == "borging") + target.ForceContractDisease(new /datum/disease/transformation/robot(0)) + else if(myeffect == "corgifying") + target.ForceContractDisease(new /datum/disease/transformation/corgi(0)) + else if(myeffect == "firedeath") + var/turf/simulated/T = get_turf(target) + new /obj/effect/hotspot(T) + target.adjustFireLoss(150) // hard crit, the burning takes care of the rest. + else if(myeffect == "braindeath") + to_chat(target,"A series of bright lights flash across your vision: COGNITOHAZARD YHWH-3 ACTIVATED") + target.mutations.Add(NOCLONE) + target.adjustBrainLoss(125) + else if(myeffect == "honktumor") + if(!target.get_int_organ(/obj/item/organ/internal/honktumor)) + var/obj/item/organ/internal/organ = new /obj/item/organ/internal/honktumor + organ.insert(target) + else if(myeffect == "demotion") + command_announcement.Announce("[mytarget] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + else + message_admins("Evil paper [src] was activated without a proper effect set! This is a bug.") + used = 1 + evilpaper_selfdestruct() + +/obj/item/weapon/paper/evilfax/proc/evilpaper_selfdestruct() + visible_message("[src] spontaneously catches fire, and burns up!") + qdel(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/cable.dm b/code/modules/power/cable.dm index 8208635f577..863b231f25a 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -520,6 +520,11 @@ obj/structure/cable/proc/cableColor(var/colorC) else return ..() +/obj/item/stack/cable_coil/split() + var/obj/item/stack/cable_coil/C = ..() + C.color = color + return C + /obj/item/stack/cable_coil/update_icon() if (!color) color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_ORANGE, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN) @@ -600,27 +605,6 @@ obj/structure/cable/proc/cableColor(var/colorC) src.use(amt) return -//remove cables from the stack -/* This is probably reduntant -/obj/item/stack/cable_coil/use(var/used) - if(src.amount < used) - return 0 - else if (src.amount == used) - if(ismob(loc)) //handle mob icon update - var/mob/M = loc - M.unEquip(src) - qdel(src) - return 1 - else - amount -= used - update_icon() - return 1 -*/ -/obj/item/stack/cable_coil/use(var/used) - . = ..() - update_icon() - return - //add cables to the stack /obj/item/stack/cable_coil/proc/give(var/extra) if(amount + extra > MAXCOIL) 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/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 4f0d72e1511..06ba1a093f8 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -213,7 +213,7 @@ else // Any other A.yo = -20 A.xo = 0 - A.process() //TODO: Carn: check this out + A.fire() //TODO: Carn: check this out /obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params) diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 45670ec70b0..26dce25ead2 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -6,14 +6,16 @@ flags = CONDUCT slot_flags = SLOT_BELT throwforce = 1 - w_class = 1.0 - var/caliber = "" //Which kind of guns it can be loaded into - var/projectile_type = ""//The bullet type to create when New() is called + w_class = 1 + var/fire_sound = null //What sound should play when this ammo is fired + var/caliber = null //Which kind of guns it can be loaded into + var/projectile_type = null //The bullet type to create when New() is called var/obj/item/projectile/BB = null //The loaded bullet - var/pellets = 1 - var/deviation = 0 - var/spread = 0 - + var/pellets = 1 //Pellets for spreadshot + var/variance = 0 //Variance for inaccuracy fundamental to the casing + var/delay = 0 //Delay for energy weapons + var/randomspread = 0 //Randomspread for automatics + var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown. /obj/item/ammo_casing/New() ..() @@ -29,54 +31,50 @@ icon_state = "[initial(icon_state)][BB ? "-live" : ""]" desc = "[initial(desc)][BB ? "" : " This one is spent"]" - - -/obj/item/ammo_casing/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/weapon/screwdriver)) - if(BB) - if(initial(BB.name) == "bullet") - var/tmp_label = "" - var/label_text = sanitize(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label)) - if(length(label_text) > 20) - to_chat(user, "The inscription can be at most 20 characters long.") - else - if(label_text == "") - to_chat(user, "You scratch the inscription off of [initial(BB)].") - BB.name = initial(BB.name) - else - to_chat(user, "You inscribe \"[label_text]\" into \the [initial(BB.name)].") - BB.name = "[initial(BB.name)] \"[label_text]\"" - else - to_chat(user, "You can only inscribe a metal bullet.")//because inscribing beanbags is silly - - else - to_chat(user, "There is no bullet in the casing to inscribe anything into.") - -/obj/item/ammo_casing/attackby(obj/item/ammo_box/box as obj, mob/user as mob, params) - if(!istype(box, /obj/item/ammo_box)) - return - if(isturf(loc)) - var/boolets = 0 - for(var/obj/item/ammo_casing/pew in loc) - if(box.stored_ammo.len >= box.max_ammo) - break - if(pew.BB) - if(box.give_round(pew)) - boolets++ - else - continue - if(boolets > 0) - box.update_icon() - to_chat(user, "You collect [boolets] shell\s. [box] now contains [box.stored_ammo.len] shell\s.") - else - to_chat(user, "You fail to collect anything.") - -/obj/item/ammo_casing/proc/newshot() //For energy weapons, shotgun shells and wands (!). - if(!BB) - BB = new projectile_type(src) +/obj/item/ammo_casing/proc/newshot(params) //For energy weapons, shotgun shells and wands (!). + if (!BB) + BB = new projectile_type(src, params) return +/obj/item/ammo_casing/attackby(obj/item/I as obj, mob/user as mob, params) + if(istype(I, /obj/item/ammo_box)) + var/obj/item/ammo_box/box = I + if(isturf(loc)) + var/boolets = 0 + for(var/obj/item/ammo_casing/bullet in loc) + if (box.stored_ammo.len >= box.max_ammo) + break + if (bullet.BB) + if (box.give_round(bullet, 0)) + boolets++ + else + continue + if (boolets > 0) + box.update_icon() + to_chat(user, "You collect [boolets] shell\s. [box] now contains [box.stored_ammo.len] shell\s.") + else + to_chat(user, "You fail to collect anything!") + else + if(istype(I, /obj/item/weapon/screwdriver)) + if(BB) + if(initial(BB.name) == "bullet") + var/tmp_label = "" + var/label_text = sanitize(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label)) + if(length(label_text) > 20) + to_chat(user, "The inscription can be at most 20 characters long.") + else + if(label_text == "") + to_chat(user, "You scratch the inscription off of [initial(BB)].") + BB.name = initial(BB.name) + else + to_chat(user, "You inscribe \"[label_text]\" into \the [initial(BB.name)].") + BB.name = "[initial(BB.name)] \"[label_text]\"" + else + to_chat(user, "You can only inscribe a metal bullet.")//because inscribing beanbags is silly + else + to_chat(user, "There is no bullet in the casing to inscribe anything into.") + ..() //Boxes of ammo /obj/item/ammo_box @@ -89,53 +87,78 @@ item_state = "syringe_kit" materials = list(MAT_METAL=30000) throwforce = 2 - w_class = 1.0 + w_class = 1 throw_speed = 4 throw_range = 10 var/list/stored_ammo = list() - var/obj/item/ammo_casing/ammo_type + var/ammo_type = /obj/item/ammo_casing var/max_ammo = 7 var/multiple_sprites = 0 - var/caliber = "" + var/caliber var/multiload = 1 + /obj/item/ammo_box/New() - for(var/i = 1, i <= max_ammo, i++) + for(var/i in 1 to max_ammo) stored_ammo += new ammo_type(src) update_icon() -/obj/item/ammo_box/proc/get_round(var/keep = 0) - if(!stored_ammo.len) +/obj/item/ammo_box/Destroy() + for(var/atom/A in stored_ammo) + qdel(A) + stored_ammo = null + return ..() + +/obj/item/ammo_box/proc/get_round(keep = 0) + if (!stored_ammo.len) return null else var/b = stored_ammo[stored_ammo.len] stored_ammo -= b - if(keep) + if (keep) stored_ammo.Insert(1,b) return b -/obj/item/ammo_box/proc/give_round(var/obj/item/ammo_casing/r) - var/obj/item/ammo_casing/rb = r - if(rb) - if(stored_ammo.len < max_ammo && rb.caliber == caliber) - stored_ammo += rb - rb.loc = src - return 1 +/obj/item/ammo_box/proc/give_round(obj/item/ammo_casing/R, replace_spent = 0) + // Boxes don't have a caliber type, magazines do. Not sure if it's intended or not, but if we fail to find a caliber, then we fall back to ammo_type. + if(!R || (caliber && R.caliber != caliber) || (!caliber && R.type != ammo_type)) + return 0 + + if (stored_ammo.len < max_ammo) + stored_ammo += R + R.loc = src + return 1 + //for accessibles magazines (e.g internal ones) when full, start replacing spent ammo + else if(replace_spent) + for(var/obj/item/ammo_casing/AC in stored_ammo) + if(!AC.BB)//found a spent ammo + stored_ammo -= AC + AC.loc = get_turf(loc) + + stored_ammo += R + R.loc = src + return 1 + return 0 -/obj/item/ammo_box/attackby(var/obj/item/A as obj, mob/user as mob, var/silent = 0, params) +/obj/item/ammo_box/proc/can_load(mob/user) + return 1 + +/obj/item/ammo_box/attackby(obj/item/A, mob/user, params, silent = 0, replace_spent = 0) var/num_loaded = 0 + if(!can_load(user)) + return if(istype(A, /obj/item/ammo_box)) var/obj/item/ammo_box/AM = A for(var/obj/item/ammo_casing/AC in AM.stored_ammo) - var/didload = give_round(AC) - if(didload) + var/did_load = give_round(AC, replace_spent) + if(did_load) AM.stored_ammo -= AC num_loaded++ - if(!multiload || !didload) + if(!multiload || !did_load) break if(istype(A, /obj/item/ammo_casing)) var/obj/item/ammo_casing/AC = A - if(give_round(AC)) + if(give_round(AC, replace_spent)) user.drop_item() AC.loc = src num_loaded++ @@ -145,6 +168,8 @@ A.update_icon() update_icon() + return num_loaded + /obj/item/ammo_box/attack_self(mob/user as mob) var/obj/item/ammo_casing/A = get_round() if(A) diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index 44189411515..a5af74e4d6c 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -1,128 +1,146 @@ /obj/item/ammo_casing/a357 desc = "A .357 bullet casing." caliber = "357" - projectile_type = "/obj/item/projectile/bullet" + projectile_type = /obj/item/projectile/bullet + +/obj/item/ammo_casing/a762 + desc = "A 7.62mm bullet casing." + icon_state = "762-casing" + caliber = "a762" + projectile_type = /obj/item/projectile/bullet + +/obj/item/ammo_casing/a762/enchanted + projectile_type = /obj/item/projectile/bullet/weakbullet3 /obj/item/ammo_casing/a50 desc = "A .50AE bullet casing." caliber = ".50" - projectile_type = "/obj/item/projectile/bullet" + projectile_type = /obj/item/projectile/bullet /obj/item/ammo_casing/c38 desc = "A .38 bullet casing." caliber = "38" - projectile_type = "/obj/item/projectile/bullet/weakbullet2/rubber" - -/obj/item/ammo_casing/cap - desc = "A cap for children toys." - caliber = "caps" - projectile_type = "/obj/item/projectile/bullet/cap" - + projectile_type = /obj/item/projectile/bullet/weakbullet2/rubber /obj/item/ammo_casing/c10mm desc = "A 10mm bullet casing." caliber = "10mm" - projectile_type = "/obj/item/projectile/bullet/midbullet3" - + projectile_type = /obj/item/projectile/bullet/midbullet3 /obj/item/ammo_casing/c9mm desc = "A 9mm bullet casing." caliber = "9mm" - projectile_type = "/obj/item/projectile/bullet/weakbullet3" + projectile_type = /obj/item/projectile/bullet/weakbullet3 /obj/item/ammo_casing/c9mmap desc = "A 9mm bullet casing." caliber = "9mm" - projectile_type = "/obj/item/projectile/bullet/armourpiercing" + projectile_type = /obj/item/projectile/bullet/armourpiercing /obj/item/ammo_casing/c9mmtox desc = "A 9mm bullet casing." caliber = "9mm" - projectile_type = "/obj/item/projectile/bullet/toxinbullet" + projectile_type = /obj/item/projectile/bullet/toxinbullet /obj/item/ammo_casing/c9mminc desc = "A 9mm bullet casing." caliber = "9mm" - projectile_type = "/obj/item/projectile/bullet/incendiary/firebullet" + projectile_type = /obj/item/projectile/bullet/incendiary/firebullet /obj/item/ammo_casing/c46x30mm desc = "A 4.6x30mm bullet casing." caliber = "4.6x30mm" - projectile_type = "/obj/item/projectile/bullet/weakbullet3" + projectile_type = /obj/item/projectile/bullet/weakbullet3 /obj/item/ammo_casing/c46x30mmap desc = "A 4.6x30mm bullet casing." caliber = "4.6x30mm" - projectile_type = "/obj/item/projectile/bullet/armourpiercing" + projectile_type = /obj/item/projectile/bullet/armourpiercing /obj/item/ammo_casing/c46x30mmtox desc = "A 4.6x30mm bullet casing." caliber = "4.6x30mm" - projectile_type = "/obj/item/projectile/bullet/toxinbullet" + projectile_type = /obj/item/projectile/bullet/toxinbullet /obj/item/ammo_casing/c46x30mminc desc = "A 4.6x30mm bullet casing." caliber = "4.6x30mm" - projectile_type = "/obj/item/projectile/bullet/incendiary/firebullet" + projectile_type = /obj/item/projectile/bullet/incendiary/firebullet /obj/item/ammo_casing/c45 desc = "A .45 bullet casing." caliber = ".45" - projectile_type = "/obj/item/projectile/bullet/midbullet" + projectile_type = /obj/item/projectile/bullet/midbullet +/obj/item/ammo_casing/c45nostamina + desc = "A .45 bullet casing." + caliber = ".45" + projectile_type = /obj/item/projectile/bullet/midbullet3 + +/obj/item/ammo_casing/n762 + desc = "A 7.62x38mmR bullet casing." + caliber = "n762" + projectile_type = /obj/item/projectile/bullet + +/obj/item/ammo_casing/caseless/magspear + name = "magnetic spear" + desc = "A reusable spear that is typically loaded into kinetic spearguns." + projectile_type = /obj/item/projectile/bullet/reusable/magspear + caliber = "speargun" + icon_state = "magspear" + throwforce = 15 //still deadly when thrown + throw_speed = 3 /obj/item/ammo_casing/shotgun name = "shotgun slug" desc = "A 12 gauge lead slug." icon_state = "blshell" caliber = "shotgun" - projectile_type = "/obj/item/projectile/bullet" + projectile_type = /obj/item/projectile/bullet materials = list(MAT_METAL=4000) - /obj/item/ammo_casing/shotgun/buckshot name = "buckshot shell" desc = "A 12 gauge buckshot shell." icon_state = "gshell" - projectile_type = "/obj/item/projectile/bullet/pellet" + projectile_type = /obj/item/projectile/bullet/pellet pellets = 6 - deviation = 30 + variance = 25 /obj/item/ammo_casing/shotgun/rubbershot name = "rubber shot" desc = "A shotgun casing filled with densely-packed rubber balls, used to incapacitate crowds from a distance." icon_state = "bshell" - projectile_type = "/obj/item/projectile/bullet/rpellet" + projectile_type = /obj/item/projectile/bullet/rpellet pellets = 6 - deviation = 30 + variance = 25 materials = list(MAT_METAL=4000) /obj/item/ammo_casing/shotgun/beanbag name = "beanbag slug" desc = "A weak beanbag slug for riot control." icon_state = "bshell" - projectile_type = "/obj/item/projectile/bullet/weakbullet/rubber" + projectile_type = /obj/item/projectile/bullet/weakbullet/rubber materials = list(MAT_METAL=250) - /obj/item/ammo_casing/shotgun/improvised name = "improvised shell" desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards." icon_state = "gshell" - projectile_type = "/obj/item/projectile/bullet/pellet/weak" + projectile_type = /obj/item/projectile/bullet/pellet/weak materials = list(MAT_METAL=250) pellets = 5 - deviation = 30 + variance = 25 /obj/item/ammo_casing/shotgun/improvised/overload name = "overloaded improvised shell" desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards. This one has been packed with even more \ propellant. It's like playing russian roulette, with a shotgun." icon_state = "improvshell" - projectile_type = "/obj/item/projectile/bullet/pellet/random" + projectile_type = /obj/item/projectile/bullet/pellet/overload materials = list(MAT_METAL=250) pellets = 5 - deviation = 30 + variance = 40 /obj/item/ammo_casing/shotgun/improvised/overload/New() ..() @@ -132,15 +150,20 @@ name = "taser slug" desc = "A stunning taser slug." icon_state = "stunshell" - projectile_type = "/obj/item/projectile/bullet/stunshot" + projectile_type = /obj/item/projectile/bullet/stunshot materials = list(MAT_METAL=250) - /obj/item/ammo_casing/shotgun/meteorshot name = "meteorshot shell" desc = "A shotgun shell rigged with CMC technology, which launches a massive slug when fired." icon_state = "mshell" - projectile_type = "/obj/item/projectile/bullet/meteorshot" + projectile_type = /obj/item/projectile/bullet/meteorshot + +/obj/item/ammo_casing/shotgun/breaching + name = "breaching shell" + desc = "An economic version of the meteorshot, utilizing similar technologies. Great for busting down doors." + icon_state = "mshell" + projectile_type = /obj/item/projectile/bullet/meteorshot/weak /obj/item/ammo_casing/shotgun/pulseslug name = "pulse slug" @@ -148,42 +171,42 @@ energy blast. While the heat and power drain limit it to one use, it can still allow an operator to engage targets that ballistic ammunition \ would have difficulty with." icon_state = "pshell" - projectile_type = "/obj/item/projectile/beam/pulse/shot" + projectile_type = /obj/item/projectile/beam/pulse/shot /obj/item/ammo_casing/shotgun/incendiary name = "incendiary slug" desc = "An incendiary-coated shotgun slug." icon_state = "ishell" - projectile_type = "/obj/item/projectile/bullet/incendiary/shell" + projectile_type = /obj/item/projectile/bullet/incendiary/shell /obj/item/ammo_casing/shotgun/frag12 name = "FRAG-12 slug" desc = "A high explosive breaching round for a 12 gauge shotgun." icon_state = "heshell" - projectile_type = "/obj/item/projectile/bullet/frag12" + projectile_type = /obj/item/projectile/bullet/frag12 /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath name = "dragonsbreath shell" desc = "A shotgun shell which fires a spread of incendiary pellets." icon_state = "ishell2" - projectile_type = "/obj/item/projectile/bullet/incendiary/shell/dragonsbreath" + projectile_type = /obj/item/projectile/bullet/incendiary/shell/dragonsbreath pellets = 4 - deviation = 30 + variance = 35 /obj/item/ammo_casing/shotgun/ion name = "ion shell" desc = "An advanced shotgun shell which uses a subspace ansible crystal to produce an effect similar to a standard ion rifle. \ The unique properties of the crystal splot the pulse into a spread of individually weaker bolts." icon_state = "ionshell" - projectile_type = "/obj/item/projectile/ion/weak" + projectile_type = /obj/item/projectile/ion/weak pellets = 4 - deviation = 30 + variance = 35 /obj/item/ammo_casing/shotgun/laserslug name = "laser slug" desc = "An advanced shotgun shell that uses a micro laser to replicate the effects of a laser weapon in a ballistic package." icon_state = "lshell" - projectile_type = "/obj/item/projectile/beam" + projectile_type = /obj/item/projectile/beam /obj/item/ammo_casing/shotgun/techshell name = "unloaded technological shell" @@ -195,7 +218,7 @@ name = "shotgun dart" desc = "A dart for use in shotguns. Can be injected with up to 30 units of any chemical." icon_state = "cshell" - projectile_type = "/obj/item/projectile/bullet/dart" + projectile_type = /obj/item/projectile/bullet/dart /obj/item/ammo_casing/shotgun/dart/New() ..() @@ -206,93 +229,116 @@ /obj/item/ammo_casing/shotgun/dart/attackby() return +/obj/item/ammo_casing/shotgun/dart/bioterror + desc = "A shotgun dart filled with deadly toxins." + +/obj/item/ammo_casing/shotgun/dart/bioterror/New() + ..() + reagents.add_reagent("neurotoxin", 6) + reagents.add_reagent("spores", 6) + reagents.add_reagent("mutetoxin", 6) //;HELP OPS IN MAINT + reagents.add_reagent("coniine", 6) + reagents.add_reagent("sodium_thiopental", 6) + /obj/item/ammo_casing/shotgun/tranquilizer name = "tranquilizer darts" desc = "A tranquilizer round used to subdue individuals utilizing stimulants." icon_state = "cshell" - projectile_type = "/obj/item/projectile/bullet/dart/syringe/tranquilizer" + projectile_type = /obj/item/projectile/bullet/dart/syringe/tranquilizer materials = list(MAT_METAL=250) -/obj/item/ammo_casing/syringegun - name = "syringe gun spring" - desc = "A high-power spring that throws syringes." - projectile_type = null +/obj/item/ammo_casing/a556 + desc = "A 5.56mm bullet casing." + caliber = "a556" + projectile_type = /obj/item/projectile/bullet/heavybullet /obj/item/ammo_casing/shotgun/fakebeanbag name = "beanbag shell" desc = "A weak beanbag shell." icon_state = "bshell" - projectile_type = "/obj/item/projectile/bullet/weakbullet/booze" - -/obj/item/ammo_casing/a762 - desc = "A 7.62mm bullet casing." - icon_state = "762-casing" - caliber = "a762" - projectile_type = "/obj/item/projectile/bullet" - -/obj/item/ammo_casing/a556 - desc = "A 5.56mm bullet casing." - caliber = "a556" - projectile_type = "/obj/item/projectile/bullet/heavybullet" + projectile_type = /obj/item/projectile/bullet/weakbullet/booze /obj/item/ammo_casing/rocket name = "rocket shell" desc = "A high explosive designed to be fired from a launcher." icon_state = "rocketshell" - projectile_type = "/obj/item/missile" + projectile_type = /obj/item/missile caliber = "rocket" /obj/item/ammo_casing/caseless desc = "A caseless bullet casing." +/obj/item/ammo_casing/caseless/fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params, distro, quiet) + if (..()) + loc = null + return 1 + else + return 0 + /obj/item/ammo_casing/caseless/a75 desc = "A .75 bullet casing." caliber = "75" - projectile_type = "/obj/item/projectile/bullet/gyro" + projectile_type = /obj/item/projectile/bullet/gyro /obj/item/ammo_casing/a40mm name = "40mm HE shell" desc = "A cased high explosive grenade that can only be activated once fired out of a grenade launcher." caliber = "40mm" icon_state = "40mmHE" - projectile_type = "/obj/item/projectile/bullet/a40mm" + projectile_type = /obj/item/projectile/bullet/a40mm -//FOAM DARTS /obj/item/ammo_casing/caseless/foam_dart name = "foam dart" desc = "It's nerf or nothing! Ages 8 and up." - projectile_type = "/obj/item/projectile/bullet/reusable/foam_dart" + projectile_type = /obj/item/projectile/bullet/reusable/foam_dart caliber = "foam_force" - icon = 'icons/obj/toyguns.dmi' + icon = 'icons/obj/guns/toy.dmi' icon_state = "foamdart" var/modified = 0 /obj/item/ammo_casing/caseless/foam_dart/update_icon() - if(modified) - icon_state = "foamdart_empty" - -/obj/item/ammo_casing/caseless/foam_dart/attackby(var/obj/item/weapon/A as obj, mob/user as mob, params) ..() - if(istype(A, /obj/item/weapon/screwdriver) && !modified) - modified = 1 - BB.damage_type = BRUTE + if (modified) icon_state = "foamdart_empty" - desc = "It's nerf or nothing! ...Although, this one doesn't look too safe." - to_chat(user, "You pop the safety cap off of [src].") - else if((istype(A, /obj/item/weapon/pen)) && modified && !BB.contents.len) + desc = "Its nerf or nothing! ... Although, this one doesn't look too safe." + if(BB) + BB.icon_state = "foamdart_empty" + else + icon_state = "foamdart" + desc = "Its nerf or nothing! Ages 8 and up." + if(BB) + BB.icon_state = "foamdart_empty" + +/obj/item/ammo_casing/caseless/foam_dart/attackby(obj/item/A, mob/user, params) + ..() + var/obj/item/projectile/bullet/reusable/foam_dart/FD = BB + if (istype(A, /obj/item/weapon/screwdriver) && !modified) + modified = 1 + FD.damage_type = BRUTE + update_icon() + else if ((istype(A, /obj/item/weapon/pen)) && modified && !FD.pen) if(!user.unEquip(A)) return - A.forceMove(BB) - BB.damage = 5 - BB.nodamage = 0 + A.loc = FD + FD.pen = A + FD.damage = 5 + FD.nodamage = 0 to_chat(user, "You insert [A] into [src].") return +/obj/item/ammo_casing/caseless/foam_dart/attack_self(mob/living/user) + var/obj/item/projectile/bullet/reusable/foam_dart/FD = BB + if(FD.pen) + FD.damage = initial(FD.damage) + FD.nodamage = initial(FD.nodamage) + user.put_in_hands(FD.pen) + to_chat(user, "You remove [FD.pen] from [src].") + FD.pen = null /obj/item/ammo_casing/caseless/foam_dart/riot name = "riot foam dart" desc = "Whose smart idea was it to use toys as crowd control? Ages 18 and up." - projectile_type = "/obj/item/projectile/bullet/reusable/foam_dart/riot" + projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/riot icon_state = "foamdart_riot" /obj/item/ammo_casing/shotgun/dart/assassination @@ -301,3 +347,8 @@ /obj/item/ammo_casing/shotgun/dart/assassination/New() ..() reagents.add_reagent("neurotoxin", 6) + +/obj/item/ammo_casing/cap + desc = "A cap for children toys." + caliber = "caps" + projectile_type = /obj/item/projectile/bullet/cap diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index eb998823b6a..894b5ac25b1 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -1,5 +1,6 @@ /obj/item/ammo_box/a357 name = "speed loader (.357)" + desc = "Designed to quickly reload revolvers." icon_state = "357" ammo_type = /obj/item/ammo_casing/a357 max_ammo = 7 @@ -7,18 +8,12 @@ /obj/item/ammo_box/c38 name = "speed loader (.38)" + desc = "Designed to quickly reload revolvers." icon_state = "38" ammo_type = /obj/item/ammo_casing/c38 max_ammo = 6 multiple_sprites = 1 -/obj/item/ammo_box/caps - name = "speed loader (caps)" - icon_state = "357" - ammo_type = /obj/item/ammo_casing/cap - max_ammo = 7 - multiple_sprites = 1 - /obj/item/ammo_box/c9mm name = "ammo box (9mm)" icon_state = "9mmbox" @@ -55,6 +50,13 @@ max_ammo = 5 multiple_sprites = 1 +/obj/item/ammo_box/n762 + name = "ammo box (7.62x38mmR)" + icon_state = "10mmbox" + origin_tech = "combat=2" + ammo_type = /obj/item/ammo_casing/n762 + max_ammo = 14 + /obj/item/ammo_box/shotgun name = "Ammunition Box (slug)" icon_state = "9mmbox" @@ -91,7 +93,7 @@ //FOAM DARTS /obj/item/ammo_box/foambox name = "ammo box (Foam Darts)" - icon = 'icons/obj/toyguns.dmi' + icon = 'icons/obj/guns/toy.dmi' icon_state = "foambox" ammo_type = /obj/item/ammo_casing/caseless/foam_dart max_ammo = 40 @@ -99,3 +101,10 @@ /obj/item/ammo_box/foambox/riot icon_state = "foambox_riot" ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot + +/obj/item/ammo_box/caps + name = "speed loader (caps)" + icon_state = "357" + ammo_type = /obj/item/ammo_casing/cap + max_ammo = 7 + multiple_sprites = 1 diff --git a/code/modules/projectiles/ammunition/energy.dm b/code/modules/projectiles/ammunition/energy.dm new file mode 100644 index 00000000000..7ed6fd4d9ed --- /dev/null +++ b/code/modules/projectiles/ammunition/energy.dm @@ -0,0 +1,247 @@ +/obj/item/ammo_casing/energy + name = "energy weapon lens" + desc = "The part of the gun that makes the laser go pew" + caliber = "energy" + projectile_type = /obj/item/projectile/energy + var/e_cost = 1000 //The amount of energy a cell needs to expend to create this shot. + var/select_name = "energy" + fire_sound = 'sound/weapons/Laser.ogg' + +/obj/item/ammo_casing/energy/laser + projectile_type = /obj/item/projectile/beam/laser + select_name = "kill" + +/obj/item/ammo_casing/energy/lasergun + projectile_type = /obj/item/projectile/beam/laser + e_cost = 830 + select_name = "kill" + +/obj/item/ammo_casing/energy/laser/hos //allows balancing of HoS and blueshit guns seperately from other energy weapons + +/obj/item/ammo_casing/energy/laser/practice + projectile_type = /obj/item/projectile/beam/practice + select_name = "practice" + +/obj/item/ammo_casing/energy/laser/scatter + projectile_type = /obj/item/projectile/beam/scatter + pellets = 5 + variance = 25 + select_name = "scatter" + +/obj/item/ammo_casing/energy/laser/heavy + projectile_type = /obj/item/projectile/beam/laser/heavylaser + select_name = "anti-vehicle" + fire_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/item/ammo_casing/energy/laser/pulse + projectile_type = /obj/item/projectile/beam/pulse + e_cost = 200 + select_name = "DESTROY" + fire_sound = 'sound/weapons/pulse.ogg' + +/obj/item/ammo_casing/energy/laser/scatter/pulse + projectile_type = /obj/item/projectile/beam/pulse + e_cost = 2000 + select_name = "ANNIHILATE" + fire_sound = 'sound/weapons/pulse.ogg' + +/obj/item/ammo_casing/energy/laser/bluetag + projectile_type = /obj/item/projectile/beam/lasertag/bluetag + select_name = "bluetag" + +/obj/item/ammo_casing/energy/laser/redtag + projectile_type = /obj/item/projectile/beam/lasertag/redtag + select_name = "redtag" + +/obj/item/ammo_casing/energy/xray + projectile_type = /obj/item/projectile/beam/xray + e_cost = 500 + fire_sound = 'sound/weapons/laser3.ogg' + +/obj/item/ammo_casing/energy/immolator + projectile_type = /obj/item/projectile/beam/immolator + fire_sound = 'sound/weapons/laser3.ogg' + e_cost = 1250 + +/obj/item/ammo_casing/energy/electrode + projectile_type = /obj/item/projectile/energy/electrode + select_name = "stun" + fire_sound = 'sound/weapons/taser.ogg' + e_cost = 2000 + delay = 15 + +/obj/item/ammo_casing/energy/electrode/gun + fire_sound = 'sound/weapons/gunshot.ogg' + e_cost = 1000 + +/obj/item/ammo_casing/energy/electrode/hos //allows balancing of HoS and blueshit guns seperately from other energy weapons + +/obj/item/ammo_casing/energy/ion + projectile_type = /obj/item/projectile/ion + select_name = "ion" + fire_sound = 'sound/weapons/IonRifle.ogg' + +/obj/item/ammo_casing/energy/declone + projectile_type = /obj/item/projectile/energy/declone + select_name = "declone" + fire_sound = 'sound/weapons/pulse3.ogg' + +/obj/item/ammo_casing/energy/mindflayer + projectile_type = /obj/item/projectile/beam/mindflayer + select_name = "MINDFUCK" + fire_sound = 'sound/weapons/Laser.ogg' + +/obj/item/ammo_casing/energy/flora + fire_sound = 'sound/effects/stealthoff.ogg' + +/obj/item/ammo_casing/energy/flora/yield + projectile_type = /obj/item/projectile/energy/florayield + select_name = "yield" + +/obj/item/ammo_casing/energy/flora/mut + projectile_type = /obj/item/projectile/energy/floramut + select_name = "mutation" + +/obj/item/ammo_casing/energy/temp + projectile_type = /obj/item/projectile/temp + e_cost = 100 + fire_sound = 'sound/weapons/pulse3.ogg' + +/obj/item/ammo_casing/energy/temp/New() + ..() + 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 + select_name = "goddamn meteor" + +/obj/item/ammo_casing/energy/kinetic + projectile_type = /obj/item/projectile/kinetic + select_name = "kinetic" + e_cost = 5000 + fire_sound = 'sound/weapons/Kenetic_accel.ogg' // fine spelling there chap + +/obj/item/ammo_casing/energy/kinetic/super + projectile_type = /obj/item/projectile/kinetic/super + +/obj/item/ammo_casing/energy/kinetic/hyper + projectile_type = /obj/item/projectile/kinetic/hyper + +/obj/item/ammo_casing/energy/disabler + projectile_type = /obj/item/projectile/beam/disabler + select_name = "disable" + e_cost = 500 + fire_sound = "sound/weapons/taser2.ogg" + +/obj/item/ammo_casing/energy/plasma + projectile_type = /obj/item/projectile/plasma + select_name = "plasma burst" + fire_sound = 'sound/weapons/plasma_cutter.ogg' + delay = 15 + e_cost = 250 + +/obj/item/ammo_casing/energy/plasma/adv + projectile_type = /obj/item/projectile/plasma/adv + delay = 10 + e_cost = 100 + +/obj/item/ammo_casing/energy/wormhole + projectile_type = /obj/item/projectile/beam/wormhole + e_cost = 0 + fire_sound = "sound/weapons/pulse3.ogg" + var/obj/item/weapon/gun/energy/wormhole_projector/gun = null + select_name = "blue" + +/obj/item/ammo_casing/energy/wormhole/New(var/obj/item/weapon/gun/energy/wormhole_projector/wh) + gun = wh + +/obj/item/ammo_casing/energy/wormhole/orange + projectile_type = /obj/item/projectile/beam/wormhole/orange + select_name = "orange" + +/obj/item/ammo_casing/energy/bolt + projectile_type = /obj/item/projectile/energy/bolt + select_name = "bolt" + e_cost = 5000 + fire_sound = 'sound/weapons/Genhit.ogg' + +/obj/item/ammo_casing/energy/bolt/large + projectile_type = /obj/item/projectile/energy/bolt/large + select_name = "heavy bolt" + +/obj/item/ammo_casing/energy/dart + projectile_type = /obj/item/projectile/energy/dart + fire_sound = 'sound/weapons/Genhit.ogg' + e_cost = 5000 + select_name = "toxic dart" + +/obj/item/ammo_casing/energy/instakill + projectile_type = /obj/item/projectile/beam/instakill + e_cost = 0 + select_name = "DESTROY" + +/obj/item/ammo_casing/energy/instakill/blue + projectile_type = /obj/item/projectile/beam/instakill/blue + +/obj/item/ammo_casing/energy/instakill/red + projectile_type = /obj/item/projectile/beam/instakill/red + +/obj/item/ammo_casing/energy/plasma + projectile_type = /obj/item/projectile/plasma + select_name = "plasma burst" + fire_sound = 'sound/weapons/pulse.ogg' + +/obj/item/ammo_casing/energy/plasma/adv + projectile_type = /obj/item/projectile/plasma/adv + +/obj/item/ammo_casing/energy/shock_revolver + fire_sound = 'sound/magic/lightningbolt.ogg' + e_cost = 2000 + select_name = "lightning beam" + projectile_type = /obj/item/projectile/energy/shock_revolver + +/obj/item/ammo_casing/energy/toxplasma + projectile_type = /obj/item/projectile/energy/toxplasma + fire_sound = "sound/weapons/taser2.ogg" + select_name = "plasma dart" + +/obj/item/ammo_casing/energy/clown + projectile_type = /obj/item/projectile/clown + fire_sound = 'sound/weapons/Gunshot_smg.ogg' + select_name = "clown" + +/obj/item/ammo_casing/energy/sniper + projectile_type = /obj/item/projectile/beam/sniper + fire_sound = 'sound/weapons/marauder.ogg' + delay = 50 + select_name = "snipe" + +/obj/item/ammo_casing/energy/teleport + projectile_type = /obj/item/projectile/energy/teleport + fire_sound = 'sound/weapons/wave.ogg' + e_cost = 1250 + select_name = "teleport beam" + var/teleport_target + +/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) + ..() diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 32c3eeaa37c..c77dcc07595 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -1,113 +1,169 @@ ////////////////INTERNAL MAGAZINES////////////////////// +/obj/item/ammo_box/magazine/internal + desc = "Oh god, this shouldn't be here" + +//internals magazines are accessible, so replace spent ammo if full when trying to put a live one in +/obj/item/ammo_box/magazine/internal/give_round(obj/item/ammo_casing/R) + return ..(R,1) + +// Revolver internal mags /obj/item/ammo_box/magazine/internal/cylinder name = "revolver cylinder" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/a357" + ammo_type = /obj/item/ammo_casing/a357 caliber = "357" max_ammo = 7 -/obj/item/ammo_box/magazine/internal/cylinder/ammo_count(var/countempties = 1) - if (!countempties) - var/boolets = 0 - for (var/i = 1, i <= stored_ammo.len, i++) - var/obj/item/ammo_casing/bullet = stored_ammo[i] - if (bullet.BB) - boolets++ - return boolets - else - return stored_ammo.len +/obj/item/ammo_box/magazine/internal/cylinder/ammo_count(countempties = 1) + var/boolets = 0 + for(var/obj/item/ammo_casing/bullet in stored_ammo) + if(bullet && (bullet.BB || countempties)) + boolets++ + return boolets -/obj/item/ammo_box/magazine/internal/cylinder/rus357 - name = "russian revolver cylinder" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/a357" - caliber = "357" - max_ammo = 6 - multiload = 0 +/obj/item/ammo_box/magazine/internal/cylinder/get_round(keep = 0) + rotate() -/obj/item/ammo_box/magazine/internal/cylinder/rus357/New() - stored_ammo += new ammo_type(src) + var/b = stored_ammo[1] + if(!keep) + stored_ammo[1] = null + + return b + +/obj/item/ammo_box/magazine/internal/cylinder/proc/rotate() + var/b = stored_ammo[1] + stored_ammo.Cut(1,2) + stored_ammo.Insert(0, b) + +/obj/item/ammo_box/magazine/internal/cylinder/proc/spin() + for(var/i in 1 to rand(0, max_ammo*2)) + rotate() + +/obj/item/ammo_box/magazine/internal/cylinder/give_round(obj/item/ammo_casing/R, replace_spent = 0) + if(!R || (caliber && R.caliber != caliber) || (!caliber && R.type != ammo_type)) + return 0 + + for(var/i in 1 to stored_ammo.len) + var/obj/item/ammo_casing/bullet = stored_ammo[i] + if(!bullet || !bullet.BB) // found a spent ammo + stored_ammo[i] = R + R.loc = src + + if(bullet) + bullet.loc = get_turf(loc) + return 1 + + return 0 /obj/item/ammo_box/magazine/internal/cylinder/rev38 - name = "d-tiv revolver cylinder" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/c38" + name = "detective revolver cylinder" + ammo_type = /obj/item/ammo_casing/c38 caliber = "38" max_ammo = 6 +/obj/item/ammo_box/magazine/internal/cylinder/rev762 + name = "nagant revolver cylinder" + ammo_type = /obj/item/ammo_casing/n762 + caliber = "n762" + max_ammo = 7 + /obj/item/ammo_box/magazine/internal/cylinder/cap name = "cap gun revolver cylinder" desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/cap" + ammo_type = /obj/item/ammo_casing/cap caliber = "cap" max_ammo = 7 +// Shotgun internal mags /obj/item/ammo_box/magazine/internal/shot name = "shotgun internal magazine" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" + ammo_type = /obj/item/ammo_casing/shotgun/beanbag caliber = "shotgun" max_ammo = 4 multiload = 0 -/obj/item/ammo_box/magazine/internal/shotcom +/obj/item/ammo_box/magazine/internal/shot/ammo_count(countempties = 1) + if (!countempties) + var/boolets = 0 + for(var/obj/item/ammo_casing/bullet in stored_ammo) + if(bullet.BB) + boolets++ + return boolets + else + return ..() + +/obj/item/ammo_box/magazine/internal/shot/tube + name = "dual feed shotgun internal tube" + ammo_type = /obj/item/ammo_casing/shotgun/rubbershot + max_ammo = 4 + +/obj/item/ammo_box/magazine/internal/shot/lethal + ammo_type = /obj/item/ammo_casing/shotgun/buckshot + +/obj/item/ammo_box/magazine/internal/shot/com name = "combat shotgun internal magazine" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/shotgun/buckshot" - caliber = "shotgun" + ammo_type = /obj/item/ammo_casing/shotgun/buckshot max_ammo = 6 - multiload = 0 -/obj/item/ammo_box/magazine/internal/cylinder/dualshot +/obj/item/ammo_box/magazine/internal/shot/dual name = "double-barrel shotgun internal magazine" - desc = "This doesn't even exist" - ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" - caliber = "shotgun" max_ammo = 2 - multiload = 0 -/obj/item/ammo_box/magazine/internal/cylinder/improvised +/obj/item/ammo_box/magazine/internal/shot/improvised name = "improvised shotgun internal magazine" - desc = "This doesn't even exist" - ammo_type = "/obj/item/ammo_casing/shotgun/improvised" - caliber = "shotgun" + ammo_type = /obj/item/ammo_casing/shotgun/improvised max_ammo = 1 - multiload = 0 -/obj/item/ammo_box/magazine/internal/shotriot +/obj/item/ammo_box/magazine/internal/shot/riot name = "riot shotgun internal magazine" - desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/shotgun/rubbershot" - caliber = "shotgun" + ammo_type = /obj/item/ammo_casing/shotgun/rubbershot max_ammo = 6 - multiload = 0 -/obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher +/obj/item/ammo_box/magazine/internal/grenadelauncher name = "grenade launcher internal magazine" - ammo_type = "/obj/item/ammo_casing/a40mm" + ammo_type = /obj/item/ammo_casing/a40mm caliber = "40mm" max_ammo = 1 /obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher/multi - ammo_type = "/obj/item/ammo_casing/a40mm" + ammo_type = /obj/item/ammo_casing/a40mm max_ammo = 6 +/obj/item/ammo_box/magazine/internal/speargun + name = "speargun internal magazine" + ammo_type = /obj/item/ammo_casing/caseless/magspear + caliber = "speargun" + max_ammo = 1 + +/obj/item/ammo_box/magazine/internal/rus357 + name = "russian revolver cylinder" + ammo_type = /obj/item/ammo_casing/a357 + caliber = "357" + max_ammo = 6 + multiload = 0 + +/obj/item/ammo_box/magazine/internal/rus357/New() + stored_ammo += new ammo_type(src) + /obj/item/ammo_box/magazine/internal/boltaction name = "bolt action rifle internal magazine" desc = "Oh god, this shouldn't be here" - ammo_type = "/obj/item/ammo_casing/a762" + ammo_type = /obj/item/ammo_casing/a762 caliber = "a762" max_ammo = 5 multiload = 1 +/obj/item/ammo_box/magazine/internal/boltaction/enchanted + max_ammo =1 + ammo_type = /obj/item/ammo_casing/a762/enchanted + /obj/item/ammo_box/magazine/internal/shot/toy - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart caliber = "foam_force" max_ammo = 4 /obj/item/ammo_box/magazine/internal/shot/toy/crossbow - max_ammo = 5 + max_ammo = 5 /obj/item/ammo_box/magazine/internal/shot/toy/tommygun max_ammo = 10 @@ -116,17 +172,18 @@ /obj/item/ammo_box/magazine/m10mm name = "pistol magazine (10mm)" + desc = "A gun magazine." icon_state = "9x19p" origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/c10mm" + ammo_type = /obj/item/ammo_casing/c10mm caliber = "10mm" max_ammo = 8 multiple_sprites = 2 /obj/item/ammo_box/magazine/m45 name = "handgun magazine (.45)" - icon_state = "45" - ammo_type = "/obj/item/ammo_casing/c45" + icon_state = "45-8" + ammo_type = /obj/item/ammo_casing/c45 caliber = ".45" max_ammo = 8 @@ -137,7 +194,7 @@ /obj/item/ammo_box/magazine/wt550m9 name = "wt550 magazine (4.6x30mm)" icon_state = "46x30mmt-20" - ammo_type = "/obj/item/ammo_casing/c46x30mm" + ammo_type = /obj/item/ammo_casing/c46x30mm caliber = "4.6x30mm" max_ammo = 20 @@ -147,20 +204,20 @@ /obj/item/ammo_box/magazine/wt550m9/wtap name = "wt550 magazine (Armour Piercing 4.6x30mm)" - ammo_type = "/obj/item/ammo_casing/c46x30mmap" + ammo_type = /obj/item/ammo_casing/c46x30mmap /obj/item/ammo_box/magazine/wt550m9/wttx name = "wt550 magazine (Toxin Tipped 4.6x30mm)" - ammo_type = "/obj/item/ammo_casing/c46x30mmtox" + ammo_type = /obj/item/ammo_casing/c46x30mmtox /obj/item/ammo_box/magazine/wt550m9/wtic name = "wt550 magazine (Incindiary 4.6x30mm)" - ammo_type = "/obj/item/ammo_casing/c46x30mminc" + ammo_type = /obj/item/ammo_casing/c46x30mminc /obj/item/ammo_box/magazine/uzim9mm name = "uzi magazine (9mm)" icon_state = "uzi9mm-32" - ammo_type = "/obj/item/ammo_casing/c9mm" + ammo_type = /obj/item/ammo_casing/c9mm caliber = "9mm" max_ammo = 32 @@ -171,35 +228,46 @@ /obj/item/ammo_box/magazine/smgm9mm name = "SMG magazine (9mm)" icon_state = "smg9mm" - ammo_type = "/obj/item/ammo_casing/c9mm" + ammo_type = /obj/item/ammo_casing/c9mm caliber = "9mm" - max_ammo = 30 + max_ammo = 21 materials = list(MAT_METAL = 2000) /obj/item/ammo_box/magazine/smgm9mm/ap name = "SMG magazine (Armour Piercing 9mm)" - ammo_type = "/obj/item/ammo_casing/c9mmap" + ammo_type = /obj/item/ammo_casing/c9mmap materials = list(MAT_METAL = 3000) /obj/item/ammo_box/magazine/smgm9mm/toxin name = "SMG magazine (Toxin Tipped 9mm)" - ammo_type = "/obj/item/ammo_casing/c9mmtox" + ammo_type = /obj/item/ammo_casing/c9mmtox materials = list(MAT_METAL = 3000) /obj/item/ammo_box/magazine/smgm9mm/fire name = "SMG Magazine (Incendiary 9mm)" - ammo_type = "/obj/item/ammo_casing/c9mminc" + ammo_type = /obj/item/ammo_casing/c9mminc materials = list(MAT_METAL = 3000) /obj/item/ammo_box/magazine/smgm9mm/update_icon() ..() icon_state = "[initial(icon_state)]-[round(ammo_count(),6)]" +/obj/item/ammo_box/magazine/pistolm9mm + name = "pistol magazine (9mm)" + icon_state = "9x19p-8" + ammo_type = /obj/item/ammo_casing/c9mm + caliber = "9mm" + max_ammo = 15 + +/obj/item/ammo_box/magazine/pistolm9mm/update_icon() + ..() + icon_state = "9x19p-[ammo_count() ? "8" : "0"]" + /obj/item/ammo_box/magazine/smgm45 name = "SMG magazine (.45)" icon_state = "c20r45" origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/c45" + ammo_type = /obj/item/ammo_casing/c45 caliber = ".45" max_ammo = 20 @@ -210,7 +278,7 @@ /obj/item/ammo_box/magazine/tommygunm45 name = "drum magazine (.45)" icon_state = "drum45" - ammo_type = "/obj/item/ammo_casing/c45" + ammo_type = /obj/item/ammo_casing/c45 caliber = ".45" max_ammo = 50 @@ -218,7 +286,7 @@ name = "handgun magazine (.50ae)" icon_state = "50ae" origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/a50" + ammo_type = /obj/item/ammo_casing/a50 caliber = ".50" max_ammo = 7 multiple_sprites = 1 @@ -226,7 +294,7 @@ /obj/item/ammo_box/magazine/m75 name = "specialized magazine (.75)" icon_state = "75" - ammo_type = "/obj/item/ammo_casing/caseless/a75" + ammo_type = /obj/item/ammo_casing/caseless/a75 caliber = "75" multiple_sprites = 2 max_ammo = 8 @@ -235,50 +303,16 @@ name = "toploader magazine (5.56mm)" icon_state = "5.56m" origin_tech = "combat=5;syndicate=1" - ammo_type = "/obj/item/ammo_casing/a556" + ammo_type = /obj/item/ammo_casing/a556 caliber = "a556" max_ammo = 30 multiple_sprites = 2 -/obj/item/ammo_box/magazine/m762 - name = "box magazine (7.62mm)" - icon_state = "a762" - origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/a762" - caliber = "a762" - max_ammo = 50 - -/obj/item/ammo_box/magazine/m762/update_icon() - ..() - icon_state = "[initial(icon_state)]-[round(ammo_count(),10)]" - -/obj/item/ammo_box/magazine/m762/buckshot - name = "box magazine (buckshot)" - icon_state = "b762" - caliber = "shotgun" - ammo_type ="/obj/item/ammo_casing/shotgun/buckshot" - max_ammo = 300 // Bluespace! - -/obj/item/ammo_box/magazine/m762/buckshot/update_icon() - ..() - icon_state = "[initial(icon_state)]-[round(ammo_count(),60)]" - -/obj/item/ammo_box/magazine/m762/he // I am not a good person. - name = "box magazine (40mm high explosive)" - icon_state = "g762" - caliber = "40mm" - ammo_type ="/obj/item/ammo_casing/a40mm" - max_ammo = 25 - -/obj/item/ammo_box/magazine/m762/he/update_icon() - ..() - icon_state = "[initial(icon_state)]-[round(ammo_count(),5)]" - - /obj/item/ammo_box/magazine/m12g name = "shotgun magazine (12g slugs)" + desc = "A drum magazine." icon_state = "m12gb" - ammo_type = "/obj/item/ammo_casing/shotgun" + ammo_type = /obj/item/ammo_casing/shotgun origin_tech = "combat=3;syndicate=1" caliber = "shotgun" max_ammo = 8 @@ -290,36 +324,45 @@ /obj/item/ammo_box/magazine/m12g/buckshot name = "shotgun magazine (12g buckshot slugs)" icon_state = "m12gb" - ammo_type = "/obj/item/ammo_casing/shotgun/buckshot" + ammo_type = /obj/item/ammo_casing/shotgun/buckshot /obj/item/ammo_box/magazine/m12g/stun name = "shotgun magazine (12g taser slugs)" icon_state = "m12gs" - ammo_type = "/obj/item/ammo_casing/shotgun/stunslug" + ammo_type = /obj/item/ammo_casing/shotgun/stunslug /obj/item/ammo_box/magazine/m12g/dragon name = "shotgun magazine (12g dragon's breath)" icon_state = "m12gf" - ammo_type = "/obj/item/ammo_casing/shotgun/incendiary/dragonsbreath" + ammo_type = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath + +/obj/item/ammo_box/magazine/m12g/bioterror + name = "shotgun magazine (12g bioterror)" + icon_state = "m12gt" + ammo_type = /obj/item/ammo_casing/shotgun/dart/bioterror + +/obj/item/ammo_box/magazine/m12g/breach + name = "shotgun magazine (12g breacher slugs)" + icon_state = "m12gbc" + ammo_type = /obj/item/ammo_casing/shotgun/breaching -//FOAM DARTS /obj/item/ammo_box/magazine/toy name = "foam force META magazine" - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart caliber = "foam_force" /obj/item/ammo_box/magazine/toy/smg name = "foam force SMG magazine" icon_state = "smg9mm-30" - max_ammo = 30 + max_ammo = 20 /obj/item/ammo_box/magazine/toy/smg/update_icon() ..() - icon_state = "smg9mm-[round(ammo_count(),6)]" + icon_state = "smg9mm-[round(ammo_count(),5)]" /obj/item/ammo_box/magazine/toy/smg/riot - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart/riot" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot /obj/item/ammo_box/magazine/toy/pistol name = "foam force pistol magazine" @@ -328,11 +371,11 @@ multiple_sprites = 2 /obj/item/ammo_box/magazine/toy/pistol/riot - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart/riot" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot /obj/item/ammo_box/magazine/toy/smgm45 name = "donksoft SMG magazine" - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart/riot" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot max_ammo = 20 /obj/item/ammo_box/magazine/toy/smgm45/update_icon() @@ -341,7 +384,7 @@ /obj/item/ammo_box/magazine/toy/m762 name = "donksoft box magazine" - ammo_type = "/obj/item/ammo_casing/caseless/foam_dart/riot" + ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot max_ammo = 50 /obj/item/ammo_box/magazine/toy/m762/update_icon() diff --git a/code/modules/projectiles/ammunition/special.dm b/code/modules/projectiles/ammunition/special.dm new file mode 100644 index 00000000000..d17d65e9fc8 --- /dev/null +++ b/code/modules/projectiles/ammunition/special.dm @@ -0,0 +1,49 @@ +/obj/item/ammo_casing/magic + name = "magic casing" + desc = "I didn't even know magic needed ammo..." + projectile_type = /obj/item/projectile/magic + +/obj/item/ammo_casing/magic/change + projectile_type = /obj/item/projectile/magic/change + +/obj/item/ammo_casing/magic/animate + projectile_type = /obj/item/projectile/magic/animate + +/obj/item/ammo_casing/magic/heal + projectile_type = /obj/item/projectile/magic/resurrection + +/obj/item/ammo_casing/magic/death + projectile_type = /obj/item/projectile/magic/death + +/obj/item/ammo_casing/magic/teleport + projectile_type = /obj/item/projectile/magic/teleport + +/obj/item/ammo_casing/magic/door + projectile_type = /obj/item/projectile/magic/door + +/obj/item/ammo_casing/magic/fireball + projectile_type = /obj/item/projectile/magic/fireball + +/obj/item/ammo_casing/magic/chaos + projectile_type = /obj/item/projectile/magic + +/obj/item/ammo_casing/magic/chaos/newshot() + projectile_type = pick(typesof(/obj/item/projectile/magic)) + ..() + +/obj/item/ammo_casing/magic/honk + projectile_type = /obj/item/projectile/bullet/honker + +/obj/item/ammo_casing/forcebolt + projectile_type = /obj/item/projectile/forcebolt + +/obj/item/ammo_casing/syringegun + name = "syringe gun spring" + desc = "A high-power spring that throws syringes." + projectile_type = null + +/obj/item/ammo_casing/energy/c3dbullet + projectile_type = /obj/item/projectile/bullet/midbullet3 + select_name = "spraydown" + fire_sound = 'sound/weapons/gunshot_smg.ogg' + e_cost = 200 diff --git a/code/modules/projectiles/firing.dm b/code/modules/projectiles/firing.dm new file mode 100644 index 00000000000..2a75004f223 --- /dev/null +++ b/code/modules/projectiles/firing.dm @@ -0,0 +1,95 @@ +/obj/item/ammo_casing/proc/fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params, distro, quiet, zone_override = "", spread) + distro += variance + for (var/i = max(1, pellets), i > 0, i--) + var/targloc = get_turf(target) + ready_proj(target, user, quiet, zone_override) + if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now... + if(randomspread) + spread = round((rand() - 0.5) * distro) + else //Smart spread + spread = round((i / pellets - 0.5) * distro) + if(!throw_proj(target, targloc, user, params, spread)) + return 0 + if(i > 1) + newshot() + if(click_cooldown_override) + user.changeNext_move(click_cooldown_override) + else + user.changeNext_move(CLICK_CD_RANGE) + user.newtonian_move(get_dir(target, user)) + update_icon() + return 1 + +/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") + if (!BB) + return + BB.original = target + BB.firer = user + if (zone_override) + BB.def_zone = zone_override + else + BB.def_zone = user.zone_sel.selecting + BB.suppressed = quiet + + if(reagents && BB.reagents) + reagents.trans_to(BB, reagents.total_volume) //For chemical darts/bullets + qdel(reagents) + +/obj/item/ammo_casing/proc/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread) + var/turf/curloc = get_turf(user) + if (!istype(targloc) || !istype(curloc) || !BB) + return 0 + BB.ammo_casing = src + if(targloc == curloc) + if(target) //if the target is right on our location we go straight to bullet_act() + target.bullet_act(BB, BB.def_zone) + qdel(BB) + BB = null + return 1 + + BB.preparePixelProjectile(target, targloc, user, params, spread) + if(BB) + BB.fire() + BB = null + return 1 + +/obj/item/ammo_casing/proc/spread(turf/target, turf/current, distro) + var/dx = abs(target.x - current.x) + var/dy = abs(target.y - current.y) + return locate(target.x + round(gaussian(0, distro) * (dy+2)/8, 1), target.y + round(gaussian(0, distro) * (dx+2)/8, 1), target.z) + +/obj/item/projectile/proc/preparePixelProjectile(atom/target, var/turf/targloc, mob/living/user, params, spread) + var/turf/curloc = get_turf(user) + loc = get_turf(user) + starting = get_turf(user) + current = curloc + yo = targloc.y - curloc.y + xo = targloc.x - curloc.x + + if(params) + var/list/mouse_control = params2list(params) + if(mouse_control["icon-x"]) + p_x = text2num(mouse_control["icon-x"]) + if(mouse_control["icon-y"]) + p_y = text2num(mouse_control["icon-y"]) + if(mouse_control["screen-loc"]) + //Split screen-loc up into X+Pixel_X and Y+Pixel_Y + var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",") + + //Split X+Pixel_X up into list(X, Pixel_X) + var/list/screen_loc_X = splittext(screen_loc_params[1],":") + + //Split Y+Pixel_Y up into list(Y, Pixel_Y) + var/list/screen_loc_Y = splittext(screen_loc_params[2],":") + var/x = text2num(screen_loc_X[1]) * world.icon_size + text2num(screen_loc_X[2]) - world.icon_size + (user.client ? user.client.pixel_x : 0) + var/y = text2num(screen_loc_Y[1]) * world.icon_size + text2num(screen_loc_Y[2]) - world.icon_size + (user.client ? user.client.pixel_y : 0) + + //Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average. + var/screenview = (user.client.view * 2 + 1) * world.icon_size //Refer to http://www.byond.com/docs/ref/info.html#/client/var/view for mad maths + + var/ox = round(screenview/2) //"origin" x + var/oy = round(screenview/2) //"origin" y + var/angle = Atan2(y - oy, x - ox) + Angle = angle + if(spread) + Angle += spread diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index cb4f21d2497..74a4bcd8ba6 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -1,54 +1,59 @@ - #define SAWN_INTACT 0 - #define SAWN_OFF 1 - #define SAWN_SAWING -1 - /obj/item/weapon/gun name = "gun" - desc = "Its a gun. It's pretty terrible, though." - icon = 'icons/obj/gun.dmi' + desc = "It's a gun. It's pretty terrible, though." + icon = 'icons/obj/guns/projectile.dmi' icon_state = "detective" item_state = "gun" - lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/guns_righthand.dmi' flags = CONDUCT slot_flags = SLOT_BELT materials = list(MAT_METAL=2000) - w_class = 3.0 + w_class = 3 throwforce = 5 - throw_speed = 4 + throw_speed = 3 throw_range = 5 - force = 5.0 + force = 5 origin_tech = "combat=1" needs_permit = 1 attack_verb = list("struck", "hit", "bashed") - var/fire_sound = 'sound/weapons/Gunshot.ogg' - var/obj/item/projectile/in_chamber = null - var/silenced = 0 - var/ghettomodded = 0 - var/recoil = 0 + var/fire_sound = "gunshot" + var/fire_sound_text = "gunshot" //the fire sound that shows in chat messages: laser blast, gunshot, etc. + var/suppressed = 0 //whether or not a message is displayed when fired var/can_suppress = 0 var/can_unsuppress = 1 + var/recoil = 0 //boom boom shake the room var/clumsy_check = 1 - var/sawn_desc = null + var/obj/item/ammo_casing/chambered = null + var/trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers + var/sawn_desc = null //description change if weapon is sawn-off var/sawn_state = SAWN_INTACT - var/obj/item/ammo_casing/chambered = null // The round (not bullet) that is in the chamber. THIS MISPLACED ITEM BROUGHT TO YOU BY HACKY BUCKSHOT. - var/tmp/list/mob/living/target //List of who yer targeting. - var/tmp/lock_time = -100 - var/tmp/mouthshoot = 0 ///To stop people from suiciding twice... >.> - var/automatic = 0 //Used to determine if you can target multiple people. - var/tmp/mob/living/last_moved_mob //Used to fire faster at more than one person. - var/tmp/told_cant_shoot = 0 //So that it doesn't spam them with the fact they cannot hit them. - var/firerate = 1 // 0 for one bullet after tarrget moves and aim is lowered, - //1 for keep shooting until aim is lowered - var/fire_delay = 0 - var/last_fired = 0 + var/burst_size = 1 //how large a burst is + var/fire_delay = 0 //rate of fire for burst firing and semi auto + var/firing_burst = 0 //Prevent the weapon from firing again while already firing + var/semicd = 0 //cooldown handler + var/weapon_weight = WEAPON_LIGHT + var/list/restricted_species + + var/spread = 0 + var/randomspread = 1 + + var/unique_rename = 0 //allows renaming with a pen + var/unique_reskin = 0 //allows one-time reskinning + var/current_skin = null //the skin choice if we had a reskin + var/list/options = list() + + lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/guns_righthand.dmi' + var/obj/item/device/flashlight/F = null var/can_flashlight = 0 - var/heavy_weapon = 0 - var/randomspread = 0 - var/burst_size = 1 + var/list/upgrades = list() + + var/ammo_x_offset = 0 //used for positioning ammo count overlay on sprite + var/ammo_y_offset = 0 + var/flight_x_offset = 0 + var/flight_y_offset = 0 //Zooming var/zoomable = FALSE //whether the gun generates a Zoom action on creation @@ -56,312 +61,200 @@ var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect) var/datum/action/toggle_scope_zoom/azoom - proc/ready_to_fire() - if(world.time >= last_fired + fire_delay) - last_fired = world.time - return 1 - else - return 0 - - proc/process_chambered() - return 0 - - - proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver. - if(!M.IsAdvancedToolUser()) - return 0 - return 1 - - - proc/shoot_with_empty_chamber(mob/living/user as mob|obj) - to_chat(user, "*click*") - playsound(user, 'sound/weapons/emptyclick.ogg', 40, 1) - return - - emp_act(severity) - for(var/obj/O in contents) - O.emp_act(severity) - - proc/prepare_shot(var/obj/item/projectile/proj) //Transfer properties from the gun to the bullet - proj.shot_from = src - proj.silenced = silenced - return - /obj/item/weapon/gun/New() + ..() + if(F) + verbs += /obj/item/weapon/gun/proc/toggle_gunlight build_zooming() + +/obj/item/weapon/gun/examine(mob/user) ..() + if(unique_reskin && !current_skin) + to_chat(user, "Alt-click it to reskin it.") + if(unique_rename) + to_chat(user, "Use a pen on it to rename it.") -/obj/item/weapon/gun/pickup(mob/user) +/obj/item/weapon/gun/proc/process_chamber() + return 0 - if(azoom) - azoom.Grant(user) - ..() - -/obj/item/weapon/gun/dropped(mob/user) - - zoom(user,FALSE) - if(azoom) - azoom.Remove(user) - ..() - -/obj/item/weapon/gun/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params) - if(flag) return //we're placing gun on a table or in backpack - if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this? - Fire(A,user,params) //Otherwise, fire normally. - -/obj/item/weapon/gun/proc/isHandgun() +//check if there's enough ammo/energy/whatever to shoot one time +//i.e if clicking would make it shoot +/obj/item/weapon/gun/proc/can_shoot() return 1 -/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this +/obj/item/weapon/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) + to_chat(user, "*click*") + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + +/obj/item/weapon/gun/proc/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1) + if(recoil) + shake_camera(user, recoil + 1, recoil) + + if(suppressed) + playsound(user, fire_sound, 10, 1) + else + playsound(user, fire_sound, 50, 1) + if(!message) + return + if(pointblank) + user.visible_message("[user] fires [src] point blank at [pbtarget]!", "You fire [src] point blank at [pbtarget]!", "You hear \a [fire_sound_text]!") + else + user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear \a [fire_sound_text]!") + + if(weapon_weight >= WEAPON_MEDIUM) + if(user.get_inactive_hand()) + if(prob(15)) + if(user.drop_item()) + user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!") + +/obj/item/weapon/gun/emp_act(severity) + for(var/obj/O in contents) + O.emp_act(severity) + +/obj/item/weapon/gun/afterattack(atom/target, mob/living/user, flag, params) + if(firing_burst) + return + if(flag) //It's adjacent, is the user, or is on the user's person + if(target in user.contents) //can't shoot stuff inside us. + return + if(!ismob(target) || user.a_intent == "harm") //melee attack + return + if(target == user && user.zone_sel.selecting != "mouth") //so we can't shoot ourselves (unless mouth selected) + return + + if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. + var/mob/living/L = user + if(!can_trigger_gun(L)) + return + + if(!can_shoot()) //Just because you can pull the trigger doesn't mean it can't shoot. + shoot_with_empty_chamber(user) + return + + if(flag) + if(user.zone_sel.selecting == "mouth") + handle_suicide(user, target, params) + return + + //Exclude lasertag guns from the CLUMSY check. if(clumsy_check) - if(istype(user, /mob/living)) - var/mob/living/M = user - if ((CLUMSY in M.mutations) && prob(50)) - to_chat(M, "[src] blows up in your face.") - M.take_organ_damage(0,20) - M.drop_item() - qdel(src) + if(istype(user)) + if (user.disabilities & CLUMSY && prob(40)) + to_chat(user, "You shoot yourself in the foot with \the [src]!") + var/shot_leg = pick("l_foot", "r_foot") + process_fire(user, user, 0, params, zone_override = shot_leg) + user.drop_item() return - if (!user.IsAdvancedToolUser() || istype(user, /mob/living/simple_animal/diona)) - to_chat(user, "You don't have the dexterity to do this!") + if(weapon_weight == WEAPON_HEAVY && user.get_inactive_hand()) + to_chat(user, "You need both hands free to fire \the [src]!") return - if(istype(user, /mob/living)) - var/mob/living/M = user - if (HULK in M.mutations) - to_chat(M, "Your meaty finger is much too large for the trigger guard!") - return - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.species.flags & NOGUNS) - to_chat(user, "Your fingers don't fit in the trigger guard!") - return - if(H.martial_art && H.martial_art.name == "The Sleeping Carp") //great dishonor to famiry - to_chat(user, "Use of ranged weaponry would bring dishonor to the clan.") - return + process_fire(target,user,1,params) + +/obj/item/weapon/gun/proc/can_trigger_gun(var/mob/living/user) + if(!user.can_use_guns(src)) + return 0 + if(restricted_species && restricted_species.len && !(user.get_species() in restricted_species)) + to_chat(user, "[src] is incompatible with your biology!") + return 0 + return 1 + +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) add_fingerprint(user) - if(!special_check(user)) + if(semicd) return - if (!ready_to_fire()) - if (world.time % 3) //to prevent spam - to_chat(user, "[src] is not ready to fire again!") - return - - if(heavy_weapon) + if(weapon_weight) if(user.get_inactive_hand()) recoil = 4 //one-handed kick else recoil = initial(recoil) - if (istype(in_chamber, /obj/item/projectile/bullet/blank)) // A hacky way of making blank shotgun shells work again. Honk. - in_chamber.delete() - in_chamber = null - return - - user.changeNext_move(CLICK_CD_RANGE) - - var/spread = 0 - var/turf/targloc = get_turf(target) - for(var/f = 1 to burst_size) - if(!process_chambered()) //CHECK - return click_empty(user) - - if(chambered) - for (var/i = max(1, chambered.pellets), i > 0, i--) //Previous way of doing it fucked up math for spreading. This way, even the first projectile is part of the spread code. - if(i != max(1, chambered.pellets)) //Have we fired the initial chambered bullet yet? - in_chamber = new chambered.projectile_type() - ready_projectile(target, user) - prepare_shot(in_chamber) - if(chambered.deviation) - if(randomspread) //Random spread - spread = (rand() - 0.5) * chambered.deviation - else //Smart spread - spread = (i / chambered.pellets - 0.5) * chambered.deviation - if(!process_projectile(targloc, user, params, spread)) - return 0 - else - ready_projectile(target, user) - prepare_shot(in_chamber) - if(!process_projectile(targloc, user, params, spread)) - return 0 - - if(recoil) - spawn() - shake_camera(user, recoil + 1, recoil) - - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 50, 1) - if(f == 1) // Only print this once - user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ - "You fire [src][reflex ? "by reflex":""]!", \ - "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") - - if(heavy_weapon) - if(user.get_inactive_hand()) - if(prob(15)) - user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!") - user.drop_item() + if(burst_size > 1) + firing_burst = 1 + for(var/i = 1 to burst_size) + if(!user) + break + if(!issilicon(user)) + if( i>1 && !(src in get_both_hands(user))) //for burst firing break - - user.newtonian_move(get_dir(target, user)) + if(chambered) + var/sprd = 0 + if(randomspread) + sprd = round((rand() - 0.5) * spread) + else + sprd = round((i / burst_size - 0.5) * spread) + if(!chambered.fire(target, user, params, ,suppressed, zone_override, sprd)) + shoot_with_empty_chamber(user) + break + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + break + process_chamber() + update_icon() + sleep(fire_delay) + firing_burst = 0 + else + if(chambered) + if(!chambered.fire(target, user, params, , suppressed, zone_override, spread)) + shoot_with_empty_chamber(user) + return + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + return + process_chamber() update_icon() + semicd = 1 + spawn(fire_delay) + semicd = 0 + + if(user) if(user.hand) user.update_inv_l_hand() else user.update_inv_r_hand() - sleep(fire_delay) + feedback_add_details("gun_fired","[type]") -/obj/item/weapon/gun/proc/ready_projectile(atom/target as mob|obj|turf, mob/living/user) - in_chamber.firer = user - in_chamber.def_zone = user.zone_sel.selecting - in_chamber.original = target - return - -/obj/item/weapon/gun/proc/process_projectile(var/turf/targloc, mob/living/user as mob|obj, params, spread) - var/turf/curloc = user.loc - if (!istype(targloc) || !istype(curloc) || !in_chamber) - return 0 - if(targloc == curloc) //Fire the projectile - user.bullet_act(in_chamber) - del(in_chamber) - update_icon() - return 1 - - in_chamber.loc = get_turf(user) - in_chamber.starting = get_turf(user) - in_chamber.current = curloc - in_chamber.OnFired() - in_chamber.yo = targloc.y - curloc.y - in_chamber.xo = targloc.x - curloc.x - if(params) - var/list/mouse_control = params2list(params) - if(mouse_control["icon-x"]) - in_chamber.p_x = text2num(mouse_control["icon-x"]) - if(mouse_control["icon-y"]) - in_chamber.p_y = text2num(mouse_control["icon-y"]) - if(mouse_control["screen-loc"]) - //Split screen-loc up into X+Pixel_X and Y+Pixel_Y - var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",") - - //Split X+Pixel_X up into list(X, Pixel_X) - var/list/screen_loc_X = splittext(screen_loc_params[1],":") - - //Split Y+Pixel_Y up into list(Y, Pixel_Y) - var/list/screen_loc_Y = splittext(screen_loc_params[2],":") - - var/x = text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32 - var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32 - var/ox = round(480/2) //"origin" x - Basically center of the screen. This is a bad way of doing it because if you are able to view MORE than 17 tiles at a time your aim will get fucked. - var/oy = round(480/2) //"origin" y - Basically center of the screen. - - var/angle = Atan2(y - oy, x - ox) - - in_chamber.Angle = angle - - if(istype(user, /mob/living/carbon)) //Increase spread based on shock - var/mob/living/carbon/mob = user - if(mob.shock_stage > 120) - spread += rand(-5,5) - else if(mob.shock_stage > 70) - spread += rand(-2,2) - - if(spread) - in_chamber.Angle += spread - if(in_chamber) - in_chamber.process() - in_chamber = null - return 1 - -/obj/item/weapon/gun/proc/can_fire() - return process_chambered() - -/obj/item/weapon/gun/proc/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) - return in_chamber.check_fire(target,user) - -/obj/item/weapon/gun/proc/click_empty(mob/user = null) - if (user) - user.visible_message("*click click*", "\red *click*") - playsound(user, 'sound/weapons/empty.ogg', 100, 1) +/obj/item/weapon/gun/attack(mob/M as mob, mob/user) + if(user.a_intent == "harm") //Flogging + ..() else - src.visible_message("*click click*") - playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1) + return -/obj/item/weapon/gun/attack(mob/living/M as mob, mob/living/user as mob, def_zone) - //Suicide handling. - if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) - mouthshoot = 1 - M.visible_message(" [user] sticks their gun in their mouth, ready to pull the trigger...") - if(!do_after(user, 40, target = M)) - M.visible_message(" [user] decided life was worth living") - mouthshoot = 0 - return - if (process_chambered()) - user.visible_message("[user] pulls the trigger.") - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 50, 1) - if(istype(in_chamber, /obj/item/projectile/lasertag) || istype(in_chamber, /obj/item/projectile/bullet/reusable/foam_dart)) - user.show_message("You feel rather silly, trying to commit suicide with a toy.") - mouthshoot = 0 - return - in_chamber.on_hit(M) - if (in_chamber.damage_type != STAMINA) - user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1) - user.death() - else - to_chat(user, "Ow...") - user.apply_effect(110,STAMINA,0) - del(in_chamber) - mouthshoot = 0 - return - else - click_empty(user) - mouthshoot = 0 - return - - if (src.process_chambered()) - //Point blank shooting if on harm intent or target we were targeting. - if(user.a_intent == I_HARM) - user.visible_message("\red \The [user] fires \the [src] point blank at [M]!") - if(istype(in_chamber)) in_chamber.damage *= 1.3 - Fire(M,user,0,0,1) - return - else if(target && M in target) - Fire(M,user,0,0,1) ///Otherwise, shoot! - return - else - return ..() //Pistolwhippin' - - -/obj/item/weapon/gun/attackby(var/obj/item/A as obj, mob/user as mob, params) - if(istype(A, /obj/item/device/flashlight/seclite)) - var/obj/item/device/flashlight/seclite/S = A +/obj/item/weapon/gun/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/device/flashlight/seclite)) + var/obj/item/device/flashlight/seclite/S = I if(can_flashlight) if(!F) - if(user.l_hand != src && user.r_hand != src) - to_chat(user, "You'll need [src] in your hands to do that.") + if(!user.unEquip(I)) return - user.drop_item() to_chat(user, "You click [S] into place on [src].") if(S.on) set_light(0) F = S - A.loc = src + I.loc = src update_icon() update_gunlight(user) verbs += /obj/item/weapon/gun/proc/toggle_gunlight - if(istype(A, /obj/item/weapon/screwdriver)) - if(F) - if(user.l_hand != src && user.r_hand != src) - to_chat(user, "You'll need [src] in your hands to do that.") - return + + if(istype(I, /obj/item/weapon/screwdriver)) + if(F && can_flashlight) for(var/obj/item/device/flashlight/seclite/S in src) to_chat(user, "You unscrew the seclite from [src].") F = null @@ -370,8 +263,11 @@ S.update_brightness(user) update_icon() verbs -= /obj/item/weapon/gun/proc/toggle_gunlight + + if(unique_rename) + if(istype(I, /obj/item/weapon/pen)) + rename_gun(user) ..() - return /obj/item/weapon/gun/proc/toggle_gunlight() set name = "Toggle Gunlight" @@ -383,15 +279,14 @@ var/mob/living/carbon/human/user = usr if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc].") + to_chat(user, "You cannot turn the light on while in this [user.loc]!") F.on = !F.on to_chat(user, "You toggle the gunlight [F.on ? "on":"off"].") playsound(user, 'sound/weapons/empty.ogg', 100, 1) update_gunlight(user) - return -/obj/item/weapon/gun/proc/update_gunlight(var/mob/user = null) +/obj/item/weapon/gun/proc/update_gunlight(mob/user = null) if(F) if(F.on) set_light(F.brightness_on) @@ -400,7 +295,80 @@ update_icon() else set_light(0) + +/obj/item/weapon/gun/pickup(mob/user) + ..() + if(azoom) + azoom.Grant(user) + +/obj/item/weapon/gun/dropped(mob/user) + ..() + zoom(user,FALSE) + if(azoom) + azoom.Remove(user) + +/obj/item/weapon/gun/AltClick(mob/user) + ..() + if(user.incapacitated()) + to_chat(user, "You can't do that right now!") return + if(unique_reskin && !current_skin && loc == user) + reskin_gun(user) + +/obj/item/weapon/gun/proc/reskin_gun(mob/M) + var/choice = input(M,"Warning, you can only reskin your weapon once!","Reskin Gun") in options + + if(src && choice && !current_skin && !M.incapacitated() && in_range(M,src)) + if(options[choice] == null) + return + current_skin = options[choice] + to_chat(M, "Your gun is now skinned as [choice]. Say hello to your new friend.") + update_icon() + +/obj/item/weapon/gun/proc/rename_gun(mob/M) + var/input = stripped_input(M,"What do you want to name the gun?", ,"", MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove) + name = input + to_chat(M, "You name the gun [input]. Say hello to your new friend.") + return + +/obj/item/weapon/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params) + if(!ishuman(user) || !ishuman(target)) + return + + if(semicd) + return + + if(user == target) + target.visible_message("[user] sticks [src] in their mouth, ready to pull the trigger...", \ + "You stick [src] in your mouth, ready to pull the trigger...") + else + target.visible_message("[user] points [src] at [target]'s head, ready to pull the trigger...", \ + "[user] points [src] at your head, ready to pull the trigger...") + + semicd = 1 + + if(!do_mob(user, target, 120) || user.zone_sel.selecting != "mouth") + if(user) + if(user == target) + user.visible_message("[user] decided life was worth living.") + else if(target && target.Adjacent(user)) + target.visible_message("[user] has decided to spare [target]'s life.", "[user] has decided to spare your life!") + semicd = 0 + return + + semicd = 0 + + target.visible_message("[user] pulls the trigger!", "[user] pulls the trigger!") + + if(chambered && chambered.BB) + chambered.BB.damage *= 5 + + process_fire(target, user, 1, params) + +/obj/item/weapon/gun/proc/isHandgun() + return 1 ///////////// // ZOOMING // @@ -424,8 +392,6 @@ gun.zoom(L, FALSE) ..() - - /obj/item/weapon/gun/proc/zoom(mob/living/user, forced_zoom) if(!user || !user.client) return diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm index eeb775be84a..de217a9715d 100644 --- a/code/modules/projectiles/guns/alien.dm +++ b/code/modules/projectiles/guns/alien.dm @@ -1,108 +1,100 @@ -//Vox pinning weapon. -/obj/item/weapon/gun/launcher/spikethrower - - name = "Vox spike thrower" +/obj/item/weapon/gun/projectile/automatic/spikethrower + name = "\improper Vox spike thrower" desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive." - - var/last_regen = 0 - var/spike_gen_time = 100 - var/max_spikes = 3 - var/spikes = 3 - release_force = 30 - icon = 'icons/obj/gun.dmi' - icon_state = "spikethrower3" + icon_state = "spikethrower" item_state = "spikethrower" + w_class = 2 fire_sound_text = "a strange noise" - fire_sound = 'sound/weapons/bladeslice.ogg' + mag_type = /obj/item/ammo_box/magazine/internal/spikethrower + burst_size = 2 + fire_delay = 3 + can_suppress = 0 + var/charge_tick = 0 + var/charge_delay = 15 + restricted_species = list("Vox", "Vox Armalis") -/obj/item/weapon/gun/launcher/spikethrower/New() +/obj/item/weapon/gun/projectile/automatic/spikethrower/New() ..() processing_objects.Add(src) - last_regen = world.time -/obj/item/weapon/gun/launcher/spikethrower/Destroy() +/obj/item/weapon/gun/projectile/automatic/spikethrower/Destroy() processing_objects.Remove(src) return ..() -/obj/item/weapon/gun/launcher/spikethrower/process() - - if(spikes < max_spikes && world.time > last_regen + spike_gen_time) - spikes++ - last_regen = world.time - update_icon() - -/obj/item/weapon/gun/launcher/spikethrower/examine(mob/user) - ..(user) - to_chat(user, "It has [spikes] [spikes == 1 ? "spike" : "spikes"] remaining.") - -/obj/item/weapon/gun/launcher/spikethrower/update_icon() - icon_state = "spikethrower[spikes]" - -/obj/item/weapon/gun/launcher/spikethrower/emp_act(severity) +/obj/item/weapon/gun/projectile/automatic/spikethrower/update_icon() return -/obj/item/weapon/gun/launcher/spikethrower/special_check(user) - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(H.species && H.species.name != "Vox" && H.species.name != "Vox Armalis") - to_chat(user, "\red \The [src] does not respond to you!") - return 0 +/obj/item/weapon/gun/projectile/automatic/spikethrower/process() + charge_tick++ + if(charge_tick < charge_delay || !magazine) + return + charge_tick = 0 + var/obj/item/ammo_casing/caseless/spike/S = new(get_turf(src)) + magazine.give_round(S) return 1 -/obj/item/weapon/gun/launcher/spikethrower/update_release_force() +/obj/item/weapon/gun/projectile/automatic/spikethrower/attack_self() return -/obj/item/weapon/gun/launcher/spikethrower/chamber_round() - if(in_chamber) return 1 - if(spikes < 1) return 0 +/obj/item/weapon/gun/projectile/automatic/spikethrower/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() - spikes-- - in_chamber = new /obj/item/weapon/spike(src) - return 1 +/obj/item/ammo_box/magazine/internal/spikethrower + name = "\improper Vox spikethrower internal magazine" + ammo_type = /obj/item/ammo_casing/caseless/spike + caliber = "spike" + max_ammo = 10 -/obj/item/weapon/gun/launcher/spikethrower/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0) - if(..()) update_icon() +/obj/item/ammo_casing/caseless/spike + name = "alloy spike" + desc = "A broadhead spike made out of a weird silvery metal." + projectile_type = /obj/item/projectile/bullet/spike + sharp = 1 + edge = 0 + throwforce = 5 + w_class = 3 + caliber = "spike" + icon_state = "bolt" + fire_sound = 'sound/weapons/bladeslice.ogg' + +/obj/item/projectile/bullet/spike + name = "alloy spike" + desc = "It's about a foot of weird silvery metal with a wicked point." + damage = 25 + stun = 1 + armour_penetration = 30 + icon_state = "magspear" + +/obj/item/projectile/bullet/spike/on_hit(atom/target, blocked = 0) + if((blocked != 100) && istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + H.drip(500) + ..() //This gun only functions for armalis. The on-sprite is too huge to render properly on other sprites. /obj/item/weapon/gun/energy/noisecannon - name = "alien heavy cannon" desc = "It's some kind of enormous alien weapon, as long as a man is tall." - - icon = 'icons/obj/gun.dmi' //Actual on-sprite is handled by icon_override. icon_state = "noisecannon" item_state = "noisecannon" recoil = 1 - force = 10 - projectile_type = "/obj/item/projectile/energy/sonic" - cell_type = "/obj/item/weapon/stock_parts/cell/super" - fire_delay = 40 - fire_sound = 'sound/effects/basscannon.ogg' - - var/mode = 1 - -/obj/item/weapon/gun/energy/noisecannon/attack_hand(mob/user as mob) - if(loc != user) - var/mob/living/carbon/human/H = user - if(istype(H)) - if(H.species.name == "Vox Armalis") - ..() - return - to_chat(user, "\red \The [src] is far too large for you to pick up.") - return - -/obj/item/weapon/gun/energy/noisecannon/process_chambered() //Does not have ammo. - in_chamber = new projectile_type(src) - return 1 + ammo_type = list(/obj/item/ammo_casing/energy/sonic) + cell_type = /obj/item/weapon/stock_parts/cell/super + restricted_species = list("Vox Armalis") /obj/item/weapon/gun/energy/noisecannon/update_icon() return +//Casing +/obj/item/ammo_casing/energy/sonic + projectile_type = /obj/item/projectile/energy/sonic + fire_sound = 'sound/effects/basscannon.ogg' + delay = 40 + //Projectile. /obj/item/projectile/energy/sonic name = "distortion" - icon = 'icons/obj/machines/particle_accelerator.dmi' icon_state = "particle" damage = 60 damage_type = BRUTE @@ -112,7 +104,3 @@ embed = 0 weaken = 5 stun = 5 - -/obj/item/projectile/energy/sonic/proc/split() - //TODO: create two more projectiles to either side of this one, fire at targets to the side of target turf. - return \ No newline at end of file diff --git a/code/modules/reagents/dartgun.dm b/code/modules/projectiles/guns/dartgun.dm similarity index 94% rename from code/modules/reagents/dartgun.dm rename to code/modules/projectiles/guns/dartgun.dm index 4fb705dbcf9..2e55b19b4a9 100644 --- a/code/modules/reagents/dartgun.dm +++ b/code/modules/projectiles/guns/dartgun.dm @@ -33,9 +33,8 @@ var/list/starting_chems = null /obj/item/weapon/gun/dartgun/update_icon() - if(!cartridge) - icon_state = "dartgun-empty" + icon_state = "dartgun-e" return 1 if(!cartridge.darts) @@ -47,7 +46,6 @@ return 1 /obj/item/weapon/gun/dartgun/New() - ..() if(starting_chems) for(var/chem in starting_chems) @@ -104,7 +102,7 @@ to_chat(user, "[src] is empty.") @@ -305,7 +301,7 @@ anchored = 1 density = 0 - New() - var/datum/reagents/R = new/datum/reagents(15) - reagents = R - R.my_atom = src \ No newline at end of file +/obj/effect/syringe_gun_dummy/New() + var/datum/reagents/R = new/datum/reagents(15) + reagents = R + R.my_atom = src diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 8add6a5caf9..76e86d74699 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -2,25 +2,26 @@ icon_state = "energy" name = "energy gun" desc = "A basic energy-based gun." - fire_sound = 'sound/weapons/Taser.ogg' + icon = 'icons/obj/guns/energy.dmi' + fire_sound_text = "laser blast" var/obj/item/weapon/stock_parts/cell/power_supply //What type of power cell this uses - var/charge_cost = 1000 //How much energy is needed to fire. - var/cell_type = "/obj/item/weapon/stock_parts/cell" - var/projectile_type = "/obj/item/projectile/beam" - var/modifystate + var/cell_type = /obj/item/weapon/stock_parts/cell + var/modifystate = 0 + var/list/ammo_type = list(/obj/item/ammo_casing/energy) + var/select = 1 //The state of the select fire switch. Determines from the ammo_type list what kind of shot is fired next. var/can_charge = 1 - - //self-recharging - var/self_recharge = 0 //if set, the weapon will recharge itself + var/charge_sections = 4 + ammo_x_offset = 2 + var/shaded_charge = 0 //if this gun uses a stateful charge bar for more detail + var/selfcharge = 0 var/use_external_power = 0 //if set, the weapon will look for an external power source to draw from, otherwise it recharges magically - var/recharge_time = 4 var/charge_tick = 0 + var/charge_delay = 4 /obj/item/weapon/gun/energy/emp_act(severity) - if(power_supply) - power_supply.use(round(power_supply.charge / severity)) - update_icon() + power_supply.use(round(power_supply.charge / severity)) + update_icon() /obj/item/weapon/gun/energy/New() ..() @@ -29,39 +30,147 @@ else power_supply = new(src) power_supply.give(power_supply.maxcharge) - if(self_recharge) + var/obj/item/ammo_casing/energy/shot + for (var/i = 1, i <= ammo_type.len, i++) + var/shottype = ammo_type[i] + shot = new shottype(src) + ammo_type[i] = shot + shot = ammo_type[select] + fire_sound = shot.fire_sound + fire_delay = shot.delay + if(selfcharge) processing_objects.Add(src) update_icon() /obj/item/weapon/gun/energy/Destroy() - if(self_recharge) + if(selfcharge) processing_objects.Remove(src) return ..() /obj/item/weapon/gun/energy/process() - if(self_recharge) //Every [recharge_time] ticks, recharge a shot for the cyborg + if(selfcharge) //Every [recharge_time] ticks, recharge a shot for the cyborg charge_tick++ - if(charge_tick < recharge_time) return 0 + if(charge_tick < charge_delay) + return charge_tick = 0 - - if(!power_supply || power_supply.charge >= power_supply.maxcharge) - return 0 // check if we actually need to recharge - + if(!power_supply) + return // check if we actually need to recharge + var/obj/item/ammo_casing/energy/E = ammo_type[select] if(use_external_power) var/obj/item/weapon/stock_parts/cell/external = get_external_power_supply() - if(!external || !external.use(charge_cost/10)) //Take power from the borg... - return 0 //Note, uses /10 because of shitty mods to the cell system - - power_supply.give(charge_cost) //... to recharge the shot + if(!external || !external.use((E.e_cost)/10)) //Take power from the borg... + return //Note, uses /10 because of shitty mods to the cell system + power_supply.give(1000) //... to recharge the shot update_icon() - return 1 + +/obj/item/weapon/gun/energy/attack_self(mob/living/user as mob) + if(ammo_type.len > 1) + select_fire(user) + update_icon() + if(istype(user,/mob/living/carbon/human)) //This has to be here or else if you toggle modes by clicking the gun in hand + var/mob/living/carbon/human/H = user //Otherwise the mob icon doesn't update, blame shitty human update_icons() code + H.update_inv_l_hand() + H.update_inv_r_hand() + +/obj/item/weapon/gun/energy/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) + newshot() //prepare a new shot + ..() + +/obj/item/weapon/gun/energy/can_shoot() + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + return power_supply.charge >= shot.e_cost + +/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(params) + return + +/obj/item/weapon/gun/energy/process_chamber() + if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... + var/obj/item/ammo_casing/energy/shot = chambered + power_supply.use(shot.e_cost)//... drain the power_supply cell + chambered = null //either way, released the prepared shot + return + +/obj/item/weapon/gun/energy/proc/select_fire(mob/living/user) + select++ + if (select > ammo_type.len) + select = 1 + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + fire_sound = shot.fire_sound + fire_delay = shot.delay + if (shot.select_name) + to_chat(user, "[src] is now set to [shot.select_name].") + update_icon() + return + +/obj/item/weapon/gun/energy/update_icon() + overlays.Cut() + var/ratio = Ceiling((power_supply.charge / power_supply.maxcharge) * charge_sections) + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + var/iconState = "[icon_state]_charge" + var/itemState = null + if(!initial(item_state)) + itemState = icon_state + if (modifystate) + overlays += "[icon_state]_[shot.select_name]" + iconState += "_[shot.select_name]" + if(itemState) + itemState += "[shot.select_name]" + if(power_supply.charge < shot.e_cost) + overlays += "[icon_state]_empty" + else + if(!shaded_charge) + for(var/i = ratio, i >= 1, i--) + overlays += image(icon = icon, icon_state = iconState, pixel_x = ammo_x_offset * (i -1)) + else + overlays += image(icon = icon, icon_state = "[icon_state]_[modifystate ? "[shot.select_name]_" : ""]charge[ratio]") + if(F && can_flashlight) + var/iconF = "flight" + if(F.on) + iconF = "flight_on" + overlays += image(icon = icon, icon_state = iconF, pixel_x = flight_x_offset, pixel_y = flight_y_offset) + if(itemState) + itemState += "[ratio]" + item_state = itemState + +/obj/item/weapon/gun/energy/ui_action_click() + toggle_gunlight() + +/obj/item/weapon/gun/energy/suicide_act(mob/user) + if (can_shoot()) + user.visible_message("[user] is putting the barrel of the [name] in \his mouth. It looks like \he's trying to commit suicide.") + sleep(25) + if(user.l_hand == src || user.r_hand == src) + user.visible_message("[user] melts \his face off with the [name]!") + playsound(loc, fire_sound, 50, 1, -1) + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + power_supply.use(shot.e_cost) + update_icon() + return(FIRELOSS) + else + user.visible_message("[user] panics and starts choking to death!") + return(OXYLOSS) + else + user.visible_message("[user] is pretending to blow \his brains out with the [name]! It looks like \he's trying to commit suicide!") + playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1) + return (OXYLOSS) + +/obj/item/weapon/gun/energy/proc/robocharge() + if(isrobot(loc)) + var/mob/living/silicon/robot/R = loc + if(R && R.cell) + var/obj/item/ammo_casing/energy/shot = ammo_type[select] //Necessary to find cost of shot + if(R.cell.use(shot.e_cost/10)) //Take power from the borg... //Divided by 10 because cells and charge costs are fucked. + power_supply.give(shot.e_cost) //... to recharge the shot /obj/item/weapon/gun/energy/proc/get_external_power_supply() - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - return R.cell - if(istype(src.loc, /obj/item/rig_module)) - var/obj/item/rig_module/module = src.loc + if(istype(loc, /obj/item/rig_module)) + var/obj/item/rig_module/module = loc if(module.holder && module.holder.wearer) var/mob/living/carbon/human/H = module.holder.wearer if(istype(H) && H.back) @@ -69,29 +178,3 @@ if(istype(suit)) return suit.cell return null - -/obj/item/weapon/gun/energy/process_chambered() - if(in_chamber) return 1 - if(!power_supply) return 0 - if(!power_supply.use(charge_cost)) return 0 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - return 1 - -/obj/item/weapon/gun/energy/update_icon() - if(cell_type) - var/ratio = power_supply.charge / power_supply.maxcharge - ratio = round(ratio, 0.25) * 100 - if(modifystate) - icon_state = "[modifystate][ratio]" - else - icon_state = "[initial(icon_state)][ratio]" - else - icon_state = "energy0" - overlays.Cut() - if(F) - if(F.on) - overlays += "flight-on" - else - overlays += "flight" - return diff --git a/code/modules/projectiles/guns/energy/advtaser.dm b/code/modules/projectiles/guns/energy/advtaser.dm deleted file mode 100644 index 8601a388f15..00000000000 --- a/code/modules/projectiles/guns/energy/advtaser.dm +++ /dev/null @@ -1,40 +0,0 @@ -/obj/item/weapon/gun/energy/advtaser - name = "hybrid taser" - desc = "A hybrid taser designed to fire both short-range high-power electrodes and long-range disabler beams." - icon_state = "advtaser" - item_state = null //so the human update icon uses the icon_state instead. - cell_type = "/obj/item/weapon/stock_parts/cell" - origin_tech = null - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" - charge_cost = 2000 - modifystate = "advtaserstun" - can_flashlight = 1 - fire_delay = 15 - - var/mode = 0 //0 = stun, 1 = disable - - - attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 500 - fire_sound = 'sound/weapons/taser2.ogg' - to_chat(user, "\red [src.name] is now set to Disable.") - projectile_type = "/obj/item/projectile/beam/disabler" - modifystate = "advtaserdisable" - fire_delay = 0 - if(1) - mode = 0 - charge_cost = 2000 - fire_sound = 'sound/weapons/Taser.ogg' - to_chat(user, "\red [src.name] is now set to stun.") - projectile_type = "/obj/item/projectile/energy/electrode" - modifystate = "advtaserstun" - fire_delay = 15 - update_icon() - if(user.l_hand == src) - user.update_inv_l_hand() - else - user.update_inv_r_hand() diff --git a/code/modules/projectiles/guns/energy/blueshield.dm b/code/modules/projectiles/guns/energy/blueshield.dm deleted file mode 100644 index 914b92e19a6..00000000000 --- a/code/modules/projectiles/guns/energy/blueshield.dm +++ /dev/null @@ -1,37 +0,0 @@ -/obj/item/weapon/gun/energy/blueshield - name = "advanced stun revolver" - desc = "An advanced stun revolver with the capacity to shoot both electrodes and lasers." - icon_state = "bsgun_stun" - item_state = "gun" - modifystate = "bsgun_stun" - force = 7 - fire_sound = 'sound/weapons/gunshot.ogg' - charge_cost = 2000 - projectile_type = "/obj/item/projectile/energy/electrode" - fire_delay = 15 - var/fire_mode = 0 // 0 for taser, 1 for lethals. - -/obj/item/weapon/gun/energy/blueshield/attack_self(mob/living/user as mob) - if(!fire_mode) - fire_mode = 1 - charge_cost = 1000 - fire_delay = 0 - - fire_sound = 'sound/weapons/Laser.ogg' - projectile_type = "/obj/item/projectile/beam" - modifystate = "bsgun_kill" - - to_chat(user, "You adjust [src.name] to the kill setting.") - - else - fire_mode = 0 - charge_cost = 2000 - fire_delay = 15 - - projectile_type = "/obj/item/projectile/energy/electrode" - fire_sound = 'sound/weapons/gunshot.ogg' - modifystate = "bsgun_stun" - - to_chat(user, "You adjust [src.name] to the stun setting.") - - update_icon() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/hos.dm b/code/modules/projectiles/guns/energy/hos.dm deleted file mode 100644 index 6bcb9992c4d..00000000000 --- a/code/modules/projectiles/guns/energy/hos.dm +++ /dev/null @@ -1,45 +0,0 @@ -/obj/item/weapon/gun/energy/hos - name = "head of security's energy gun" - desc = "This is a modern recreation of the captain's antique laser gun. This gun has several unique fire modes, but lacks the ability to recharge over time." - icon_state = "hoslaser" - item_state = null //so the human update icon uses the icon_state instead. - force = 10 - fire_sound = 'sound/weapons/Taser.ogg' - origin_tech = "combat=3;magnets=2" - charge_cost = 2000 - modifystate = "hoslaserstun" - projectile_type = "/obj/item/projectile/energy/electrode" - fire_delay = 15 - var/mode = 2 - - attack_self(mob/living/user as mob) - switch(mode) - if(2) - mode = 0 - charge_cost = 1000 - fire_sound = 'sound/weapons/Laser.ogg' - to_chat(user, "\red [src.name] is now set to kill.") - projectile_type = "/obj/item/projectile/beam" - modifystate = "hoslaserkill" - fire_delay = 0 - if(0) - mode = 1 - charge_cost = 500 - fire_sound = 'sound/weapons/taser2.ogg' - to_chat(user, "\red [src.name] is now set to disable.") - projectile_type = "/obj/item/projectile/beam/disabler" - modifystate = "hoslaserdisable" - fire_delay = 0 - if(1) - mode = 2 - charge_cost = 2000 - fire_sound = 'sound/weapons/taser.ogg' - to_chat(user, "\red [src.name] is now set to stun.") - projectile_type = "/obj/item/projectile/energy/electrode" - modifystate = "hoslaserstun" - fire_delay = 15 - update_icon() - if(user.l_hand == src) - user.update_inv_l_hand() - else - user.update_inv_r_hand() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 330d9136f17..40356f8a7d9 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -1,59 +1,65 @@ /obj/item/weapon/gun/energy/laser name = "laser gun" - desc = "a basic weapon designed kill with concentrated energy bolts" + desc = "A basic energy-based laser gun that fires concentrated beams of light which pass through glass and thin metal." icon_state = "laser" item_state = "laser" - fire_sound = 'sound/weapons/Laser.ogg' - charge_cost = 760 - w_class = 3.0 + w_class = 3 materials = list(MAT_METAL=2000) origin_tech = "combat=3;magnets=2" - projectile_type = "/obj/item/projectile/beam" + ammo_type = list(/obj/item/ammo_casing/energy/lasergun) + ammo_x_offset = 1 + shaded_charge = 1 /obj/item/weapon/gun/energy/laser/practice name = "practice laser gun" desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice." - projectile_type = "/obj/item/projectile/practice" + ammo_type = list(/obj/item/ammo_casing/energy/laser/practice) clumsy_check = 0 needs_permit = 0 -obj/item/weapon/gun/energy/laser/retro +/obj/item/weapon/gun/energy/laser/retro name ="retro laser gun" icon_state = "retro" - desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." - + desc = "An older model of the basic lasergun, no longer used by Nanotrasen's private security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." + ammo_x_offset = 3 /obj/item/weapon/gun/energy/laser/captain - name = "captain's antique laser gun" + name = "antique laser gun" icon_state = "caplaser" item_state = "caplaser" desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding." force = 10 origin_tech = null + ammo_x_offset = 3 + selfcharge = 1 - self_recharge = 1 - +/obj/item/weapon/gun/energy/laser/captain/scattershot + name = "scatter shot laser rifle" + icon_state = "lasercannon" + item_state = "laser" + desc = "An industrial-grade heavy-duty laser rifle with a modified laser lense to scatter its shot into multiple smaller lasers. The inner-core can self-charge for theorically infinite use." + origin_tech = "combat=5;materials=4;powerstorage=4" + ammo_type = list(/obj/item/ammo_casing/energy/laser/scatter, /obj/item/ammo_casing/energy/laser) + shaded_charge = 0 /obj/item/weapon/gun/energy/laser/cyborg + can_charge = 0 desc = "An energy-based laser gun that draws power from the cyborg's internal energy cell directly. So this is what freedom looks like?" + origin_tech = null -/obj/item/weapon/gun/energy/laser/cyborg/process() - return 1 - -/obj/item/weapon/gun/energy/laser/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell && R.cell.charge >= 83) - R.cell.use(83) - in_chamber = new/obj/item/projectile/beam(src) - return 1 - return 0 +/obj/item/weapon/gun/energy/laser/cyborg/newshot() + ..() + robocharge() /obj/item/weapon/gun/energy/laser/cyborg/emp_act() return +/obj/item/weapon/gun/energy/laser/scatter + name = "scatter laser gun" + desc = "A laser gun equipped with a refraction kit that spreads bolts." + ammo_type = list(/obj/item/ammo_casing/energy/laser/scatter, /obj/item/ammo_casing/energy/laser) + +///Laser Cannon /obj/item/weapon/gun/energy/lasercannon name = "accelerator laser cannon" @@ -64,13 +70,18 @@ obj/item/weapon/gun/energy/laser/retro force = 10 flags = CONDUCT slot_flags = SLOT_BACK - fire_sound = 'sound/weapons/lasercannonfire.ogg' origin_tech = "combat=4;materials=3;powerstorage=3" - projectile_type = "/obj/item/projectile/beam/laser/accelerator" + ammo_type = list(/obj/item/ammo_casing/energy/laser/accelerator) + ammo_x_offset = 3 /obj/item/weapon/gun/energy/lasercannon/isHandgun() return 0 +/obj/item/ammo_casing/energy/laser/accelerator + projectile_type = /obj/item/projectile/beam/laser/accelerator + select_name = "accelerator" + fire_sound = 'sound/weapons/lasercannonfire.ogg' + /obj/item/projectile/beam/laser/accelerator name = "accelerator laser" icon_state = "heavylaser" @@ -83,40 +94,34 @@ obj/item/weapon/gun/energy/laser/retro /obj/item/weapon/gun/energy/lasercannon/mounted name = "mounted laser cannon" - self_recharge = 1 + selfcharge = 1 use_external_power = 1 - recharge_time = 10 + charge_delay = 10 +/obj/item/weapon/gun/energy/lasercannon/cyborg -/obj/item/weapon/gun/energy/lasercannon/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(250) - in_chamber = new/obj/item/projectile/beam(src) - return 1 - return 0 +/obj/item/weapon/gun/energy/lasercannon/cyborg/newshot() + ..() + robocharge() + +/obj/item/weapon/gun/energy/lasercannon/cyborg/emp_act() + return /obj/item/weapon/gun/energy/xray name = "xray laser gun" desc = "A high-power laser gun capable of expelling concentrated xray blasts." icon_state = "xray" - fire_sound = 'sound/weapons/laser3.ogg' origin_tech = "combat=5;materials=3;magnets=2;syndicate=2" - projectile_type = "/obj/item/projectile/beam/xray" - charge_cost = 500 + ammo_type = list(/obj/item/ammo_casing/energy/xray) /obj/item/weapon/gun/energy/immolator name = "Immolator laser gun" desc = "A modified laser gun, shooting highly concetrated beams with higher intensity that ignites the target, for the cost of draining more power per shot" icon_state = "immolator" item_state = "laser" - fire_sound = 'sound/weapons/laser3.ogg' - projectile_type = "/obj/item/projectile/beam/immolator" + ammo_type = list(/obj/item/ammo_casing/energy/immolator) origin_tech = "combat=4;materials=4;magnets=3;plasmatech=2" - charge_cost = 1250 + shaded_charge = 1 ////////Laser Tag//////////////////// @@ -124,34 +129,20 @@ obj/item/weapon/gun/energy/laser/retro name = "laser tag gun" icon_state = "bluetag" desc = "Standard issue weapon of the Imperial Guard" - projectile_type = "/obj/item/projectile/lasertag/blue" + ammo_type = list(/obj/item/ammo_casing/energy/laser/bluetag) origin_tech = "combat=1;magnets=2" clumsy_check = 0 needs_permit = 0 - - self_recharge = 1 - -/obj/item/weapon/gun/energy/laser/bluetag/special_check(var/mob/living/carbon/human/M) - if(ishuman(M)) - if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) - return 1 - to_chat(M, "\red You need to be wearing your laser tag vest!") - return 0 + ammo_x_offset = 2 + selfcharge = 1 /obj/item/weapon/gun/energy/laser/redtag name = "laser tag gun" icon_state = "redtag" desc = "Standard issue weapon of the Imperial Guard" - projectile_type = "/obj/item/projectile/lasertag/red" + ammo_type = list(/obj/item/ammo_casing/energy/laser/redtag) origin_tech = "combat=1;magnets=2" clumsy_check = 0 needs_permit = 0 - - self_recharge = 1 - -/obj/item/weapon/gun/energy/laser/redtag/special_check(var/mob/living/carbon/human/M) - if(ishuman(M)) - if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) - return 1 - to_chat(M, "\red You need to be wearing your laser tag vest!") - return 0 \ No newline at end of file + ammo_x_offset = 2 + selfcharge = 1 diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 5bc164c5d76..2ef193a6c37 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -1,192 +1,132 @@ /obj/item/weapon/gun/energy/gun name = "energy gun" desc = "A basic energy-based gun with two settings: kill and disable." - icon_state = "energystun100" + icon_state = "energy" item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser2.ogg' - charge_cost = 500 - projectile_type = "/obj/item/projectile/beam/disabler" + ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser) origin_tech = "combat=3;magnets=2" - modifystate = "energystun" + modifystate = 2 can_flashlight = 1 - - var/mode = 0 //0 = disable, 1 = kill - - - attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 1000 - fire_sound = 'sound/weapons/Laser.ogg' - to_chat(user, "\red [src.name] is now set to kill.") - projectile_type = "/obj/item/projectile/beam" - modifystate = "energykill" - if(1) - mode = 0 - charge_cost = 500 - fire_sound = 'sound/weapons/Taser2.ogg' - to_chat(user, "\red [src.name] is now set to disable.") - projectile_type = "/obj/item/projectile/beam/disabler" - modifystate = "energystun" - update_icon() - if(user.l_hand == src) - user.update_inv_l_hand() - else - user.update_inv_r_hand() + ammo_x_offset = 3 + flight_x_offset = 15 + flight_y_offset = 10 /obj/item/weapon/gun/energy/gun/cyborg desc = "An energy-based laser gun that draws power from the cyborg's internal energy cell directly. So this is what freedom looks like?" -/obj/item/weapon/gun/energy/gun/cyborg/process() - return 1 - -/obj/item/weapon/gun/energy/gun/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell && R.cell.charge >= 83) - R.cell.use(83) - in_chamber = new projectile_type(src) - return 1 - return 0 +/obj/item/weapon/gun/energy/gun/cyborg/newshot() + ..() + robocharge() +/obj/item/weapon/gun/energy/gun/cyborg/emp_act() + return /obj/item/weapon/gun/energy/gun/mounted name = "mounted energy gun" - self_recharge = 1 + selfcharge = 1 use_external_power = 1 -/obj/item/weapon/gun/energy/gun/nuclear - name = "Advanced Energy Gun" - desc = "An energy gun with an experimental miniaturized reactor." - icon_state = "nucgun" - origin_tech = "combat=3;materials=5;powerstorage=3" - var/lightfail = 0 - can_flashlight = 0 - can_charge = 0 +/obj/item/weapon/gun/energy/gun/mini + name = "miniature energy gun" + desc = "A small, pistol-sized energy gun with a built-in flashlight. It has two settings: stun and kill." + icon_state = "mini" + item_state = "gun" + w_class = 2 + ammo_x_offset = 2 + charge_sections = 3 + can_flashlight = 0 // Can't attach or detach the flashlight, and override it's icon update - New() - ..() - processing_objects.Add(src) +/obj/item/weapon/gun/energy/gun/mini/New() + F = new /obj/item/device/flashlight/seclite(src) + ..() + power_supply.maxcharge = 6000 + power_supply.charge = 6000 +/obj/item/weapon/gun/energy/gun/mini/update_icon() + ..() + if(F && F.on) + overlays += "mini-light" - Destroy() - processing_objects.Remove(src) - return ..() - - - process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - if((power_supply.charge / power_supply.maxcharge) != 1) - if(!failcheck()) return 0 - power_supply.give(1000) - update_icon() - return 1 - - - proc - failcheck() - lightfail = 0 - if (prob(src.reliability)) return 1 //No failure - if (prob(src.reliability)) - for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it - if (src in M.contents) - to_chat(M, "\red Your gun feels pleasantly warm for a moment.") - else - to_chat(M, "\red You feel a warm sensation.") - M.apply_effect(rand(3,120), IRRADIATE) - lightfail = 1 - else - for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES - if (src in M.contents) - to_chat(M, "\red Your gun's reactor overloads!") - to_chat(M, "\red You feel a wave of heat wash over you.") - M.apply_effect(300, IRRADIATE) - crit_fail = 1 //break the gun so it stops recharging - processing_objects.Remove(src) - update_icon() - return 0 - - - update_charge() - if (crit_fail) - overlays += "nucgun-whee" - return - var/ratio = power_supply.charge / power_supply.maxcharge - ratio = round(ratio, 0.25) * 100 - overlays += "nucgun-[ratio]" - - - update_reactor() - if(crit_fail) - overlays += "nucgun-crit" - return - if(lightfail) - overlays += "nucgun-medium" - else if ((power_supply.charge/power_supply.maxcharge) <= 0.5) - overlays += "nucgun-light" - else - overlays += "nucgun-clean" - - - update_mode() - if (mode == 0) - overlays += "nucgun-stun" - else if (mode == 1) - overlays += "nucgun-kill" - - emp_act(severity) - ..() - reliability = max(reliability - round(15/severity), 0) //Do not allow it to go negative! - - - update_icon() - overlays.Cut() - update_charge() - update_reactor() - update_mode() +/obj/item/weapon/gun/energy/gun/hos + name = "\improper X-01 MultiPhase Energy Gun" + desc = "This is a expensive, modern recreation of a antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time." + icon_state = "hoslaser" + force = 10 + ammo_type = list(/obj/item/ammo_casing/energy/electrode/hos, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/disabler) + ammo_x_offset = 4 +/obj/item/weapon/gun/energy/gun/blueshield + name = "advanced stun revolver" + desc = "An advanced stun revolver with the capacity to shoot both electrodes and lasers." + icon_state = "bsgun" + force = 7 + ammo_type = list(/obj/item/ammo_casing/energy/electrode/hos, /obj/item/ammo_casing/energy/laser/hos) + ammo_x_offset = 1 + shaded_charge = 1 /obj/item/weapon/gun/energy/gun/turret name = "hybrid turret gun" desc = "A heavy hybrid energy cannon with two settings: Stun and kill." icon_state = "turretlaser" + item_state = "turretlaser" slot_flags = null w_class = 5 - heavy_weapon = 1 + ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser) + weapon_weight = WEAPON_MEDIUM can_flashlight = 0 - projectile_type = /obj/item/projectile/energy/electrode - charge_cost = 1000 - fire_delay = 15 + trigger_guard = TRIGGER_GUARD_NONE + ammo_x_offset = 2 -/obj/item/weapon/gun/energy/gun/turret/update_icon() - icon_state = initial(icon_state) +/obj/item/weapon/gun/energy/gun/nuclear + name = "advanced energy gun" + desc = "An energy gun with an experimental miniaturized nuclear reactor that automatically charges the internal power cell." + icon_state = "nucgun" + item_state = "nucgun" + origin_tech = "combat=3;materials=5;powerstorage=3" + var/fail_tick = 0 + charge_delay = 5 + can_charge = 0 + ammo_x_offset = 1 + ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/disabler) + selfcharge = 1 -/obj/item/weapon/gun/energy/gun/turret/attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 500 - fire_sound = 'sound/weapons/Laser.ogg' - to_chat(user, "\red [src.name] is now set to kill.") - projectile_type = /obj/item/projectile/beam - modifystate = "energykill" - fire_delay = 0 - if(1) - mode = 0 - charge_cost = 1000 - fire_sound = 'sound/weapons/Taser.ogg' - to_chat(user, "\red [src.name] is now set to stun.") - projectile_type = /obj/item/projectile/energy/electrode - modifystate = "energystun" - fire_delay = 15 +/obj/item/weapon/gun/energy/gun/nuclear/process() + if(fail_tick > 0) + fail_tick-- + ..() + +/obj/item/weapon/gun/energy/gun/nuclear/shoot_live_shot() + failcheck() update_icon() - if(user.l_hand == src) - user.update_inv_l_hand() + ..() + +/obj/item/weapon/gun/energy/gun/nuclear/proc/failcheck() + if(!prob(reliability) && istype(loc, /mob/living)) + var/mob/living/M = loc + switch(fail_tick) + if(0 to 200) + fail_tick += (2*(100-reliability)) + M.apply_effect(rand(3,120), IRRADIATE) + to_chat(M, "Your [name] feels warmer.") + if(201 to INFINITY) + processing_objects.Remove(src) + M.apply_effect(300, IRRADIATE) + crit_fail = 1 + to_chat(M, "Your [name]'s reactor overloads!") + +/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity) + ..() + reliability = max(reliability - round(15/severity), 0) //Do not allow it to go negative! + +/obj/item/weapon/gun/energy/gun/nuclear/update_icon() + ..() + if(crit_fail) + overlays += "[icon_state]_fail_3" else - user.update_inv_r_hand() \ No newline at end of file + switch(fail_tick) + if(0) + overlays += "[icon_state]_fail_0" + if(1 to 150) + overlays += "[icon_state]_fail_1" + if(151 to INFINITY) + overlays += "[icon_state]_fail_2" diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index bc7704d709a..c155cfb9dff 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -1,93 +1,72 @@ -/obj/item/weapon/gun/energy/pulse_rifle +/obj/item/weapon/gun/energy/pulse name = "pulse rifle" - desc = "A heavy-duty, pulse-based energy weapon, preferred by front-line combat personnel." + desc = "A heavy-duty, multifaceted energy rifle with three modes. Preferred by front-line combat personnel." icon_state = "pulse" - item_state = null //so the human update icon uses the icon_state instead. + item_state = null + w_class = 4 force = 10 - fire_sound = 'sound/weapons/pulse.ogg' - charge_cost = 200 - projectile_type = "/obj/item/projectile/beam/pulse" - cell_type = "/obj/item/weapon/stock_parts/cell/super" - var/mode = 2 + flags = CONDUCT slot_flags = SLOT_BACK - w_class = 4.0 + 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 - emp_act() - return +/obj/item/weapon/gun/energy/pulse/emp_act(severity) + return - attack_self(mob/living/user as mob) - switch(mode) - if(2) - mode = 0 - charge_cost = 50 - fire_sound = 'sound/weapons/Taser.ogg' - to_chat(user, "\red [src.name] is now set to stun.") - projectile_type = "/obj/item/projectile/energy/electrode" - if(0) - mode = 1 - charge_cost = 100 - fire_sound = 'sound/weapons/Laser.ogg' - to_chat(user, "\red [src.name] is now set to kill.") - projectile_type = "/obj/item/projectile/beam" - if(1) - mode = 2 - charge_cost = 200 - fire_sound = 'sound/weapons/pulse.ogg' - to_chat(user, "\red [src.name] is now set to DESTROY.") - projectile_type = "/obj/item/projectile/beam/pulse" - return - - isHandgun() - return 0 - -/obj/item/weapon/gun/energy/pulse_rifle/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(charge_cost) - in_chamber = new projectile_type(src) - return 1 +/obj/item/weapon/gun/energy/pulse/isHandgun() return 0 +/obj/item/weapon/gun/energy/pulse/cyborg -/obj/item/weapon/gun/energy/pulse_rifle/destroyer - name = "pulse destroyer" - desc = "A heavy-duty, pulse-based energy weapon." - cell_type = "/obj/item/weapon/stock_parts/cell/infinite" +/obj/item/weapon/gun/energy/pulse/cyborg/newshot() + ..() + robocharge() - attack_self(mob/living/user as mob) - to_chat(user, "\red [src.name] has three settings, and they are all DESTROY.") - -/obj/item/weapon/gun/energy/pulse_rifle/carbine +/obj/item/weapon/gun/energy/pulse/carbine name = "pulse carbine" desc = "A compact variant of the pulse rifle with less firepower but easier storage." w_class = 3 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 - -/obj/item/weapon/gun/energy/pulse_rifle/pistol +/obj/item/weapon/gun/energy/pulse/pistol name = "pulse pistol" desc = "A pulse rifle in an easily concealed handgun package with low capacity." w_class = 2 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_rifle/pistol/isHandgun() +/obj/item/weapon/gun/energy/pulse/pistol/isHandgun() return 1 -/obj/item/weapon/gun/energy/pulse_rifle/pistol/m1911 +/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 + ammo_type = list(/obj/item/ammo_casing/energy/laser/pulse) + +/obj/item/weapon/gun/energy/pulse/destroyer/attack_self(mob/living/user) + to_chat(user, "[name] has three settings, and they are all DESTROY.") + +/obj/item/weapon/gun/energy/pulse/destroyer/annihilator + name = "pulse ANNIHILATOR" + desc = "For when the situation calls for a little more than a pulse destroyer." + ammo_type = list(/obj/item/ammo_casing/energy/laser/scatter/pulse) + +/obj/item/weapon/gun/energy/pulse/pistol/m1911 name = "\improper M1911-P" 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-p" + icon_state = "m1911" item_state = "gun" - cell_type = "/obj/item/weapon/stock_parts/cell/infinite" - isHandgun() - return 1 \ No newline at end of file + 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 d6c0ad7beb3..3c4766fd58b 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -8,7 +8,10 @@ w_class = 5.0 flags = CONDUCT slot_flags = SLOT_BACK - projectile_type = "/obj/item/projectile/ion" + ammo_type = list(/obj/item/ammo_casing/energy/ion) + ammo_x_offset = 3 + flight_x_offset = 17 + flight_y_offset = 9 /obj/item/weapon/gun/energy/ionrifle/emp_act(severity) return @@ -17,10 +20,12 @@ name = "ion carbine" desc = "The MK.II Prototype Ion Projector is a lightweight carbine version of the larger ion rifle, built to be ergonomic and efficient." icon_state = "ioncarbine" - item_state = "ioncarbine" origin_tech = "combat=4;magnets=4;materials=4" w_class = 3 slot_flags = SLOT_BELT + ammo_x_offset = 2 + flight_x_offset = 18 + flight_y_offset = 11 /obj/item/weapon/gun/energy/decloner name = "biological demolecularisor" @@ -28,65 +33,38 @@ icon_state = "decloner" fire_sound = 'sound/weapons/pulse3.ogg' origin_tech = "combat=5;materials=4;powerstorage=3" - projectile_type = "/obj/item/projectile/energy/declone" + ammo_type = list(/obj/item/ammo_casing/energy/declone) + ammo_x_offset = 1 +/obj/item/weapon/gun/energy/decloner/update_icon() + ..() + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + if(power_supply.charge > shot.e_cost) + overlays += "decloner_spin" /obj/item/weapon/gun/energy/floragun name = "floral somatoray" desc = "A tool that discharges controlled radiation which induces mutation in plant cells." - icon_state = "floramut100" + icon_state = "flora" item_state = "gun" fire_sound = 'sound/effects/stealthoff.ogg' - projectile_type = "/obj/item/projectile/energy/floramut" + ammo_type = list(/obj/item/ammo_casing/energy/flora/yield, /obj/item/ammo_casing/energy/flora/mut) origin_tech = "materials=2;biotech=3;powerstorage=3" - modifystate = "floramut" - var/mode = 0 //0 = mutate, 1 = yield boost - needs_permit = 0 - - self_recharge = 1 - -/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 1000 - to_chat(user, "\red The [src.name] is now set to increase yield.") - projectile_type = "/obj/item/projectile/energy/florayield" - modifystate = "florayield" - if(1) - mode = 0 - charge_cost = 1000 - to_chat(user, "\red The [src.name] is now set to induce mutations.") - projectile_type = "/obj/item/projectile/energy/floramut" - modifystate = "floramut" - update_icon() - return - - -/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, flag) - - if(flag && istype(target,/obj/machinery/portable_atmospherics/hydroponics)) - var/obj/machinery/portable_atmospherics/hydroponics/tray = target - if(process_chambered()) - user.visible_message("\red \The [user] fires \the [src] into \the [tray]!") - Fire(target,user) - return - - ..() + modifystate = 1 + ammo_x_offset = 1 + selfcharge = 1 /obj/item/weapon/gun/energy/meteorgun name = "meteor gun" desc = "For the love of god, make sure you're aiming this the right way!" + icon = 'icons/obj/guns/projectile.dmi' icon_state = "riotgun" item_state = "c20r" w_class = 4 - projectile_type = "/obj/item/projectile/meteor" - cell_type = "/obj/item/weapon/stock_parts/cell/potato" + ammo_type = list(/obj/item/ammo_casing/energy/meteor) + cell_type = /obj/item/weapon/stock_parts/cell/potato clumsy_check = 0 //Admin spawn only, might as well let clowns use it. - - self_recharge = 1 - recharge_time = 5 //Time it takes for shots to recharge (in ticks) - + selfcharge = 1 /obj/item/weapon/gun/energy/meteorgun/pen name = "meteor pen" @@ -98,119 +76,116 @@ righthand_file = 'icons/mob/inhands/items_righthand.dmi' w_class = 1 - /obj/item/weapon/gun/energy/mindflayer name = "\improper Mind Flayer" desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon." icon_state = "xray" - projectile_type = "/obj/item/projectile/beam/mindflayer" - fire_sound = 'sound/weapons/Laser.ogg' - -obj/item/weapon/gun/energy/staff/focus - name = "mental focus" - desc = "An artefact that channels the will of the user into destructive bolts of force. If you aren't careful with it, you might poke someone's brain out." - icon = 'icons/obj/wizard.dmi' - icon_state = "focus" - item_state = "focus" - projectile_type = "/obj/item/projectile/forcebolt" - /* - attack_self(mob/living/user as mob) - if(projectile_type == "/obj/item/projectile/forcebolt") - charge_cost = 200 - to_chat(user, "\red The [src.name] will now strike a small area.") - projectile_type = "/obj/item/projectile/forcebolt/strong" - else - charge_cost = 100 - to_chat(user, "\red The [src.name] will now strike only a single person.") - projectile_type = "/obj/item/projectile/forcebolt" - */ - -/obj/item/weapon/gun/energy/clown - name = "HONK Rifle" - desc = "Clown Planet's finest." - icon_state = "energy" - projectile_type = "/obj/item/projectile/clown" - fire_sound = 'sound/weapons/Gunshot_smg.ogg' - clumsy_check = 0 - - - -/obj/item/weapon/gun/energy/toxgun - name = "plasma pistol" - desc = "A specialized firearm designed to fire lethal bolts of toxins." - icon_state = "toxgun" - fire_sound = 'sound/effects/stealthoff.ogg' - w_class = 3.0 - origin_tech = "combat=4;plasmatech=3" - projectile_type = "/obj/item/projectile/energy/plasma" - -/obj/item/weapon/gun/energy/sniperrifle - name = "L.W.A.P. Sniper Rifle" - desc = "A rifle constructed of lightweight materials, fitted with a SMART aiming-system scope." - icon = 'icons/obj/gun.dmi' - icon_state = "esniper" - fire_sound = 'sound/weapons/marauder.ogg' - origin_tech = "combat=6;materials=5;powerstorage=4" - projectile_type = "/obj/item/projectile/beam/sniper" - slot_flags = SLOT_BACK - charge_cost = 2500 - fire_delay = 50 - w_class = 4.0 - zoomable = TRUE - zoom_amt = 7 //Long range, enough to see in front of you, but no tiles behind you. - + item_state = null + ammo_type = list(/obj/item/ammo_casing/energy/mindflayer) + ammo_x_offset = 2 /obj/item/weapon/gun/energy/kinetic_accelerator name = "proto-kinetic accelerator" desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." icon_state = "kineticgun" item_state = "kineticgun" - projectile_type = "/obj/item/projectile/kinetic" - fire_sound = 'sound/weapons/Kenetic_accel.ogg' - charge_cost = 5000 - cell_type = "/obj/item/weapon/stock_parts/cell/emproof" - needs_permit = 0 // Aparently these are safe to carry? I'm sure Golliaths would disagree. - fire_delay = 16 //Because guncode is bad and you can bug the reload for rapid fire otherwise. - var/recently_fired = 0 + ammo_type = list(/obj/item/ammo_casing/energy/kinetic) + cell_type = /obj/item/weapon/stock_parts/cell/emproof + // Apparently these are safe to carry? I'm sure goliaths would disagree. + needs_permit = 0 + var/overheat_time = 16 + unique_rename = 1 + weapon_weight = WEAPON_LIGHT + origin_tech = "combat=2;powerstorage=1" + var/holds_charge = FALSE + var/unique_frequency = FALSE // modified by KA modkits + + var/overheat = FALSE /obj/item/weapon/gun/energy/kinetic_accelerator/super name = "super-kinetic accelerator" desc = "An upgraded, superior version of the proto-kinetic accelerator." icon_state = "kineticgun_u" - projectile_type = "/obj/item/projectile/kinetic/super" - fire_delay = 15 + ammo_type = list(/obj/item/ammo_casing/energy/kinetic/super) + overheat_time = 15 origin_tech = "combat=3;powerstorage=2" /obj/item/weapon/gun/energy/kinetic_accelerator/hyper name = "hyper-kinetic accelerator" desc = "An upgraded, even more superior version of the proto-kinetic accelerator." icon_state = "kineticgun_h" - projectile_type = "/obj/item/projectile/kinetic/hyper" - fire_delay = 13 + ammo_type = list(/obj/item/ammo_casing/energy/kinetic/hyper) + overheat_time = 14 origin_tech = "combat=4;powerstorage=3" /obj/item/weapon/gun/energy/kinetic_accelerator/cyborg - flags = NODROP + holds_charge = TRUE + unique_frequency = TRUE -/obj/item/weapon/gun/energy/kinetic_accelerator/Fire() - if(!recently_fired) - recently_fired = 1 - spawn(fire_delay) - reload(usr) - ..() +/obj/item/weapon/gun/energy/kinetic_accelerator/New() + . = ..() + if(!holds_charge) + empty() + +/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot() + . = ..() + attempt_reload() + +/obj/item/weapon/gun/energy/kinetic_accelerator/equipped(mob/user) + . = ..() + if(!can_shoot()) + attempt_reload() + +/obj/item/weapon/gun/energy/kinetic_accelerator/dropped() + . = ..() + if(!holds_charge) + // Put it on a delay because moving item from slot to hand + // calls dropped(). + spawn(1) + if(!ismob(loc)) + empty() + +/obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty() + power_supply.use(5000) + update_icon() + +/obj/item/weapon/gun/energy/kinetic_accelerator/proc/attempt_reload() + if(overheat) + return + overheat = TRUE + + var/carried = 0 + if(!unique_frequency) + for(var/obj/item/weapon/gun/energy/kinetic_accelerator/K in \ + loc.GetAllContents()) + + carried++ + + carried = max(carried, 1) + else + carried = 1 + + spawn(overheat_time * carried) + reload() + overheat = FALSE /obj/item/weapon/gun/energy/kinetic_accelerator/emp_act(severity) return -/obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload(mob/living/user) +/obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload() power_supply.give(5000) - if(!silenced) - playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) - else if(user) - to_chat(usr, "You silently charge [src].") - recently_fired = 0 + if(!suppressed) + playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) + else + to_chat(loc, "[src] silently charges up.") update_icon() +/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon() + if(!can_shoot()) + icon_state = "[initial(icon_state)]_empty" + else + icon_state = initial(icon_state) + /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow name = "mini energy crossbow" desc = "A weapon favored by syndicate stealth specialists." @@ -219,10 +194,17 @@ obj/item/weapon/gun/energy/staff/focus w_class = 2 materials = list(MAT_METAL=2000) origin_tech = "combat=2;magnets=2;syndicate=5" - silenced = 1 - projectile_type = "/obj/item/projectile/energy/bolt" - fire_sound = 'sound/weapons/Genhit.ogg' - fire_delay = 20 + suppressed = 1 + ammo_type = list(/obj/item/ammo_casing/energy/bolt) + weapon_weight = WEAPON_LIGHT + unique_rename = 0 + overheat_time = 20 + holds_charge = TRUE + unique_frequency = TRUE + +/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/ninja + name = "energy dart thrower" + ammo_type = list(/obj/item/ammo_casing/energy/dart) /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/large name = "energy crossbow" @@ -231,8 +213,8 @@ obj/item/weapon/gun/energy/staff/focus w_class = 3 materials = list(MAT_METAL=4000) origin_tech = "combat=2;magnets=2;syndicate=3" //can be further researched for more syndie tech - silenced = 0 - projectile_type = "/obj/item/projectile/energy/bolt/large" + suppressed = 0 + ammo_type = list(/obj/item/ammo_casing/energy/bolt/large) /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/large/cyborg desc = "One and done!" @@ -240,27 +222,35 @@ obj/item/weapon/gun/energy/staff/focus origin_tech = null materials = list() +/obj/item/weapon/gun/energy/kinetic_accelerator/suicide_act(mob/user) + if(!suppressed) + playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) + user.visible_message("[user] cocks the [name] and pretends to blow \his brains out! It looks like \he's trying to commit suicide!") + shoot_live_shot() + return (OXYLOSS) + /obj/item/weapon/gun/energy/plasmacutter name = "plasma cutter" desc = "A mining tool capable of expelling concentrated plasma bursts. You could use it to cut limbs off of xenos! Or, you know, mine stuff." icon_state = "plasmacutter" item_state = "plasmacutter" - modifystate = "plasmacutter" + modifystate = -1 origin_tech = "combat=1;materials=3;magnets=2;plasmatech=2;engineering=1" - projectile_type = /obj/item/projectile/plasma + ammo_type = list(/obj/item/ammo_casing/energy/plasma) fire_sound = 'sound/weapons/laser.ogg' flags = CONDUCT | OPENCONTAINER attack_verb = list("attacked", "slashed", "cut", "sliced") - charge_cost = 250 - fire_delay = 15 + force = 12 + sharp = 1 + edge = 1 can_charge = 0 /obj/item/weapon/gun/energy/plasmacutter/examine(mob/user) - ..(user) + ..() if(power_supply) to_chat(user, "[src] is [round(power_supply.percent())]% charged.") -/obj/item/weapon/gun/energy/plasmacutter/attackby(var/obj/item/A, var/mob/user) +/obj/item/weapon/gun/energy/plasmacutter/attackby(obj/item/A, mob/user) if(istype(A, /obj/item/stack/sheet/mineral/plasma)) var/obj/item/stack/sheet/S = A S.use(1) @@ -273,92 +263,35 @@ obj/item/weapon/gun/energy/staff/focus else ..() +/obj/item/weapon/gun/energy/plasmacutter/update_icon() + return + /obj/item/weapon/gun/energy/plasmacutter/adv name = "advanced plasma cutter" icon_state = "adv_plasmacutter" modifystate = "adv_plasmacutter" origin_tech = "combat=3;materials=4;magnets=3;plasmatech=3;engineering=2" - projectile_type = /obj/item/projectile/plasma/adv - fire_delay = 10 - charge_cost = 100 - -/obj/item/weapon/gun/energy/disabler - name = "disabler" - desc = "A self-defense weapon that exhausts organic targets, weakening them until they collapse." - icon_state = "disabler" - item_state = null - projectile_type = /obj/item/projectile/beam/disabler - fire_sound = 'sound/weapons/taser2.ogg' - cell_type = "/obj/item/weapon/stock_parts/cell" - charge_cost = 500 - -/obj/item/weapon/gun/energy/disabler/cyborg - name = "cyborg disabler" - desc = "An integrated disabler that draws from a cyborg's power cell. This weapon contains a limiter to prevent the cyborg's power cell from overheating." - - self_recharge = 1 - use_external_power = 1 - recharge_time = 2.5 - - -/* 3d printer 'pseudo guns' for borgs */ - -/obj/item/weapon/gun/energy/printer - name = "cyborg lmg" - desc = "A machinegun that fires 3d-printed flachettes slowly regenerated using a cyborg's internal power source." - icon_state = "l6closed0" - icon = 'icons/obj/gun.dmi' - fire_sound = 'sound/weapons/Gunshot_smg.ogg' - cell_type = "/obj/item/weapon/stock_parts/cell/secborg" - projectile_type = "/obj/item/projectile/bullet/midbullet3" - charge_cost = 200 //Yeah, let's NOT give them a 300 round clip that recharges, 20 is more reasonable and will actually hurt the borg's battery for overuse. - - self_recharge = 1 - use_external_power = 1 - recharge_time = 5 - -/obj/item/weapon/gun/energy/printer/update_icon() - return + ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv) + force = 15 /obj/item/weapon/gun/energy/wormhole_projector name = "bluespace wormhole projector" desc = "A projector that emits high density quantum-coupled bluespace beams." - projectile_type = "/obj/item/projectile/beam/wormhole" - charge_cost = 0 - fire_sound = "sound/weapons/pulse3.ogg" + ammo_type = list(/obj/item/ammo_casing/energy/wormhole, /obj/item/ammo_casing/energy/wormhole/orange) item_state = null icon_state = "wormhole_projector100" - modifystate = "wormhole_projector" var/obj/effect/portal/blue var/obj/effect/portal/orange - var/mode = 0 //0 = blue 1 = orange +/obj/item/weapon/gun/energy/wormhole_projector/update_icon() + icon_state = "[initial(icon_state)][select]" + item_state = icon_state + return -/obj/item/weapon/gun/energy/wormhole_projector/attack_self(mob/living/user as mob) - switch_modes() - -/obj/item/weapon/gun/energy/wormhole_projector/proc/switch_modes(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - to_chat(user, "[name] is now set to orange.") - projectile_type = "/obj/item/projectile/beam/wormhole/orange" - modifystate = "wormhole_projector_orange" - if(1) - mode = 0 - to_chat(user, "[name] is now set to blue.") - projectile_type = "/obj/item/projectile/beam/wormhole" - modifystate = "wormhole_projector" - update_icon() - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - -/obj/item/weapon/gun/energy/wormhole_projector/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0) +/obj/item/weapon/gun/energy/wormhole_projector/process_chamber() ..() - switch_modes(user) + select_fire() /obj/item/weapon/gun/energy/wormhole_projector/proc/portal_destroyed(obj/effect/portal/P) if(P.icon_state == "portal") @@ -373,7 +306,6 @@ obj/item/weapon/gun/energy/staff/focus /obj/item/weapon/gun/energy/wormhole_projector/proc/create_portal(obj/item/projectile/beam/wormhole/W) var/obj/effect/portal/P = new /obj/effect/portal(get_turf(W), null, src) P.precision = 0 - P.failchance = 0 if(W.name == "bluespace beam") qdel(blue) blue = P @@ -383,4 +315,270 @@ obj/item/weapon/gun/energy/staff/focus orange = P if(orange && blue) blue.target = get_turf(orange) - orange.target = get_turf(blue) \ No newline at end of file + orange.target = get_turf(blue) + +/* 3d printer 'pseudo guns' for borgs */ + +/obj/item/weapon/gun/energy/printer + name = "cyborg lmg" + 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 + ammo_type = list(/obj/item/ammo_casing/energy/c3dbullet) + can_charge = 0 + +/obj/item/weapon/gun/energy/printer/update_icon() + return + +/obj/item/weapon/gun/energy/printer/emp_act() + return + +/obj/item/weapon/gun/energy/printer/newshot() + ..() + robocharge() + +/obj/item/weapon/gun/energy/laser/instakill + name = "instakill rifle" + icon_state = "instagib" + item_state = "instagib" + desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit." + ammo_type = list(/obj/item/ammo_casing/energy/instakill) + force = 60 + origin_tech = null + +/obj/item/weapon/gun/energy/laser/instakill/emp_act() //implying you could stop the instagib + return + +/obj/item/weapon/gun/energy/laser/instakill/red + desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a red design." + icon_state = "instagibred" + item_state = "instagibred" + ammo_type = list(/obj/item/ammo_casing/energy/instakill/red) + +/obj/item/weapon/gun/energy/laser/instakill/blue + desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a blue design." + icon_state = "instagibblue" + item_state = "instagibblue" + ammo_type = list(/obj/item/ammo_casing/energy/instakill/blue) + +/obj/item/weapon/gun/energy/clown + name = "HONK Rifle" + desc = "Clown Planet's finest." + 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" + desc = "A specialized firearm designed to fire lethal bolts of toxins." + icon_state = "toxgun" + fire_sound = 'sound/effects/stealthoff.ogg' + w_class = 3 + origin_tech = "combat=4;plasmatech=3" + ammo_type = list(/obj/item/ammo_casing/energy/toxplasma) + shaded_charge = 1 + +/obj/item/weapon/gun/energy/sniperrifle + name = "L.W.A.P. Sniper Rifle" + desc = "A rifle constructed of lightweight materials, fitted with a SMART aiming-system scope." + icon_state = "esniper" + origin_tech = "combat=6;materials=5;powerstorage=4" + ammo_type = list(/obj/item/ammo_casing/energy/sniper) + slot_flags = SLOT_BACK + w_class = 4 + zoomable = TRUE + zoom_amt = 7 //Long range, enough to see in front of you, but no tiles behind you. + shaded_charge = 1 + +/obj/item/weapon/gun/energy/temperature + name = "temperature gun" + icon = 'icons/obj/guns/gun_temperature.dmi' + icon_state = "tempgun_4" + item_state = "tempgun_4" + slot_flags = SLOT_BACK + w_class = 4 + fire_sound = 'sound/weapons/pulse3.ogg' + desc = "A gun that changes the body temperature of its targets." + var/temperature = 300 + var/target_temperature = 300 + var/e_cost = 1000 + 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 + + var/powercost = "" + var/powercostcolor = "" + + var/emagged = 0 //ups the temperature cap from 500 to 1000, targets hit by beams over 500 Kelvin will burst into flames + var/dat = "" + +/obj/item/weapon/gun/energy/temperature/New() + ..() + update_icon() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/temperature/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/weapon/gun/energy/temperature/newshot() + ..(temperature, e_cost) + +/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) + user.set_machine(src) + update_dat() + user << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x120") + onclose(user, "tempgun") + +/obj/item/weapon/gun/energy/temperature/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/emag) && !emagged) + emagged = 1 + to_chat(user, "You double the gun's temperature cap! Targets hit by searing beams will burst into flames!") + desc = "A gun that changes the body temperature of its targets. Its temperature cap has been hacked." + +/obj/item/weapon/gun/energy/temperature/Topic(href, href_list) + if (..()) + return + usr.set_machine(src) + add_fingerprint(usr) + + if(href_list["temp"]) + var/amount = text2num(href_list["temp"]) + if(amount > 0) + target_temperature = min((500 + 500*emagged), target_temperature+amount) + else + target_temperature = max(0, target_temperature+amount) + if (istype(loc, /mob)) + attack_self(loc) + add_fingerprint(usr) + return + +/obj/item/weapon/gun/energy/temperature/process() + switch(temperature) + if(0 to 100) + e_cost = 3000 + powercost = "High" + if(100 to 250) + e_cost = 2000 + powercost = "Medium" + if(251 to 300) + e_cost = 1000 + powercost = "Low" + if(301 to 400) + e_cost = 2000 + powercost = "Medium" + if(401 to 1000) + e_cost = 3000 + powercost = "High" + switch(powercost) + if("High") powercostcolor = "orange" + if("Medium") powercostcolor = "green" + else powercostcolor = "blue" + if(target_temperature != temperature) + var/difference = abs(target_temperature - temperature) + if(difference >= (10 + 40*emagged)) //so emagged temp guns adjust their temperature much more quickly + if(target_temperature < temperature) + temperature -= (10 + 40*emagged) + else + temperature += (10 + 40*emagged) + else + temperature = target_temperature + update_icon() + + if (istype(loc, /mob/living/carbon)) + var /mob/living/carbon/M = loc + if (src == M.machine) + update_dat() + M << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") + return + +/obj/item/weapon/gun/energy/temperature/proc/update_dat() + dat = "" + dat += "Current output temperature: " + if(temperature > 500) + dat += "[temperature] ([round(temperature-T0C)]°C)" + dat += " SEARING!" + else if(temperature > (T0C + 50)) + dat += "[temperature] ([round(temperature-T0C)]°C)" + else if(temperature > (T0C - 50)) + dat += "[temperature] ([round(temperature-T0C)]°C)" + else + dat += "[temperature] ([round(temperature-T0C)]°C)" + dat += "
    " + dat += "Target output temperature: " //might be string idiocy, but at least it's easy to read + dat += "- " + dat += "- " + dat += "- " + dat += "[target_temperature] " + dat += "+ " + dat += "+ " + dat += "+" + dat += "
    " + dat += "Power cost: " + dat += "[powercost]" + +/obj/item/weapon/gun/energy/temperature/proc/update_temperature() + switch(temperature) + if(501 to INFINITY) + item_state = "tempgun_8" + if(400 to 500) + item_state = "tempgun_7" + if(360 to 400) + item_state = "tempgun_6" + if(335 to 360) + item_state = "tempgun_5" + if(295 to 335) + item_state = "tempgun_4" + if(260 to 295) + item_state = "tempgun_3" + if(200 to 260) + item_state = "tempgun_2" + if(120 to 260) + item_state = "tempgun_1" + if(-INFINITY to 120) + item_state = "tempgun_0" + icon_state = item_state + +/obj/item/weapon/gun/energy/temperature/update_icon() + overlays = 0 + update_temperature() + update_user() + update_charge() + +/obj/item/weapon/gun/energy/temperature/proc/update_user() + if (istype(loc,/mob/living/carbon)) + var/mob/living/carbon/M = loc + M.update_inv_back() + M.update_inv_l_hand() + M.update_inv_r_hand() + +/obj/item/weapon/gun/energy/temperature/proc/update_charge() + var/charge = power_supply.charge + switch(charge) + if(9000 to INFINITY) overlays += "900" + if(8000 to 9000) overlays += "800" + if(7000 to 8000) overlays += "700" + if(6000 to 7000) overlays += "600" + if(5000 to 6000) overlays += "500" + if(4000 to 5000) overlays += "400" + if(3000 to 4000) overlays += "300" + 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 37d22ba5ff7..9728a9442e1 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -1,84 +1,67 @@ - /obj/item/weapon/gun/energy/taser name = "taser gun" desc = "A small, low capacity gun used for non-lethal takedowns." icon_state = "taser" item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" - cell_type = "/obj/item/weapon/stock_parts/cell/crap" - fire_delay = 15 + ammo_type = list(/obj/item/ammo_casing/energy/electrode) + ammo_x_offset = 3 + cell_type = /obj/item/weapon/stock_parts/cell/crap /obj/item/weapon/gun/energy/taser/mounted name = "mounted taser gun" - self_recharge = 1 + selfcharge = 1 use_external_power = 1 /obj/item/weapon/gun/energy/taser/cyborg name = "taser gun" desc = "A small, low capacity gun used for non-lethal takedowns." icon_state = "taser" - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" - cell_type = "/obj/item/weapon/stock_parts/cell/secborg" + cell_type = /obj/item/weapon/stock_parts/cell/secborg - self_recharge = 1 - recharge_time = 10 //Time it takes for shots to recharge (in ticks) +/obj/item/weapon/gun/energy/disabler/cyborg/newshot() + ..() + robocharge() /obj/item/weapon/gun/energy/shock_revolver name = "tesla revolver" desc = "A high-tech revolver that fires internal, reusable shock cartridges in a revolving cylinder. The cartridges can be recharged using conventional rechargers." icon_state = "stunrevolver" item_state = "gun" - fire_sound = 'sound/weapons/gunshot.ogg' - projectile_type = "/obj/item/projectile/energy/shock_revolver" - charge_cost = 2000 + ammo_type = list(/obj/item/ammo_casing/energy/shock_revolver) can_flashlight = 0 + shaded_charge = 1 -/obj/item/projectile/energy/shock_revolver - name = "shock bolt" - icon_state = "purple_laser" - var/chain +/obj/item/weapon/gun/energy/gun/advtaser + name = "hybrid taser" + desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams." + icon_state = "advtaser" + ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/disabler) + origin_tech = null + ammo_x_offset = 2 -/obj/item/projectile/energy/shock_revolver/OnFired() - spawn(1) - chain = Beam(firer, icon_state="purple_lightning", icon = 'icons/effects/effects.dmi',time=1000, maxdistance = 30) +/obj/item/weapon/gun/energy/gun/advtaser/cyborg + name = "cyborg taser" + desc = "An integrated hybrid taser that draws directly from a cyborg's power cell. The weapon contains a limiter to prevent the cyborg's power cell from overheating." + can_flashlight = 0 + can_charge = 0 -/obj/item/projectile/energy/shock_revolver/on_hit(atom/target) - . = ..() - if(isliving(target)) - tesla_zap(src, 3, 10000) - qdel(chain) +/obj/item/weapon/gun/energy/gun/advtaser/cyborg/newshot() + ..() + robocharge() -/obj/item/weapon/gun/energy/crossbow - name = "mini energy-crossbow" - desc = "A weapon favored by many of the syndicates stealth specialists." - icon_state = "crossbow" - w_class = 2.0 - item_state = "crossbow" - materials = list(MAT_METAL=2000) - origin_tech = "combat=2;magnets=2;syndicate=5" - silenced = 1 - fire_sound = 'sound/weapons/Genhit.ogg' - projectile_type = "/obj/item/projectile/energy/bolt" - cell_type = "/obj/item/weapon/stock_parts/cell/crap" - - self_recharge = 1 - -/obj/item/weapon/gun/energy/crossbow/ninja - name = "energy dart thrower" - projectile_type = /obj/item/projectile/energy/dart - -/obj/item/weapon/gun/energy/crossbow/update_icon() - return -/obj/item/weapon/gun/energy/crossbow/largecrossbow - name = "Energy Crossbow" - desc = "A weapon favored by syndicate carp hunters." - icon_state = "crossbowlarge" - silenced = 0 - w_class = 3.0 - force = 10 - materials = list(MAT_METAL=4000) - projectile_type = "/obj/item/projectile/energy/bolt/large" +/obj/item/weapon/gun/energy/disabler + name = "disabler" + desc = "A self-defense weapon that exhausts organic targets, weakening them until they collapse." + icon_state = "disabler" + item_state = null + ammo_type = list(/obj/item/ammo_casing/energy/disabler) + ammo_x_offset = 3 +/obj/item/weapon/gun/energy/disabler/cyborg + name = "cyborg disabler" + desc = "An integrated disabler that draws from a cyborg's power cell. This weapon contains a limiter to prevent the cyborg's power cell from overheating." + can_charge = 0 +/obj/item/weapon/gun/energy/disabler/cyborg/newshot() + ..() + robocharge() diff --git a/code/modules/projectiles/guns/energy/telegun.dm b/code/modules/projectiles/guns/energy/telegun.dm index 3819401e031..e8a882d7c80 100644 --- a/code/modules/projectiles/guns/energy/telegun.dm +++ b/code/modules/projectiles/guns/energy/telegun.dm @@ -5,11 +5,10 @@ desc = "An extremely high-tech bluespace energy gun capable of teleporting targets to far off locations." icon_state = "telegun" item_state = "ionrifle" - fire_sound = 'sound/weapons/wave.ogg' origin_tech = "combat=6;materials=7;powerstorage=5;bluespace=5;syndicate=4" - cell_type = "/obj/item/weapon/stock_parts/cell/crap" - projectile_type = "/obj/item/projectile/energy/teleport" - charge_cost = 1250 + 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 /obj/item/weapon/gun/energy/telegun/Destroy() @@ -36,4 +35,7 @@ L[tmpname] = R var/desc = input("Please select a location to lock in.", "Telegun Target Interface") in L - teleport_target = L[desc] \ No newline at end of file + teleport_target = L[desc] + +/obj/item/weapon/gun/energy/telegun/newshot() + ..(teleport_target) diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm deleted file mode 100644 index 1e0eb5d08c2..00000000000 --- a/code/modules/projectiles/guns/energy/temperature.dm +++ /dev/null @@ -1,182 +0,0 @@ -/obj/item/weapon/gun/energy/temperature - name = "temperature gun" - icon = 'icons/obj/gun_temperature.dmi' - icon_state = "tempgun_4" - item_state = "tempgun_4" - slot_flags = SLOT_BACK - w_class = 4.0 - fire_sound = 'sound/weapons/pulse3.ogg' - desc = "A gun that changes the body temperature of its targets." - var/temperature = 300 - var/target_temperature = 300 - charge_cost = 90 - origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2" - - projectile_type = /obj/item/projectile/temp - cell_type = /obj/item/weapon/stock_parts/cell/temperaturegun - - var/powercost = "" - var/powercostcolor = "" - - var/emagged = 0 //ups the temperature cap from 500 to 1000, targets hit by beams over 500 Kelvin will burst into flames - var/dat = "" - -/obj/item/weapon/gun/energy/temperature/New() - ..() - update_icon() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/temperature/Destroy() - processing_objects.Remove(src) - return ..() - - -/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) - user.set_machine(src) - update_dat() - - user << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x120") - onclose(user, "tempgun") - -/obj/item/weapon/gun/energy/temperature/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/emag) && !emagged) - emagged = 1 - to_chat(user, "You double the gun's temperature cap! Targets hit by searing beams will burst into flames!") - desc = "A gun that changes the body temperature of its targets. Its temperature cap has been hacked." - -/obj/item/weapon/gun/energy/temperature/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - add_fingerprint(usr) - - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - target_temperature = min((500 + 500*emagged), target_temperature+amount) - else - target_temperature = max(0, target_temperature+amount) - if (istype(loc, /mob)) - attack_self(loc) - add_fingerprint(usr) - return - - -/obj/item/weapon/gun/energy/temperature/process() - switch(temperature) - if(0 to 100) - charge_cost = 300 - powercost = "High" - if(100 to 250) - charge_cost = 180 - powercost = "Medium" - if(251 to 300) - charge_cost = 90 - powercost = "Low" - if(301 to 400) - charge_cost = 180 - powercost = "Medium" - if(401 to 1000) - charge_cost = 300 - powercost = "High" - switch(powercost) - if("High") powercostcolor = "orange" - if("Medium") powercostcolor = "green" - else powercostcolor = "blue" - if(target_temperature != temperature) - var/difference = abs(target_temperature - temperature) - if(difference >= (10 + 40*emagged)) //so emagged temp guns adjust their temperature much more quickly - if(target_temperature < temperature) - temperature -= (10 + 40*emagged) - else - temperature += (10 + 40*emagged) - else - temperature = target_temperature - update_icon() - - if (istype(loc, /mob/living/carbon)) - var /mob/living/carbon/M = loc - if (src == M.machine) - update_dat() - M << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") - - - if(power_supply) - power_supply.give(50) - update_icon() - return - -/obj/item/weapon/gun/energy/temperature/proc/update_dat() - dat = "" - dat += "Current output temperature: " - if(temperature > 500) - dat += "[temperature] ([round(temperature-T0C)]°C)" - dat += " SEARING!" - else if(temperature > (T0C + 50)) - dat += "[temperature] ([round(temperature-T0C)]°C)" - else if(temperature > (T0C - 50)) - dat += "[temperature] ([round(temperature-T0C)]°C)" - else - dat += "[temperature] ([round(temperature-T0C)]°C)" - dat += "
    " - dat += "Target output temperature: " //might be string idiocy, but at least it's easy to read - dat += "- " - dat += "- " - dat += "- " - dat += "[target_temperature] " - dat += "+ " - dat += "+ " - dat += "+" - dat += "
    " - dat += "Power cost: " - dat += "[powercost]" - -/obj/item/weapon/gun/energy/temperature/proc/update_temperature() - switch(temperature) - if(501 to INFINITY) - item_state = "tempgun_8" - if(400 to 500) - item_state = "tempgun_7" - if(360 to 400) - item_state = "tempgun_6" - if(335 to 360) - item_state = "tempgun_5" - if(295 to 335) - item_state = "tempgun_4" - if(260 to 295) - item_state = "tempgun_3" - if(200 to 260) - item_state = "tempgun_2" - if(120 to 260) - item_state = "tempgun_1" - if(-INFINITY to 120) - item_state = "tempgun_0" - icon_state = item_state - -/obj/item/weapon/gun/energy/temperature/proc/update_charge() - var/charge = power_supply.charge - switch(charge) - if(900 to INFINITY) overlays += "900" - if(800 to 900) overlays += "800" - if(700 to 800) overlays += "700" - if(600 to 700) overlays += "600" - if(500 to 600) overlays += "500" - if(400 to 500) overlays += "400" - if(300 to 400) overlays += "300" - if(200 to 300) overlays += "200" - if(100 to 200) overlays += "100" - if(-INFINITY to 100) overlays += "0" - -/obj/item/weapon/gun/energy/temperature/proc/update_user() - if (istype(loc,/mob/living/carbon)) - var/mob/living/carbon/M = loc - M.update_inv_back() - M.update_inv_l_hand() - M.update_inv_r_hand() - -/obj/item/weapon/gun/energy/temperature/update_icon() - overlays = 0 - update_temperature() - update_user() - update_charge() \ No newline at end of file diff --git a/code/modules/projectiles/guns/grenade_launcher.dm b/code/modules/projectiles/guns/grenade_launcher.dm new file mode 100644 index 00000000000..5abac9ebad9 --- /dev/null +++ b/code/modules/projectiles/guns/grenade_launcher.dm @@ -0,0 +1,54 @@ +/obj/item/weapon/gun/grenadelauncher + name = "grenade launcher" + desc = "a terrible, terrible thing. it's really awful!" + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "riotgun" + item_state = "riotgun" + w_class = 4 + throw_speed = 2 + throw_range = 10 + force = 5 + var/list/grenades = new/list() + var/max_grenades = 3 + + materials = list(MAT_METAL=2000) + +/obj/item/weapon/gun/grenadelauncher/examine(mob/user) + if(..(user, 2)) + to_chat(user, "[grenades.len] / [max_grenades] grenades.") + +/obj/item/weapon/gun/grenadelauncher/attackby(obj/item/I as obj, mob/user as mob, params) + if((istype(I, /obj/item/weapon/grenade))) + if(grenades.len < max_grenades) + if(!user.unEquip(I)) + return + I.loc = src + grenades += I + to_chat(user, "You put the grenade in the [name].") + to_chat(user, "[grenades.len] / [max_grenades] grenades.") + else + to_chat(user, "The grenade launcher cannot hold more grenades.") + +/obj/item/weapon/gun/grenadelauncher/afterattack(obj/target, mob/user , flag) + if(target == user) + return + + if(grenades.len) + fire_grenade(target,user) + else + to_chat(user, "The grenade launcher is empty.") + +/obj/item/weapon/gun/grenadelauncher/proc/fire_grenade(atom/target, mob/user) + user.visible_message("[user] fired a grenade!", \ + "You fire the grenade launcher!") + var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta! + grenades -= F + F.loc = user.loc + F.throw_at(target, 30, 2, user) + message_admins("[key_name_admin(user)] fired a grenade ([F.name]) from a grenade launcher ([name]).") + log_game("[key_name(user)] fired a grenade ([F.name]) from a grenade launcher ([name]).") + F.active = 1 + F.icon_state = initial(icon_state) + "_active" + playsound(user.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(15) + F.prime() diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index 13f92bcef86..0c7f54bb21a 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -1,35 +1,29 @@ /obj/item/weapon/gun/magic name = "staff of nothing" desc = "This staff is boring to watch because even though it came first you've seen everything it can do in other staves for years." - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/magic.dmi' icon_state = "staffofnothing" item_state = "staff" - lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' //not really a gun and some toys use these inhands - righthand_file = 'icons/mob/inhands/items_righthand.dmi' fire_sound = 'sound/weapons/emitter.ogg' + fire_sound_text = "energy blast" flags = CONDUCT w_class = 5 - var/projectile_type = /obj/item/projectile/magic var/max_charges = 6 var/charges = 0 var/recharge_rate = 4 var/charge_tick = 0 var/can_charge = 1 + var/ammo_type var/no_den_usage origin_tech = null clumsy_check = 0 + trigger_guard = TRIGGER_GUARD_ALLOW_ALL // Has no trigger at all, uses magic instead -/obj/item/weapon/gun/magic/emp_act(severity) - return + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' //not really a gun and some toys use these inhands + righthand_file = 'icons/mob/inhands/items_righthand.dmi' -/obj/item/weapon/gun/magic/process_chambered() - if(in_chamber) return 1 - if(!charges) return 0 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - return 1 - -/obj/item/weapon/gun/magic/afterattack(atom/target as mob, mob/living/user as mob, flag) +/obj/item/weapon/gun/magic/afterattack(atom/target, mob/living/user, flag) + newshot() if(no_den_usage) var/area/A = get_area(user) if(istype(A, /area/wizard_station)) @@ -38,22 +32,38 @@ else no_den_usage = 0 ..() - if(charges && !in_chamber && !flag) charges-- + +/obj/item/weapon/gun/magic/can_shoot() + return charges + +/obj/item/weapon/gun/magic/newshot(params) + if (charges && chambered) + chambered.newshot(params) + return + +/obj/item/weapon/gun/magic/process_chamber() + if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... + charges--//... drain a charge + return /obj/item/weapon/gun/magic/New() ..() charges = max_charges - if(can_charge) processing_objects.Add(src) + chambered = new ammo_type(src) + if(can_charge) + processing_objects.Add(src) /obj/item/weapon/gun/magic/Destroy() - if(can_charge) processing_objects.Remove(src) + if(can_charge) + processing_objects.Remove(src) return ..() /obj/item/weapon/gun/magic/process() charge_tick++ - if(charge_tick < recharge_rate || charges >= max_charges) return 0 + if(charge_tick < recharge_rate || charges >= max_charges) + return 0 charge_tick = 0 charges++ return 1 @@ -63,4 +73,9 @@ /obj/item/weapon/gun/magic/shoot_with_empty_chamber(mob/living/user as mob|obj) to_chat(user, "The [name] whizzles quietly.") - return \ No newline at end of file + return + +/obj/item/weapon/gun/magic/suicide_act(mob/user) + user.visible_message("[user] is twisting the [name] above \his head, releasing a magical blast! It looks like \he's trying to commit suicide.") + playsound(loc, fire_sound, 50, 1, -1) + return FIRELOSS diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index 16fc552397d..85b483b8363 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -4,49 +4,61 @@ obj/item/weapon/gun/magic/staff/ obj/item/weapon/gun/magic/staff/change name = "staff of change" desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" - projectile_type = "/obj/item/projectile/magic/change" + ammo_type = /obj/item/ammo_casing/magic/change icon_state = "staffofchange" item_state = "staffofchange" obj/item/weapon/gun/magic/staff/animate name = "staff of animation" desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." - projectile_type = "/obj/item/projectile/magic/animate" + ammo_type = /obj/item/ammo_casing/magic/animate icon_state = "staffofanimation" item_state = "staffofanimation" obj/item/weapon/gun/magic/staff/healing name = "staff of healing" desc = "An artefact that spits bolts of restoring magic which can remove ailments of all kinds and even raise the dead." - projectile_type = "/obj/item/projectile/magic/resurrection" + ammo_type = /obj/item/ammo_casing/magic/heal icon_state = "staffofhealing" item_state = "staffofhealing" +/obj/item/weapon/gun/magic/staff/healing/handle_suicide() //Stops people trying to commit suicide to heal themselves + return + obj/item/weapon/gun/magic/staff/chaos name = "staff of chaos" desc = "An artefact that spits bolts of chaotic magic that can potentially do anything." - projectile_type = "/obj/item/projectile/magic" + ammo_type = /obj/item/ammo_casing/magic/chaos icon_state = "staffofchaos" item_state = "staffofchaos" max_charges = 10 recharge_rate = 2 - no_den_usage = 1 -/obj/item/weapon/gun/magic/staff/chaos/process_chambered() //Snowflake proc, because this uses projectile_type instead of ammo_casing for whatever reason. - projectile_type = pick(typesof(/obj/item/projectile/magic)) - if(in_chamber) return 1 - if(!charges) return 0 - in_chamber = new projectile_type(src) - return 1 - obj/item/weapon/gun/magic/staff/door name = "staff of door creation" desc = "An artefact that spits bolts of transformative magic that can create doors in walls." - projectile_type = "/obj/item/projectile/magic/door" + ammo_type = /obj/item/ammo_casing/magic/door icon_state = "staffofdoor" item_state = "staffofdoor" max_charges = 10 recharge_rate = 2 + no_den_usage = 1 - no_den_usage = 1 \ No newline at end of file +/obj/item/weapon/gun/magic/staff/honk + name = "staff of the honkmother" + desc = "Honk" + fire_sound = "sound/items/airhorn.ogg" + ammo_type = /obj/item/ammo_casing/magic/honk + icon_state = "honker" + item_state = "honker" + max_charges = 4 + recharge_rate = 8 + +obj/item/weapon/gun/magic/staff/focus + name = "mental focus" + desc = "An artefact that channels the will of the user into destructive bolts of force. If you aren't careful with it, you might poke someone's brain out." + icon = 'icons/obj/wizard.dmi' + icon_state = "focus" + item_state = "focus" + ammo_type = list(/obj/item/ammo_casing/forcebolt) diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 6be4e0936bf..abde404e87d 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -1,21 +1,13 @@ /obj/item/weapon/gun/magic/wand/ name = "wand of nothing" desc = "It's not just a stick, it's a MAGIC stick!" - projectile_type = "/obj/item/projectile/magic" + ammo_type = /obj/item/ammo_casing/magic icon_state = "nothingwand" item_state = "wand" w_class = 2 can_charge = 0 max_charges = 100 //100, 50, 50, 34 (max charge distribution by 25%ths) var/variable_charges = 1 - var/drained = 0 - -/obj/item/projectile/magic/fireball/Range() - var/mob/living/L = locate(/mob/living) in (range(src, 1) - firer) - if(L && L.stat != DEAD) - Bump(L) //Magic Bullet #teachthecontroversy - return - ..() /obj/item/weapon/gun/magic/wand/New() if(prob(75) && variable_charges) //25% chance of listed max charges, 50% chance of 1/2 max charges, 25% chance of 1/3 max charges @@ -26,26 +18,21 @@ ..() /obj/item/weapon/gun/magic/wand/examine(mob/user) - ..(user) + ..() to_chat(user, "Has [charges] charge\s remaining.") -/obj/item/weapon/gun/magic/wand/attack_self(mob/living/user as mob) - if(charges) - zap_self(user) - else - to_chat(user, "The [name] whizzles quietly.") - ..() +/obj/item/weapon/gun/magic/wand/update_icon() + icon_state = "[initial(icon_state)][charges ? "" : "-drained"]" -/obj/item/weapon/gun/magic/wand/attack(atom/target as mob, mob/living/user as mob) + +/obj/item/weapon/gun/magic/wand/attack(atom/target, mob/living/user) if(target == user) return ..() -/obj/item/weapon/gun/magic/wand/afterattack(atom/target as mob, mob/living/user as mob) - if(!charges && !drained) - to_chat(user, "The [name] whizzles quietly.") - icon_state = "[icon_state]-drained" - drained = 1 +/obj/item/weapon/gun/magic/wand/afterattack(atom/target, mob/living/user) + if(!charges) + shoot_with_empty_chamber(user) return if(target == user) if(no_den_usage) @@ -53,74 +40,83 @@ if(istype(A, /area/wizard_station)) to_chat(user, "You know better than to violate the security of The Den, best wait until you leave to use [src].") return - else - no_den_usage = 0 + else + no_den_usage = 0 zap_self(user) else ..() + update_icon() -/obj/item/weapon/gun/magic/wand/proc/zap_self(mob/living/user as mob) - user.visible_message("[user] zaps \himself with [src]!") +/obj/item/weapon/gun/magic/wand/proc/zap_self(mob/living/user) + user.visible_message("[user] zaps \himself with [src].") + playsound(user, fire_sound, 50, 1) + user.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] zapped \himself with a [src]" + +///////////////////////////////////// +//WAND OF DEATH +///////////////////////////////////// /obj/item/weapon/gun/magic/wand/death name = "wand of death" desc = "This deadly wand overwhelms the victim's body with pure energy, slaying them without fail." - projectile_type = "/obj/item/projectile/magic/death" + ammo_type = /obj/item/ammo_casing/magic/death icon_state = "deathwand" max_charges = 3 //3, 2, 2, 1 -/obj/item/weapon/gun/magic/wand/death/zap_self(mob/living/user as mob) - if(alert(user, "You really want to zap yourself with the wand of death?",, "Yes", "No") == "Yes" && charges && user.get_active_hand() == src && isliving(user)) - var/message ="You irradiate yourself with pure energy! " - message += pick("Do not pass go. Do not collect 200 zorkmids.","You feel more confident in your spell casting skills.","You Die...","Do you want your possessions identified?") - to_chat(user, message) - user.adjustOxyLoss(500) - charges-- - ..() +/obj/item/weapon/gun/magic/wand/death/zap_self(mob/living/user) + var/message ="You irradiate yourself with pure energy! " + message += pick("Do not pass go. Do not collect 200 zorkmids.","You feel more confident in your spell casting skills.","You Die...","Do you want your possessions identified?") + to_chat(user, message) + user.adjustFireLoss(500) + charges-- + ..() + +///////////////////////////////////// +//WAND OF HEALING +///////////////////////////////////// /obj/item/weapon/gun/magic/wand/resurrection name = "wand of resurrection" desc = "This wand uses healing magics to heal and revive. They are rarely utilized within the Wizard Federation for some reason." - projectile_type = "/obj/item/projectile/magic/resurrection" + ammo_type = /obj/item/ammo_casing/magic/heal icon_state = "revivewand" max_charges = 3 //3, 2, 2, 1 -/obj/item/weapon/gun/magic/wand/resurrection/zap_self(mob/living/user as mob) - user.setToxLoss(0) - user.setOxyLoss(0) - user.setCloneLoss(0) - user.SetParalysis(0) - user.SetStunned(0) - user.SetWeakened(0) - user.radiation = 0 - user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss()) - user.reagents.clear_reagents() +/obj/item/weapon/gun/magic/wand/resurrection/zap_self(mob/living/user) + user.revive() to_chat(user, "You feel great!") charges-- ..() +///////////////////////////////////// +//WAND OF POLYMORPH +///////////////////////////////////// + /obj/item/weapon/gun/magic/wand/polymorph name = "wand of polymorph" desc = "This wand is attuned to chaos and will radically alter the victim's form." - projectile_type = "/obj/item/projectile/magic/change" + ammo_type = /obj/item/ammo_casing/magic/change icon_state = "polywand" max_charges = 10 //10, 5, 5, 4 -/obj/item/weapon/gun/magic/wand/polymorph/zap_self(mob/living/user as mob) - if(alert(user, "Your new form might not have arms to zap with... Continue?",, "Yes", "No") == "Yes" && charges && user.get_active_hand() == src && isliving(user)) - ..() //because the user mob ceases to exists by the time wabbajack fully resolves - wabbajack(user) - charges-- +/obj/item/weapon/gun/magic/wand/polymorph/zap_self(mob/living/user) + ..() //because the user mob ceases to exists by the time wabbajack fully resolves + wabbajack(user) + charges-- + +///////////////////////////////////// +//WAND OF TELEPORTATION +///////////////////////////////////// /obj/item/weapon/gun/magic/wand/teleport name = "wand of teleportation" desc = "This wand will wrench targets through space and time to move them somewhere else." - projectile_type = "/obj/item/projectile/magic/teleport" + ammo_type = /obj/item/ammo_casing/magic/teleport icon_state = "telewand" max_charges = 10 //10, 5, 5, 4 no_den_usage = 1 -/obj/item/weapon/gun/magic/wand/teleport/zap_self(mob/living/user as mob) +/obj/item/weapon/gun/magic/wand/teleport/zap_self(mob/living/user) do_teleport(user, user, 10) var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread() smoke.set_up(10, 0, user.loc) @@ -128,25 +124,34 @@ charges-- ..() +///////////////////////////////////// +//WAND OF DOOR CREATION +///////////////////////////////////// + /obj/item/weapon/gun/magic/wand/door name = "wand of door creation" desc = "This particular wand can create doors in any wall for the unscrupulous wizard who shuns teleportation magics." - projectile_type = "/obj/item/projectile/magic/door" + ammo_type = /obj/item/ammo_casing/magic/door icon_state = "doorwand" max_charges = 20 //20, 10, 10, 7 -/obj/item/weapon/gun/magic/wand/door/zap_self() - return +/obj/item/weapon/gun/magic/wand/door/zap_self(mob/living/user) + to_chat(user, "You feel vaguely more open with your feelings.") + charges-- + ..() + +///////////////////////////////////// +//WAND OF FIREBALL +///////////////////////////////////// /obj/item/weapon/gun/magic/wand/fireball name = "wand of fireball" desc = "This wand shoots scorching balls of fire that explode into destructive flames." - projectile_type = "/obj/item/projectile/magic/fireball" + ammo_type = /obj/item/ammo_casing/magic/fireball icon_state = "firewand" max_charges = 8 //8, 4, 4, 3 -/obj/item/weapon/gun/magic/wand/fireball/zap_self(mob/living/user as mob) - if(alert(user, "Zapping yourself with a wand of fireball is probably a bad idea, do it anyway?",, "Yes", "No") == "Yes" && charges && user.get_active_hand() == src && isliving(user)) - explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) - charges-- - ..() \ No newline at end of file +/obj/item/weapon/gun/magic/wand/fireball/zap_self(mob/living/user) + explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) + charges-- + ..() diff --git a/code/modules/projectiles/medbeam.dm b/code/modules/projectiles/guns/medbeam.dm similarity index 91% rename from code/modules/projectiles/medbeam.dm rename to code/modules/projectiles/guns/medbeam.dm index 04f8f4b6862..032874c4918 100644 --- a/code/modules/projectiles/medbeam.dm +++ b/code/modules/projectiles/guns/medbeam.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/chronos.dmi' icon_state = "chronogun" item_state = "chronogun" - w_class = 3.0 + w_class = 3 var/mob/living/current_target var/last_check = 0 @@ -13,7 +13,7 @@ var/active = 0 var/datum/beam/current_beam = null - heavy_weapon = 1 + weapon_weight = WEAPON_MEDIUM /obj/item/weapon/gun/medbeam/New() ..() @@ -34,7 +34,7 @@ on_beam_release(current_target) current_target = null -/obj/item/weapon/gun/medbeam/Fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) +/obj/item/weapon/gun/medbeam/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) add_fingerprint(user) if(current_target) @@ -48,7 +48,7 @@ spawn(0) current_beam.Start() - feedback_add_details("gun_fired","[src.type]") + feedback_add_details("gun_fired","[type]") /obj/item/weapon/gun/medbeam/process() var/mob/living/carbon/human/H = loc @@ -113,4 +113,4 @@ return /obj/effect/ebeam/medical - name = "medical beam" \ No newline at end of file + name = "medical beam" diff --git a/code/modules/projectiles/guns/mounted.dm b/code/modules/projectiles/guns/mounted.dm index d0e023d0d6d..ae9c8f06d09 100644 --- a/code/modules/projectiles/guns/mounted.dm +++ b/code/modules/projectiles/guns/mounted.dm @@ -1,31 +1,30 @@ -/obj/item/weapon/gun/energy/advtaser/mounted +/obj/item/weapon/gun/energy/gun/advtaser/mounted name = "mounted taser" desc = "An arm mounted dual-mode weapon that fires electrodes and disabler shots." - icon_state = "armcannonstun" - item_state = "armcannonstun" - modifystate = "armcannonstun" + icon_state = "armcannon" force = 5 - self_recharge = 1 flags = NODROP - slot_flags = null - w_class = 5.0 + w_class = 5 can_flashlight = 0 + selfcharge = 1 + trigger_guard = TRIGGER_GUARD_ALLOW_ALL // Has no trigger at all, uses neural signals instead -/obj/item/weapon/gun/energy/advtaser/mounted/dropped()//if somebody manages to drop this somehow... - src.loc = null//send it to nullspace to get retrieved by the implant later on. gotta cover those edge cases. +/obj/item/weapon/gun/energy/gun/advtaser/mounted/dropped()//if somebody manages to drop this somehow... + ..() + loc = null//send it to nullspace to get retrieved by the implant later on. gotta cover those edge cases. /obj/item/weapon/gun/energy/laser/mounted name = "mounted laser" desc = "An arm mounted cannon that fires lethal lasers. Doesn't come with a charge beam." - icon_state = "armcannonlase" + icon_state = "armcannon" item_state = "armcannonlase" - modifystate = "armcannonlase" force = 5 - self_recharge = 1 flags = NODROP - slot_flags = null - w_class = 5.0 + w_class = 5 materials = null + selfcharge = 1 + trigger_guard = TRIGGER_GUARD_ALLOW_ALL /obj/item/weapon/gun/energy/laser/mounted/dropped() - src.loc = null \ No newline at end of file + ..() + loc = null diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index ffe2cd269b5..03519770eee 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -1,22 +1,13 @@ -#define SPEEDLOADER 0 -#define FROM_BOX 1 -#define MAGAZINE 2 - /obj/item/weapon/gun/projectile desc = "Now comes in flavors like GUN. Uses 10mm ammo, for some reason" name = "projectile gun" icon_state = "pistol" origin_tech = "combat=2;materials=2" - w_class = 3.0 + w_class = 3 materials = list(MAT_METAL=1000) -// recoil = 1 - var/mag_type = "/obj/item/ammo_box/magazine/m10mm" //Removes the need for max_ammo and caliber info + + var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info var/obj/item/ammo_box/magazine/magazine -// var/obj/item/ammo_casing/chambered = null // The round (not bullet) that is in the chamber. - - - - /obj/item/weapon/gun/projectile/New() ..() @@ -26,31 +17,26 @@ update_icon() return +/obj/item/weapon/gun/projectile/update_icon() + ..() + if(current_skin) + icon_state = "[current_skin][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]" + else + icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]" -/obj/item/weapon/gun/projectile/process_chambered(var/eject_casing = 1, var/empty_chamber = 1 ) -// if(in_chamber) -// return 1 - +/obj/item/weapon/gun/projectile/process_chamber(eject_casing = 1, empty_chamber = 1) var/obj/item/ammo_casing/AC = chambered //Find chambered round if(isnull(AC) || !istype(AC)) - return 0 + chamber_round() + return if(eject_casing) AC.loc = get_turf(src) //Eject casing onto ground. AC.SpinAnimation(10, 1) //next gen special effects + if(empty_chamber) chambered = null chamber_round() - if(AC.BB) - if(AC.reagents && AC.BB.reagents) - var/datum/reagents/casting_reagents = AC.reagents - casting_reagents.trans_to(AC.BB, casting_reagents.total_volume) //For chemical darts/bullets - qdel(casting_reagents) - in_chamber = AC.BB //Load projectile into chamber. - AC.BB.loc = src //Set projectile loc to gun. - AC.update_icon() - return 1 - return 0 - + return /obj/item/weapon/gun/projectile/proc/chamber_round() if(chambered || !magazine) @@ -60,12 +46,16 @@ chambered.loc = src return +/obj/item/weapon/gun/projectile/can_shoot() + if(!magazine || !magazine.ammo_count(0)) + return 0 + return 1 /obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob, params) ..() if(istype(A, /obj/item/ammo_box/magazine)) var/obj/item/ammo_box/magazine/AM = A - if(!magazine && istype(AM, text2path(mag_type))) + if(!magazine && istype(AM, mag_type)) user.remove_from_mob(AM) magazine = AM magazine.loc = src @@ -79,13 +69,11 @@ if(istype(A, /obj/item/weapon/suppressor)) var/obj/item/weapon/suppressor/S = A if(can_suppress) - if(!silenced) - if(user.l_hand != src && user.r_hand != src) - to_chat(user, "You'll need [src] in your hands to do that.") + if(!suppressed) + if(!user.unEquip(A)) return - user.drop_item() to_chat(user, "You screw [S] onto [src].") - silenced = A + suppressed = A S.oldsound = fire_sound S.initial_w_class = w_class fire_sound = 'sound/weapons/Gunshot_silenced.ogg' @@ -101,39 +89,45 @@ return return 0 -/obj/item/weapon/gun/projectile/attack_hand(mob/user as mob) +/obj/item/weapon/gun/projectile/attack_hand(mob/user) if(loc == user) - if(silenced && can_unsuppress) - var/obj/item/weapon/suppressor/S = silenced + if(suppressed && can_unsuppress) + var/obj/item/weapon/suppressor/S = suppressed if(user.l_hand != src && user.r_hand != src) ..() return - to_chat(user, "You unscrew [silenced] from [src].") - user.put_in_hands(silenced) + to_chat(user, "You unscrew [suppressed] from [src].") + user.put_in_hands(suppressed) fire_sound = S.oldsound w_class = S.initial_w_class - silenced = 0 + suppressed = 0 update_icon() return ..() /obj/item/weapon/gun/projectile/attack_self(mob/living/user as mob) + var/obj/item/ammo_casing/AC = chambered //Find chambered round if(magazine) - magazine.loc = get_turf(src.loc) + magazine.loc = get_turf(loc) user.put_in_hands(magazine) magazine.update_icon() magazine = null to_chat(user, "You pull the magazine out of \the [src]!") + else if(chambered) + AC.loc = get_turf(src) + AC.SpinAnimation(10, 1) + chambered = null + to_chat(user, "You unload the round from \the [src]'s chamber.") else to_chat(user, "There's no magazine in \the [src].") update_icon() return /obj/item/weapon/gun/projectile/examine(mob/user) - ..(user) + ..() to_chat(user, "Has [get_ammo()] round\s remaining.") -/obj/item/weapon/gun/projectile/proc/get_ammo(var/countchambered = 1) +/obj/item/weapon/gun/projectile/proc/get_ammo(countchambered = 1) var/boolets = 0 //mature var names for mature people if(chambered && countchambered) boolets++ @@ -141,12 +135,68 @@ boolets += magazine.ammo_count() return boolets +/obj/item/weapon/gun/projectile/suicide_act(mob/user) + if (chambered && chambered.BB && !chambered.BB.nodamage) + user.visible_message("[user] is putting the barrel of the [name] in \his mouth. It looks like \he's trying to commit suicide.") + sleep(25) + if(user.l_hand == src || user.r_hand == src) + process_fire(user, user, 0, zone_override = "head") + user.visible_message("[user] blows \his brains out with the [name]!") + return(BRUTELOSS) + else + user.visible_message("[user] panics and starts choking to death!") + return(OXYLOSS) + else + user.visible_message("[user] is pretending to blow \his brains out with the [name]! It looks like \he's trying to commit suicide!") + playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1) + return (OXYLOSS) + +/obj/item/weapon/gun/projectile/proc/sawoff(mob/user) + if(sawn_state == SAWN_OFF) + to_chat(user, "\The [src] is already shortened!") + return + user.changeNext_move(CLICK_CD_MELEE) + user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...") + + //if there's any live ammo inside the gun, makes it go off + if(blow_up(user)) + user.visible_message("\The [src] goes off!", "\The [src] goes off in your face!") + return + + if(do_after(user, 30, target = src)) + if(sawn_state == SAWN_OFF) + return + user.visible_message("[user] shortens \the [src]!", "You shorten \the [src].") + name = "sawn-off [name]" + desc = sawn_desc + w_class = 3 + item_state = "gun"//phil235 is it different with different skin? + slot_flags &= ~SLOT_BACK //you can't sling it on your back + slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) + sawn_state = SAWN_OFF + update_icon() + return 1 + +// Sawing guns related proc +/obj/item/weapon/gun/projectile/proc/blow_up(mob/user) + . = 0 + for(var/obj/item/ammo_casing/AC in magazine.stored_ammo) + if(AC.BB) + process_fire(user, user,0) + . = 1 + /obj/item/weapon/suppressor name = "suppressor" desc = "A universal syndicate small-arms suppressor for maximum espionage." - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/projectile.dmi' icon_state = "suppressor" item_state = "suppressor" w_class = 2 var/oldsound = null var/initial_w_class = null + +/obj/item/weapon/suppressor/specialoffer + name = "cheap suppressor" + desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits all weapons." + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "suppressor" diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index b56344ce039..7544ecc7b50 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -1,6 +1,5 @@ /obj/item/weapon/gun/projectile/automatic w_class = 3.0 - automatic = 1 var/alarmed = 0 var/select = 1 can_suppress = 1 @@ -11,13 +10,6 @@ /obj/item/weapon/gun/projectile/automatic/isHandgun() return 0 -/obj/item/weapon/gun/projectile/automatic/proto - name = "\improper Nanotrasen Saber SMG" - desc = "A prototype three-round burst 9mm submachine gun, designated 'SABR'. Has a threaded barrel for suppressors." - icon_state = "saber" - mag_type = "/obj/item/ammo_box/magazine/smgm9mm" - origin_tech = "combat=4;materials=2" - /obj/item/weapon/gun/projectile/automatic/update_icon() ..() overlays.Cut() @@ -25,8 +17,7 @@ overlays += "[initial(icon_state)]semi" if(select == 1) overlays += "[initial(icon_state)]burst" - icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][silenced ? "-suppressed" : ""]" - return + icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/weapon/gun/projectile/automatic/attackby(var/obj/item/A as obj, mob/user as mob, params) . = ..() @@ -34,17 +25,17 @@ return if(istype(A, /obj/item/ammo_box/magazine)) var/obj/item/ammo_box/magazine/AM = A - if(istype(AM, text2path(mag_type))) + if(istype(AM, mag_type)) if(magazine) to_chat(user, "You perform a tactical reload on \the [src], replacing the magazine.") - magazine.forceMove(get_turf(src.loc)) + magazine.loc = get_turf(loc) magazine.update_icon() magazine = null else to_chat(user, "You insert the magazine into \the [src].") user.remove_from_mob(AM) magazine = AM - magazine.forceMove(src) + magazine.loc = src chamber_round() A.update_icon() update_icon() @@ -67,14 +58,22 @@ playsound(user, 'sound/weapons/empty.ogg', 100, 1) update_icon() - return + +/obj/item/weapon/gun/projectile/automatic/can_shoot() + return get_ammo() /obj/item/weapon/gun/projectile/automatic/proc/empty_alarm() if(!chambered && !get_ammo() && !alarmed) - playsound(src.loc, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) + playsound(loc, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) update_icon() alarmed = 1 - return + +/obj/item/weapon/gun/projectile/automatic/proto + name = "\improper Nanotrasen Saber SMG" + desc = "A prototype three-round burst 9mm submachine gun, designated 'SABR'. Has a threaded barrel for suppressors." + icon_state = "saber" + mag_type = /obj/item/ammo_box/magazine/smgm9mm + origin_tech = "combat=4;materials=2" /obj/item/weapon/gun/projectile/automatic/c20r name = "\improper C-20r SMG" @@ -82,7 +81,7 @@ icon_state = "c20r" item_state = "c20r" origin_tech = "combat=5;materials=2;syndicate=8" - mag_type = "/obj/item/ammo_box/magazine/smgm45" + mag_type = /obj/item/ammo_box/magazine/smgm45 fire_sound = 'sound/weapons/Gunshot_smg.ogg' fire_delay = 2 burst_size = 2 @@ -90,24 +89,21 @@ /obj/item/weapon/gun/projectile/automatic/c20r/New() ..() update_icon() - return /obj/item/weapon/gun/projectile/automatic/c20r/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag) ..() empty_alarm() - return /obj/item/weapon/gun/projectile/automatic/c20r/update_icon() ..() - icon_state = "c20r[magazine ? "-[Ceiling(get_ammo(0)/4)*4]" : ""][chambered ? "" : "-e"][silenced ? "-suppressed" : ""]" - return + icon_state = "c20r[magazine ? "-[Ceiling(get_ammo(0)/4)*4]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/weapon/gun/projectile/automatic/wt550 name = "security auto rifle" desc = "An outdated personal defense weapon utilized by law enforcement. The WT-550 Automatic Rifle fires 4.6x30mm rounds." icon_state = "wt550" item_state = "arg" - mag_type = "/obj/item/ammo_box/magazine/wt550m9" + mag_type = /obj/item/ammo_box/magazine/wt550m9 fire_delay = 2 can_suppress = 0 burst_size = 1 @@ -116,87 +112,22 @@ /obj/item/weapon/gun/projectile/automatic/wt550/update_icon() ..() icon_state = "wt550[magazine ? "-[Ceiling(get_ammo(0)/4)*4]" : ""]" - return /obj/item/weapon/gun/projectile/automatic/mini_uzi name = "\improper 'Type U3' Uzi" desc = "A lightweight, burst-fire submachine gun, for when you really want someone dead. Uses 9mm rounds." icon_state = "mini-uzi" origin_tech = "combat=5;materials=2;syndicate=8" - mag_type = "/obj/item/ammo_box/magazine/uzim9mm" + mag_type = /obj/item/ammo_box/magazine/uzim9mm burst_size = 2 -/obj/item/weapon/gun/projectile/automatic/l6_saw - name = "\improper L6 SAW" - desc = "A heavily modified 7.62 light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the reciever below the designation." - icon_state = "l6closed100" - item_state = "l6closedmag" - w_class = 5 - slot_flags = 0 - origin_tech = "combat=5;materials=1;syndicate=2" - mag_type = "/obj/item/ammo_box/magazine/m762" - fire_sound = 'sound/weapons/Gunshot3.ogg' - - var/cover_open = 0 - can_suppress = 0 - burst_size = 5 - fire_delay = 3 - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob) - cover_open = !cover_open - to_chat(user, "You [cover_open ? "open" : "close"] [src]'s cover.") - update_icon() - -/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon() - if(magazine && magazine.caliber != "a762") - icon_state = "l6[cover_open ? "open" : "closed"]0" - icon_state = "l6[cover_open ? "open" : "closed"][magazine ? round(magazine.ammo_count() * 2, 25) : "-empty"]" - -/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays - if(cover_open) - to_chat(user, "[src]'s cover is open! Close it before firing!") - else - ..() - update_icon() - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob) - if(loc != user) - ..() - return //let them pick it up - if(!cover_open || (cover_open && !magazine)) - ..() - else if(cover_open && magazine) - //drop the mag - magazine.update_icon() - magazine.loc = get_turf(src.loc) - user.put_in_hands(magazine) - magazine = null - update_icon() - to_chat(user, "You remove the magazine from [src].") - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attackby(var/obj/item/A as obj, mob/user as mob, params) - if(!cover_open && istype(A, mag_type)) - to_chat(user, "[src]'s cover is closed! You can't insert a new mag!") - return - ..() - -/obj/item/weapon/gun/projectile/automatic/l6_saw/devastator - name = "\improper 'Devastator' LMG" - desc = "A heavily modified L6 SAW designed to chamber wide rounds. Commonly used by elite Syndicate boarding teams " - mag_type = "/obj/item/ammo_box/magazine/m762/buckshot" - -/obj/item/weapon/gun/projectile/automatic/l6_saw/devastator/New() - ..() - mag_type = "/obj/item/ammo_box/magazine/m762" // Workaround so it spawns with a shotgun mag loaded, but can still load regular LMG mags. - /obj/item/weapon/gun/projectile/automatic/m90 name = "\improper M-90gl Carbine" desc = "A three-round burst 5.56 toploading carbine, designated 'M-90gl'. Has an attached underbarrel grenade launcher which can be toggled on and off." icon_state = "m90" item_state = "m90" origin_tech = "combat=5;materials=2;syndicate=8" - mag_type = "/obj/item/ammo_box/magazine/m556" + mag_type = /obj/item/ammo_box/magazine/m556 fire_sound = 'sound/weapons/Gunshot_smg.ogg' action_button_name = "Toggle Grenade Launcher" can_suppress = 0 @@ -208,19 +139,17 @@ ..() underbarrel = new /obj/item/weapon/gun/projectile/revolver/grenadelauncher(src) update_icon() - return /obj/item/weapon/gun/projectile/automatic/m90/afterattack(var/atom/target, var/mob/living/user, flag, params) if(select == 2) underbarrel.afterattack(target, user, flag, params) else ..() - empty_alarm() return /obj/item/weapon/gun/projectile/automatic/m90/attackby(var/obj/item/A, mob/user, params) if(istype(A, /obj/item/ammo_casing)) - if(istype(A, text2path(underbarrel.magazine.ammo_type))) + if(istype(A, underbarrel.magazine.ammo_type)) underbarrel.attack_self() underbarrel.attackby(A, user, params) else @@ -257,7 +186,6 @@ to_chat(user, "You switch to semi-auto.") playsound(user, 'sound/weapons/empty.ogg', 100, 1) update_icon() - return /obj/item/weapon/gun/projectile/automatic/tommygun name = "\improper Thompson SMG" @@ -267,11 +195,11 @@ w_class = 5 slot_flags = 0 origin_tech = "combat=5;materials=1;syndicate=2" - mag_type = "/obj/item/ammo_box/magazine/tommygunm45" + mag_type = /obj/item/ammo_box/magazine/tommygunm45 fire_sound = 'sound/weapons/Gunshot_smg.ogg' can_suppress = 0 - fire_delay = 1 burst_size = 4 + fire_delay = 1 /obj/item/weapon/gun/projectile/automatic/ar name = "ARG" @@ -280,8 +208,42 @@ item_state = "arg" slot_flags = 0 origin_tech = "combat=5;materials=1" - mag_type = "/obj/item/ammo_box/magazine/m556" + mag_type = /obj/item/ammo_box/magazine/m556 fire_sound = 'sound/weapons/Gunshot_smg.ogg' can_suppress = 0 burst_size = 3 fire_delay = 1 + +// Bulldog shotgun // +/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog + name = "\improper 'Bulldog' Shotgun" + desc = "A compact, mag-fed semi-automatic shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines." + icon_state = "bulldog" + item_state = "bulldog" + w_class = 3.0 + origin_tech = "combat=5;materials=4;syndicate=6" + mag_type = /obj/item/ammo_box/magazine/m12g + fire_sound = 'sound/weapons/Gunshot4.ogg' + can_suppress = 0 + burst_size = 1 + fire_delay = 0 + action_button_name = null + +/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/New() + ..() + update_icon() + +/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/proc/update_magazine() + if(magazine) + overlays.Cut() + overlays += "[magazine.icon_state]" + return + +/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/update_icon() + overlays.Cut() + update_magazine() + icon_state = "bulldog[chambered ? "" : "-e"]" + +/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag) + ..() + empty_alarm() diff --git a/code/modules/projectiles/guns/projectile/crossbow.dm b/code/modules/projectiles/guns/projectile/crossbow.dm deleted file mode 100644 index 3645899ab21..00000000000 --- a/code/modules/projectiles/guns/projectile/crossbow.dm +++ /dev/null @@ -1,323 +0,0 @@ -//AMMUNITION - -/obj/item/weapon/arrow - - name = "bolt" - desc = "It's got a tip for you - get the point?" - icon = 'icons/obj/weapons.dmi' - icon_state = "bolt" - item_state = "bolt" - throwforce = 8 - w_class = 3.0 - sharp = 1 - edge = 0 - -/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart. - return - -/obj/item/weapon/spike - name = "alloy spike" - desc = "It's about a foot of weird silver metal with a wicked point." - sharp = 1 - edge = 0 - throwforce = 5 - w_class = 2 - icon = 'icons/obj/weapons.dmi' - icon_state = "metal-rod" - item_state = "bolt" - -/obj/item/weapon/arrow/quill - - name = "vox quill" - desc = "A wickedly barbed quill from some bizarre animal." - icon_state = "quill" - item_state = "quill" - throwforce = 5 - -/obj/item/weapon/arrow/rod - - name = "metal rod" - desc = "Don't cry for me, Orithena." - icon_state = "metal-rod" - -/obj/item/weapon/arrow/rod/removed(mob/user) - if(throwforce == 15) // The rod has been superheated - we don't want it to be useable when removed from the bow. - to_chat(user, "[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.") - var/obj/item/weapon/shard/shrapnel/S = new() - S.loc = get_turf(src) - qdel(src) - -/obj/item/weapon/arrow/baguette - name = "baguette" - desc = "Still warm from the oven!" - icon = 'icons/obj/weapons.dmi' - icon_state = "baguette" - item_state = "baguette" - throwforce = 3 - sharp = 0 - -/obj/item/weapon/gun/launcher/crossbow - - name = "powered crossbow" - desc = "A 2557AD twist on an old classic. Pick up that can." - icon_state = "crossbow" - item_state = "crossbow-solid" - fire_sound = 'sound/weapons/punchmiss.ogg' // TODO: Decent THWOK noise. -// ejectshell = 0 // No spent shells. - mouthshoot = 1 // No suiciding with this weapon, causes runtimes. - fire_sound_text = "a solid thunk" - fire_delay = 25 - - var/tension = 0 // Current draw on the bow. - var/max_tension = 5 // Highest possible tension. - var/release_speed = 5 // Speed per unit of tension. - var/obj/item/weapon/stock_parts/cell/cell = null // Used for firing superheated rods. - var/current_user // Used to check if the crossbow has changed hands since being drawn. - -/obj/item/weapon/gun/launcher/crossbow/emp_act(severity) - if(cell && severity) - cell.use(100*severity) - -/obj/item/weapon/gun/launcher/crossbow/special_check(user) - if(tension <= 0) - to_chat(user, "\red \The [src] is not drawn back!") - return 0 - return 1 - -/obj/item/weapon/gun/launcher/crossbow/update_release_force() - release_force = tension*release_speed - -/obj/item/weapon/gun/launcher/crossbow/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0) - - if(!..()) return //Only do this on a successful shot. - icon_state = "crossbow" - tension = 0 - -/obj/item/weapon/gun/launcher/crossbow/attack_self(mob/living/user as mob) - if(tension) - if(in_chamber && in_chamber.loc == src) //Just in case they click it the tick after firing. - user.visible_message("[user] relaxes the tension on [src]'s string and removes [in_chamber].","You relax the tension on [src]'s string and remove [in_chamber].") - in_chamber.loc = get_turf(src) - var/obj/item/weapon/arrow/A = in_chamber - in_chamber = null - A.removed(user) - else - user.visible_message("[user] relaxes the tension on [src]'s string.","You relax the tension on [src]'s string.") - tension = 0 - icon_state = "crossbow" - else - draw(user) - -/obj/item/weapon/gun/launcher/crossbow/proc/draw(var/mob/user as mob) - - if(!in_chamber) - to_chat(user, "You don't have anything nocked to [src].") - return - - if(user.restrained()) - return - - current_user = user - user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].") - tension = 1 - spawn(25) increase_tension(user) //TODO: This needs to be changed to something less shit. - -/obj/item/weapon/gun/launcher/crossbow/proc/increase_tension(var/mob/user as mob) - - if(!in_chamber || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed. - return - - tension++ - icon_state = "crossbow-drawn" - - if(tension>=max_tension) - tension = max_tension - to_chat(usr, "[src] clunks as you draw the string to its maximum tension!") - else - user.visible_message("[usr] draws back the string of [src]!","You continue drawing back the string of [src]!") - spawn(25) increase_tension(user) - -/obj/item/weapon/gun/launcher/crossbow/attackby(obj/item/W as obj, mob/user as mob, params) - if(!in_chamber) - if (istype(W,/obj/item/weapon/arrow)) - user.drop_item() - in_chamber = W - in_chamber.loc = src - user.visible_message("[user] slides [in_chamber] into [src].","You slide [in_chamber] into [src].") - icon_state = "crossbow-nocked" - return - else if(istype(W,/obj/item/stack/rods)) - var/obj/item/stack/rods/R = W - R.use(1) - in_chamber = new /obj/item/weapon/arrow/rod(src) - in_chamber.fingerprintslast = src.fingerprintslast - in_chamber.loc = src - icon_state = "crossbow-nocked" - user.visible_message("[user] jams [in_chamber] into [src].","You jam [in_chamber] into [src].") - superheat_rod(user) - return - - if(istype(W, /obj/item/weapon/stock_parts/cell)) - if(!cell) - user.drop_item() - W.loc = src - cell = W - to_chat(user, "You jam [cell] into [src] and wire it to the firing coil.") - superheat_rod(user) - else - to_chat(user, "[src] already has a cell installed.") - - else if(istype(W, /obj/item/weapon/screwdriver)) - if(cell) - var/obj/item/C = cell - C.loc = get_turf(user) - to_chat(user, "You jimmy [cell] out of [src] with [W].") - cell = null - else - to_chat(user, "[src] doesn't have a cell installed.") - - else - ..() - -/obj/item/weapon/gun/launcher/crossbow/proc/superheat_rod(var/mob/user) - - if(!user || !cell || !in_chamber) return - if(cell.charge < 500) return - if(in_chamber.throwforce >= 15) return - if(!istype(in_chamber,/obj/item/weapon/arrow/rod)) return - - to_chat(user, "[in_chamber] plinks and crackles as it begins to glow red-hot.") - in_chamber.throwforce = 15 - in_chamber.icon_state = "metal-rod-superheated" - cell.use(500) - - -/obj/item/weapon/gun/launcher/crossbow/french - name = "french powered crossbow" - -/obj/item/weapon/gun/launcher/crossbow/french/attackby(obj/item/W as obj, mob/user as mob, params) - if(!in_chamber) - if (istype(W,/obj/item/weapon/reagent_containers/food/snacks/baguette)) - user.drop_item() - in_chamber = W - in_chamber.loc = src - user.visible_message("[user] slides [in_chamber] into [src].","You slide [in_chamber] into [src].") - icon_state = "crossbow-nocked" - return - - else if (istype(W,/obj/item/weapon/arrow)) - user.visible_message("\The [src] only takes baguettes.") - return - else if(istype(W,/obj/item/stack/rods)) - user.visible_message("\The [src] only takes baguettes.") - return - - if(istype(W, /obj/item/weapon/stock_parts/cell)) - user.visible_message("The [src] is too simple be adapted with a cell.") - return - - else - ..() - -/obj/item/weapon/gun/launcher/crossbow/french/increase_tension(var/mob/user as mob) - - if(!in_chamber || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed. - return - - tension++ - icon_state = "fcrossbow-drawn" - - if(tension>=max_tension) - tension = max_tension - to_chat(usr, "[src] clunks as you draw the string to its maximum tension!") - else - user.visible_message("[usr] draws back the string of [src]!","You continue drawing back the string of [src]!") - spawn(25) increase_tension(user) - -// Crossbow construction. -/obj/item/weapon/crossbowframe - name = "crossbow frame" - desc = "A half-finished crossbow." - icon_state = "crossbowframe0" - item_state = "crossbow-solid" - - var/buildstate = 0 - -/obj/item/weapon/crossbowframe/update_icon() - icon_state = "crossbowframe[buildstate]" - -/obj/item/weapon/crossbowframe/examine(mob/user) - ..(user) - switch(buildstate) - if(1) - to_chat(user, "It has a loose rod frame in place.") - if(2) - to_chat(user, "It has a steel backbone welded in place.") - if(3) - to_chat(user, "It has a steel backbone and a cell mount installed.") - if(4) - to_chat(user, "It has a steel backbone, plastic lath and a cell mount installed.") - if(5) - to_chat(user, "It has a steel cable loosely strung across the lath.") - -/obj/item/weapon/crossbowframe/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W,/obj/item/stack/rods)) - if(buildstate == 0) - var/obj/item/stack/rods/R = W - if(R.amount >= 3) - R.use(3) - to_chat(user, "\blue You assemble a backbone of rods around the wooden stock.") - buildstate++ - update_icon() - else - to_chat(user, "\blue You need at least three rods to complete this task.") - return - else if(istype(W,/obj/item/weapon/weldingtool)) - if(buildstate == 1) - var/obj/item/weapon/weldingtool/T = W - if(T.remove_fuel(0,user)) - if(!src || !T.isOn()) return - playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "\blue You weld the rods into place.") - buildstate++ - update_icon() - return - else if(istype(W,/obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - if(buildstate == 2) - if(C.amount >= 5) - C.use(5) - to_chat(user, "\blue You wire a crude cell mount into the top of the crossbow.") - buildstate++ - update_icon() - else - to_chat(user, "\blue You need at least five segments of cable coil to complete this task.") - return - else if(buildstate == 4) - if(C.amount >= 5) - C.use(5) - to_chat(user, "\blue You string a steel cable across the crossbow's lath.") - buildstate++ - update_icon() - else - to_chat(user, "\blue You need at least five segments of cable coil to complete this task.") - return - else if(istype(W,/obj/item/stack/sheet/mineral/plastic)) - if(buildstate == 3) - var/obj/item/stack/sheet/mineral/plastic/P = W - if(P.amount >= 3) - P.use(3) - to_chat(user, "\blue You assemble and install a heavy plastic lath onto the crossbow.") - buildstate++ - update_icon() - else - to_chat(user, "\blue You need at least three plastic sheets to complete this task.") - return - else if(istype(W,/obj/item/weapon/screwdriver)) - if(buildstate == 5) - to_chat(user, "\blue You secure the crossbow's various parts.") - new /obj/item/weapon/gun/launcher/crossbow(get_turf(src)) - qdel(src) - return - else - ..() diff --git a/code/modules/projectiles/guns/projectile/grenade launcher.dm b/code/modules/projectiles/guns/projectile/grenade launcher.dm deleted file mode 100644 index 28dc0c3a4b9..00000000000 --- a/code/modules/projectiles/guns/projectile/grenade launcher.dm +++ /dev/null @@ -1,91 +0,0 @@ -/obj/item/weapon/gun/launcher - - name = "launcher" - desc = "A device that launches things." - icon = 'icons/obj/weapons.dmi' - w_class = 5.0 - flags = CONDUCT - slot_flags = SLOT_BACK - - var/release_force = 0 - var/fire_sound_text = "a launcher firing" - -//Check if we're drawing and if the bow is loaded. -/obj/item/weapon/gun/launcher/proc/chamber_round() - return (!isnull(in_chamber)) - -//This should not fit in a combat belt or holster. -/obj/item/weapon/gun/launcher/isHandgun() - return 0 - -//Launchers are mechanical, no other impact. -/obj/item/weapon/gun/launcher/emp_act(severity) - return - -//This normally uses a proc on projectiles and our ammo is not strictly speaking a projectile. -/obj/item/weapon/gun/launcher/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) - return - -//Override this to avoid a runtime with suicide handling. -/obj/item/weapon/gun/launcher/attack(mob/living/M as mob, mob/living/user as mob, def_zone) - if (M == user && user.zone_sel.selecting == "mouth") - to_chat(user, "\red Shooting yourself with \a [src] is pretty tricky. You can't seem to manage it.") - return - ..() - -/obj/item/weapon/gun/launcher/proc/update_release_force() - return 0 - -/obj/item/weapon/gun/launcher/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0) - - if (!user.IsAdvancedToolUser()) - to_chat(user, "\red You don't have the dexterity to do this!") - return 0 - - add_fingerprint(user) - - //Make sure target turfs both exist. - var/turf/curloc = get_turf(user) - var/turf/targloc = get_turf(target) - if (!istype(targloc) || !istype(curloc)) - return 0 - - if(!special_check(user)) - return 0 - - if (!ready_to_fire()) - if (world.time % 3) //to prevent spam - to_chat(user, "[src] is not ready to fire again!") - return 0 - - if(!chamber_round()) //CHECK - return click_empty(user) - - if(!in_chamber) - return 0 - - update_release_force() - - playsound(user, fire_sound, 50, 1) - user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ - "You fire [src][reflex ? "by reflex":""]!", \ - "You hear [fire_sound_text]!") - - in_chamber.loc = get_turf(user) - in_chamber.throw_at(target,10,release_force) - - sleep(1) - - in_chamber = null - - update_icon() - - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - - return 1 - -/obj/item/weapon/gun/launcher/attack_self(mob/living/user as mob) - return \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/launchers.dm b/code/modules/projectiles/guns/projectile/launchers.dm index 6bcca0cdf68..635ab22cc8c 100644 --- a/code/modules/projectiles/guns/projectile/launchers.dm +++ b/code/modules/projectiles/guns/projectile/launchers.dm @@ -1,44 +1,12 @@ //KEEP IN MIND: These are different from gun/grenadelauncher. These are designed to shoot premade rocket and grenade projectiles, not flashbangs or chemistry casings etc. //Put handheld rocket launchers here if someone ever decides to make something so hilarious ~Paprika - -/obj/item/weapon/gun/projectile/automatic/gyropistol - name = "gyrojet pistol" - desc = "A prototype pistol designed to fire self propelled rockets." - icon_state = "gyropistol" - fire_sound = 'sound/effects/Explosion1.ogg' - origin_tech = "combat=3" - mag_type = "/obj/item/ammo_box/magazine/m75" - burst_size = 1 - fire_delay = 0 - -/obj/item/weapon/gun/projectile/automatic/gyropistol/isHandgun() - return 1 - -/obj/item/weapon/gun/projectile/automatic/gyropistol/New() - ..() - update_icon() - return - -/obj/item/weapon/gun/projectile/automatic/gyropistol/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag) - ..() - if(!chambered && !get_ammo() && !alarmed) - playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) - update_icon() - alarmed = 1 - return - -/obj/item/weapon/gun/projectile/automatic/gyropistol/update_icon() - ..() - icon_state = "[initial(icon_state)][magazine ? "loaded" : ""]" - return - /obj/item/weapon/gun/projectile/revolver/grenadelauncher//this is only used for underbarrel grenade launchers at the moment, but admins can still spawn it if they feel like being assholes desc = "A break-operated grenade launcher." name = "grenade launcher" icon_state = "dshotgun-sawn" item_state = "gun" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher fire_sound = 'sound/weapons/grenadelaunch.ogg' w_class = 3 @@ -52,7 +20,7 @@ name = "multi grenade launcher" icon_state = "bulldog" item_state = "bulldog" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher/multi" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher/multi /obj/item/weapon/gun/projectile/revolver/grenadelauncher/multi/cyborg desc = "A 6-shot grenade launcher." @@ -60,4 +28,57 @@ icon_state = "mecha_grenadelnchr" /obj/item/weapon/gun/projectile/revolver/grenadelauncher/multi/cyborg/attack_self() - return \ No newline at end of file + return + +/obj/item/weapon/gun/projectile/automatic/gyropistol + name = "gyrojet pistol" + desc = "A prototype pistol designed to fire self propelled rockets." + icon_state = "gyropistol" + fire_sound = 'sound/effects/Explosion1.ogg' + origin_tech = "combat=3" + mag_type = /obj/item/ammo_box/magazine/m75 + burst_size = 1 + fire_delay = 0 + action_button_name = null + +/obj/item/weapon/gun/projectile/automatic/gyropistol/isHandgun() + return 1 + +/obj/item/weapon/gun/projectile/automatic/gyropistol/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() + +/obj/item/weapon/gun/projectile/automatic/gyropistol/update_icon() + ..() + icon_state = "[initial(icon_state)][magazine ? "loaded" : ""]" + return + +/obj/item/weapon/gun/projectile/automatic/speargun + name = "kinetic speargun" + desc = "A weapon favored by carp hunters. Fires specialized spears using kinetic energy." + icon_state = "speargun" + item_state = "speargun" + w_class = 4 + force = 10 + can_suppress = 0 + mag_type = /obj/item/ammo_box/magazine/internal/speargun + fire_sound = 'sound/weapons/grenadelaunch.ogg' + burst_size = 1 + fire_delay = 0 + select = 0 + action_button_name = null + +/obj/item/weapon/gun/projectile/automatic/speargun/update_icon() + return + +/obj/item/weapon/gun/projectile/automatic/speargun/attack_self() + return + +/obj/item/weapon/gun/projectile/automatic/speargun/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() + +/obj/item/weapon/gun/projectile/automatic/speargun/attackby(obj/item/A, mob/user, params) + var/num_loaded = magazine.attackby(A, user, params, 1) + if(num_loaded) + to_chat(user, "You load [num_loaded] spear\s into \the [src].") + update_icon() + chamber_round() diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index 99aded2663b..b2c0aa823be 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -4,27 +4,26 @@ icon_state = "pistol" w_class = 2 origin_tech = "combat=2;materials=2;syndicate=2" - mag_type = "/obj/item/ammo_box/magazine/m10mm" + mag_type = /obj/item/ammo_box/magazine/m10mm can_suppress = 1 burst_size = 1 fire_delay = 0 action_button_name = null - + /obj/item/weapon/gun/projectile/automatic/pistol/isHandgun() return 1 /obj/item/weapon/gun/projectile/automatic/pistol/update_icon() ..() - icon_state = "[initial(icon_state)][chambered ? "" : "-e"][silenced ? "-suppressed" : ""]" + icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" return -/obj/item/weapon/gun/projectile/automatic/pistol/m2411 - name = "M2411" - desc = "John Browning's classic updated for the modern day. Uses .45 rounds." - icon_state = "m2411" - w_class = 3.0 - origin_tech = "combat=3;materials=2" - mag_type = "/obj/item/ammo_box/magazine/m45" +/obj/item/weapon/gun/projectile/automatic/pistol/m1911 + name = "\improper M1911" + desc = "A classic .45 handgun with a small magazine capacity." + icon_state = "m1911" + w_class = 3 + mag_type = /obj/item/ammo_box/magazine/m45 can_suppress = 0 /obj/item/weapon/gun/projectile/automatic/pistol/deagle @@ -32,7 +31,7 @@ desc = "A robust .50 AE handgun." icon_state = "deagle" force = 14.0 - mag_type = "/obj/item/ammo_box/magazine/m50" + mag_type = /obj/item/ammo_box/magazine/m50 can_suppress = 0 /obj/item/weapon/gun/projectile/automatic/pistol/deagle/update_icon() @@ -47,4 +46,16 @@ /obj/item/weapon/gun/projectile/automatic/pistol/deagle/camo desc = "A Deagle brand Deagle for operators operating operationally. Uses .50 AE ammo." icon_state = "deaglecamo" - item_state = "deagleg" \ No newline at end of file + item_state = "deagleg" + +/obj/item/weapon/gun/projectile/automatic/pistol/APS + name = "stechkin APS pistol" + desc = "The original russian version of a widely used Syndicate sidearm. Uses 9mm ammo." + icon_state = "aps" + w_class = 3 + origin_tech = "combat=3;materials=2;syndicate=3" + mag_type = /obj/item/ammo_box/magazine/pistolm9mm + can_suppress = 0 + burst_size = 3 + fire_delay = 2 + action_button_name = "Toggle Firemode" diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 2cb3c849e4b..299ffbc9a6c 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -2,57 +2,80 @@ name = "\improper .357 revolver" desc = "A suspicious revolver. Uses .357 ammo." icon_state = "revolver" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder -/obj/item/weapon/gun/projectile/revolver/chamber_round() - if (chambered || !magazine) - return - else if (magazine.ammo_count()) +/obj/item/weapon/gun/projectile/revolver/New() + ..() + if(!istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder)) + verbs -= /obj/item/weapon/gun/projectile/revolver/verb/spin + +/obj/item/weapon/gun/projectile/revolver/chamber_round(var/spin = 1) + if(spin) chambered = magazine.get_round(1) + else + chambered = magazine.stored_ammo[1] return -/obj/item/weapon/gun/projectile/revolver/process_chambered() +/obj/item/weapon/gun/projectile/revolver/shoot_with_empty_chamber(mob/living/user as mob|obj) + ..() + chamber_round(1) + +/obj/item/weapon/gun/projectile/revolver/process_chamber() return ..(0, 1) -/obj/item/weapon/gun/projectile/revolver/attackby(var/obj/item/A as obj, mob/user as mob, params) - var/num_loaded = 0 - if(istype(A, /obj/item/ammo_box)) - var/obj/item/ammo_box/AM = A - for(var/obj/item/ammo_casing/AC in AM.stored_ammo) - var/didload = magazine.give_round(AC) - if(didload) - AM.stored_ammo -= AC - num_loaded++ - if(!didload || !magazine.multiload) - break - if(istype(A, /obj/item/ammo_casing)) - var/obj/item/ammo_casing/AC = A - if(magazine.give_round(AC)) - user.drop_item() - AC.loc = src - num_loaded++ +/obj/item/weapon/gun/projectile/revolver/attackby(obj/item/A, mob/user, params) + . = ..() + if(.) + return + var/num_loaded = magazine.attackby(A, user, params, 1) if(num_loaded) - to_chat(user, "You load [num_loaded] shell\s into \the [src]!") + to_chat(user, "You load [num_loaded] shell\s into \the [src].") A.update_icon() update_icon() - chamber_round() + chamber_round(0) -/obj/item/weapon/gun/projectile/revolver/attack_self(mob/living/user as mob) + if(unique_rename) + if(istype(A, /obj/item/weapon/pen)) + rename_gun(user) + +/obj/item/weapon/gun/projectile/revolver/attack_self(mob/living/user) var/num_unloaded = 0 + chambered = null while (get_ammo() > 0) var/obj/item/ammo_casing/CB CB = magazine.get_round(0) - chambered = null - CB.loc = get_turf(src.loc) - CB.SpinAnimation(10, 1) - CB.update_icon() - num_unloaded++ + if(CB) + CB.loc = get_turf(loc) + CB.SpinAnimation(10, 1) + CB.update_icon() + num_unloaded++ if (num_unloaded) - to_chat(user, "You unload [num_unloaded] shell\s from [src]!") + to_chat(user, "You unload [num_unloaded] shell\s from [src].") else - to_chat(user, "[src] is empty.") + to_chat(user, "[src] is empty!") -/obj/item/weapon/gun/projectile/revolver/get_ammo(var/countchambered = 0, var/countempties = 1) +/obj/item/weapon/gun/projectile/revolver/verb/spin() + set name = "Spin Chamber" + set category = "Object" + set desc = "Click to spin your revolver's chamber." + + var/mob/M = usr + + if(M.stat || !in_range(M,src)) + return + + if(istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder)) + var/obj/item/ammo_box/magazine/internal/cylinder/C = magazine + C.spin() + chamber_round(0) + usr.visible_message("[usr] spins [src]'s chamber.", "You spin [src]'s chamber.") + else + verbs -= /obj/item/weapon/gun/projectile/revolver/verb/spin + +/obj/item/weapon/gun/projectile/revolver/can_shoot() + return get_ammo(0,0) + +/obj/item/weapon/gun/projectile/revolver/get_ammo(countchambered = 0, countempties = 1) var/boolets = 0 //mature var names for mature people if (chambered && countchambered) boolets++ @@ -61,119 +84,66 @@ return boolets /obj/item/weapon/gun/projectile/revolver/examine(mob/user) - ..(user) + ..() to_chat(user, "[get_ammo(0,0)] of those are live rounds.") -/obj/item/weapon/gun/projectile/revolver/verb/spin_revolver() - set name = "Spin cylinder" - set desc = "Fun when you're bored out of your skull." - set category = "Object" - - usr.visible_message("[usr] spins the chamber of the revolver.", "You spin the revolver's chamber.") - playsound(src.loc, 'sound/weapons/revolver_spin.ogg', 100, 1) - Spin() - -/obj/item/weapon/gun/projectile/revolver/proc/Spin() - chambered = null - var/random = rand(1, magazine.max_ammo) - if(random <= get_ammo(0,0)) - chamber_round() - update_icon() - -/obj/item/weapon/gun/projectile/revolver/capgun - name = "cap gun" - desc = "Looks almost like the real thing! Ages 8 and up." - origin_tech = "combat=1;materials=1" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/cap" - /obj/item/weapon/gun/projectile/revolver/detective desc = "A cheap Martian knock-off of a classic law enforcement firearm. Uses .38-special rounds." name = "\improper .38 Mars Special" icon_state = "detective" origin_tech = "combat=2;materials=2" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/rev38" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38 + unique_rename = 1 + unique_reskin = 1 - -/obj/item/weapon/gun/projectile/revolver/detective/special_check(var/mob/living/carbon/human/M) - if(!ghettomodded) - return 1 - if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60 - to_chat(M, "[src] blows up in your face!") - M.take_organ_damage(0,20) - M.drop_item() - qdel(src) - return 0 - return 1 - -/obj/item/weapon/gun/projectile/revolver/detective/verb/rename_gun() - set name = "Name Gun" - set category = "Object" - set desc = "Click to rename your gun." - - var/mob/M = usr - var/input = stripped_input(M,"What do you want to name the gun?", ,"", MAX_NAME_LEN) - - if(src && input && !M.stat && in_range(M,src)) - name = input - to_chat(M, "You name the gun [input]. Say hello to your new friend.") - return 1 - -/obj/item/weapon/gun/projectile/revolver/detective/verb/reskin_gun() - set name = "Reskin gun" - set category = "Object" - set desc = "Click to reskin your gun." - - var/mob/M = usr - var/list/options = list() +/obj/item/weapon/gun/projectile/revolver/detective/New() + ..() options["The Original"] = "detective" options["Leopard Spots"] = "detective_leopard" options["Black Panther"] = "detective_panther" options["Gold Trim"] = "detective_gold" options["The Peacemaker"] = "detective_peacemaker" - var/choice = input(M,"What do you want to skin the gun to?","Reskin Gun") in options + options["Cancel"] = null - if(src && choice && !M.stat && in_range(M,src)) - icon_state = options[choice] - to_chat(M, "Your gun is now skinned as [choice]. Say hello to your new friend.") - return 1 - -/obj/item/weapon/gun/projectile/revolver/detective/attackby(var/obj/item/A as obj, mob/user as mob, params) +/obj/item/weapon/gun/projectile/revolver/detective/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override = "") + if(magazine.caliber != initial(magazine.caliber)) + if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60 + playsound(user, fire_sound, 50, 1) + to_chat(user, "[src] blows up in your face!") + user.take_organ_damage(0,20) + user.unEquip(src) + return 0 ..() - if(istype(A, /obj/item/weapon/screwdriver) || istype(A, /obj/item/weapon/conversion_kit)) + +/obj/item/weapon/gun/projectile/revolver/detective/attackby(obj/item/A, mob/user, params) + ..() + if(istype(A, /obj/item/weapon/screwdriver)) if(magazine.caliber == "38") - to_chat(user, "You begin to reinforce the barrel of [src].") + to_chat(user, "You begin to reinforce the barrel of [src]...") if(magazine.ammo_count()) afterattack(user, user) //you know the drill - user.visible_message("[src] goes off!", "[src] goes off in your face!") + user.visible_message("[src] goes off!", "[src] goes off in your face!") return if(do_after(user, 30, target = src)) if(magazine.ammo_count()) - to_chat(user, "You can't modify it!") + to_chat(user, "You can't modify it!") return - if (istype(A, /obj/item/weapon/conversion_kit)) - ghettomodded = 0 - else - ghettomodded = 1 magazine.caliber = "357" - desc = "[initial(desc)] The barrel and chamber assembly seems to have been modified." - to_chat(user, "You reinforce the barrel of [src]! Now it will fire .357 rounds.") + desc = "The barrel and chamber assembly seems to have been modified." + to_chat(user, "You reinforce the barrel of [src]. Now it will fire .357 rounds.") else - to_chat(user, "You begin to revert the modifications to [src].") + to_chat(user, "You begin to revert the modifications to [src]...") if(magazine.ammo_count()) afterattack(user, user) //and again - user.visible_message("[src] goes off!", "[src] goes off in your face!") + user.visible_message("[src] goes off!", "[src] goes off in your face!") return if(do_after(user, 30, target = src)) if(magazine.ammo_count()) - to_chat(user, "You can't modify it!") + to_chat(user, "You can't modify it!") return - ghettomodded = 0 magazine.caliber = "38" desc = initial(desc) - to_chat(user, "You remove the modifications on [src]! Now it will fire .38 rounds.") - - - + to_chat(user, "You remove the modifications on [src]. Now it will fire .38 rounds.") /obj/item/weapon/gun/projectile/revolver/mateba name = "\improper Unica 6 auto-revolver" @@ -181,6 +151,21 @@ icon_state = "mateba" origin_tech = "combat=2;materials=2" +/obj/item/weapon/gun/projectile/revolver/golden + name = "\improper Golden revolver" + desc = "This ain't no game, ain't never been no show, And I'll gladly gun down the oldest lady you know. Uses .357 ammo." + icon_state = "goldrevolver" + fire_sound = 'sound/weapons/resonator_blast.ogg' + recoil = 8 + +/obj/item/weapon/gun/projectile/revolver/nagant + name = "nagant revolver" + desc = "An old model of revolver that originated in Russia. Able to be suppressed. Uses 7.62x38mmR ammo." + icon_state = "nagant" + origin_tech = "combat=3" + can_suppress = 1 + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev762 + // A gun to play Russian Roulette! // You can spin the chamber to randomize the position of the bullet. @@ -188,35 +173,239 @@ name = "\improper Russian Revolver" desc = "A Russian-made revolver for drinking games. Uses .357 ammo, and has a mechanism that spins the chamber before each trigger pull." origin_tech = "combat=2;materials=2" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/rus357" + mag_type = /obj/item/ammo_box/magazine/internal/rus357 + var/spun = 0 /obj/item/weapon/gun/projectile/revolver/russian/New() ..() Spin() + update_icon() -/obj/item/weapon/gun/projectile/revolver/russian/attack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj) +/obj/item/weapon/gun/projectile/revolver/russian/proc/Spin() + chambered = null + var/random = rand(1, magazine.max_ammo) + if(random <= get_ammo(0,0)) + chamber_round() + spun = 1 - if(!chambered && target == user) - user.visible_message("\red *click*", "\red *click*") - return +/obj/item/weapon/gun/projectile/revolver/russian/attackby(obj/item/A, mob/user, params) + var/num_loaded = ..() + if(num_loaded) + user.visible_message("[user] loads a single bullet into the revolver and spins the chamber.", "You load a single bullet into the chamber and spin it.") + else + user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") + if(get_ammo() > 0) + Spin() + update_icon() + A.update_icon() + return - if(isliving(target) && isliving(user)) - if(target == user) - var/obj/item/organ/external/affecting = user.zone_sel.selecting - if(affecting == "head") - var/obj/item/ammo_casing/AC = chambered - if(!process_chambered()) - user.visible_message("\red *click*", "\red *click*") - return - if(!in_chamber) - return - var/obj/item/projectile/P = new AC.projectile_type - playsound(user, fire_sound, 50, 1) - user.visible_message("[user.name] fires [src] at \his head!", "You fire [src] at your head!", "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") - if(!P.nodamage) - user.apply_damage(300, BRUTE, affecting, sharp=1) // You are dead, dead, dead. +/obj/item/weapon/gun/projectile/revolver/russian/attack_self(mob/user) + if(!spun && can_shoot()) + user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") + Spin() + else + var/num_unloaded = 0 + while (get_ammo() > 0) + var/obj/item/ammo_casing/CB + CB = magazine.get_round() + chambered = null + CB.loc = get_turf(loc) + CB.update_icon() + num_unloaded++ + if (num_unloaded) + to_chat(user, "You unload [num_unloaded] shell\s from [src].") + else + to_chat(user, "[src] is empty.") + +/obj/item/weapon/gun/projectile/revolver/russian/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) + if(flag) + if(!(target in user.contents) && ismob(target)) + if(user.a_intent == "harm") // Flogging action return - ..() + if(isliving(user)) + if(!can_trigger_gun(user)) + return + if(target != user) + if(ismob(target)) + to_chat(user, "A mechanism prevents you from shooting anyone but yourself!") + return + if(ishuman(user)) + if(!spun) + to_chat(user, "You need to spin the revolver's chamber first!") + return + + spun = 0 + + if(chambered) + var/obj/item/ammo_casing/AC = chambered + if(AC.fire(user, user)) + playsound(user, fire_sound, 50, 1) + var/zone = check_zone(user.zone_sel.selecting) + if(zone == "head" || zone == "eyes" || zone == "mouth") + shoot_self(user, zone) + else + user.visible_message("[user.name] cowardly fires [src] at \his [zone]!", "You cowardly fire [src] at your [zone]!", "You hear a gunshot!") + return + + user.visible_message("*click*") + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + +/obj/item/weapon/gun/projectile/revolver/russian/proc/shoot_self(mob/living/carbon/human/user, affecting = "head") + user.apply_damage(300, BRUTE, affecting) + user.visible_message("[user.name] fires [src] at \his head!", "You fire [src] at your head!", "You hear a gunshot!") + +/obj/item/weapon/gun/projectile/revolver/capgun + name = "cap gun" + desc = "Looks almost like the real thing! Ages 8 and up." + origin_tech = "combat=1;materials=1" + mag_type = /obj/item/ammo_box/magazine/internal/cylinder/cap + +///////////////////////////// +// DOUBLE BARRELED SHOTGUN // +///////////////////////////// + +/obj/item/weapon/gun/projectile/revolver/doublebarrel + name = "double-barreled shotgun" + desc = "A true classic." + icon_state = "dshotgun" + item_state = "shotgun" + w_class = 4 + force = 10 + flags = CONDUCT + slot_flags = SLOT_BACK + origin_tech = "combat=3;materials=1" + mag_type = /obj/item/ammo_box/magazine/internal/shot/dual + sawn_desc = "Omar's coming!" + unique_rename = 1 + unique_reskin = 1 + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/New() + ..() + options["Default"] = "dshotgun" + options["Dark Red Finish"] = "dshotgun-d" + options["Ash"] = "dshotgun-f" + options["Faded Grey"] = "dshotgun-g" + options["Maple"] = "dshotgun-l" + options["Rosewood"] = "dshotgun-p" + options["Cancel"] = null + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/attackby(obj/item/A, mob/user, params) + ..() + if(istype(A, /obj/item/ammo_box) || istype(A, /obj/item/ammo_casing)) + chamber_round() + if(istype(A, /obj/item/weapon/melee/energy)) + var/obj/item/weapon/melee/energy/W = A + if(W.active) + sawoff(user) + if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/gun/energy/plasmacutter)) + sawoff(user) + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/attack_self(mob/living/user) + var/num_unloaded = 0 + while (get_ammo() > 0) + var/obj/item/ammo_casing/CB + CB = magazine.get_round(0) + chambered = null + CB.loc = get_turf(loc) + CB.update_icon() + num_unloaded++ + if (num_unloaded) + to_chat(user, "You break open \the [src] and unload [num_unloaded] shell\s.") + else + to_chat(user, "[src] is empty.") + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/isHandgun() //contrary to popular opinion, double barrels are not, shockingly, handguns + return 0 + +// IMPROVISED SHOTGUN // + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised + name = "improvised shotgun" + desc = "Essentially a tube that aims shotgun shells." + icon_state = "ishotgun" + item_state = "shotgun" + w_class = 4 + force = 10 + slot_flags = null + origin_tech = "combat=2;materials=2" + mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised + sawn_desc = "I'm just here for the gasoline." + unique_rename = 0 + unique_reskin = 0 + var/slung = 0 + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params) + ..() + if(istype(A, /obj/item/stack/cable_coil) && !sawn_state) + var/obj/item/stack/cable_coil/C = A + if(C.use(10)) + slot_flags = SLOT_BACK + icon_state = "ishotgunsling" + to_chat(user, "You tie the lengths of cable to the shotgun, making a sling.") + slung = 1 + update_icon() + else + to_chat(user, "You need at least ten lengths of cable if you want to make a sling.") + return + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/update_icon() + ..() + if (slung && (slot_flags & SLOT_BELT) ) + slung = 0 + icon_state = "ishotgun-sawn" + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/sawoff(mob/user) + . = ..() + if(. && slung) //sawing off the gun removes the sling + new /obj/item/stack/cable_coil(get_turf(src), 10) + slung = 0 + update_icon() + +//caneshotgun + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane + name = "cane" + desc = "A cane used by a true gentleman. Or a clown." + icon = 'icons/obj/weapons.dmi' + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + icon_state = "cane" + item_state = "stick" + sawn_state = SAWN_OFF + w_class = 2 + force = 10 + can_unsuppress = 0 + slot_flags = null + origin_tech = "" // NO GIVAWAYS + mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised + sawn_desc = "I'm sorry, but why did you saw your cane in the first place?" + attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") + fire_sound = 'sound/weapons/Gunshot_silenced.ogg' + suppressed = 1 + needs_permit = 0 //its just a cane beepsky..... + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane/update_icon() + return + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane/attackby(obj/item/A, mob/user, params) + ..() + if(istype(A, /obj/item/stack/cable_coil)) + return + +/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane/examine(mob/user) // HAD TO REPEAT EXAMINE CODE BECAUSE GUN CODE DOESNT STEALTH + var/f_name = "\a [src]." + if(blood_DNA && !istype(src, /obj/effect/decal)) + if(gender == PLURAL) + f_name = "some " + else + f_name = "a " + f_name += "blood-stained [name]!" + + to_chat(user, "\icon[src] That's [f_name]") + + if(desc) + to_chat(user, desc) diff --git a/code/modules/projectiles/guns/projectile/rocket.dm b/code/modules/projectiles/guns/projectile/rocket.dm deleted file mode 100644 index e667d9323ce..00000000000 --- a/code/modules/projectiles/guns/projectile/rocket.dm +++ /dev/null @@ -1,50 +0,0 @@ -/obj/item/weapon/gun/rocketlauncher - var/projectile - name = "rocket launcher" - desc = "Say hello to my little friend" - icon_state = "rocket" - item_state = "rocket" - w_class = 4.0 - throw_speed = 2 - throw_range = 10 - force = 5.0 - flags = CONDUCT - origin_tech = "combat=8;materials=5" - projectile = /obj/item/missile - var/missile_speed = 2 - var/missile_range = 30 - var/max_rockets = 1 - var/list/rockets = new/list() - -/obj/item/weapon/gun/rocketlauncher/examine(mob/user) - if(..(user, 2)) - to_chat(user, "\blue [rockets.len] / [max_rockets] rockets.") - -/obj/item/weapon/gun/rocketlauncher/attackby(obj/item/I as obj, mob/user as mob, params) - if(istype(I, /obj/item/ammo_casing/rocket)) - if(rockets.len < max_rockets) - user.drop_item() - I.loc = src - rockets += I - to_chat(user, "\blue You put the rocket in [src].") - to_chat(user, "\blue [rockets.len] / [max_rockets] rockets.") - else - to_chat(usr, "\red [src] cannot hold more rockets.") - -/obj/item/weapon/gun/rocketlauncher/can_fire() - return rockets.len - -/obj/item/weapon/gun/rocketlauncher/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0) - if(rockets.len) - var/obj/item/ammo_casing/rocket/I = rockets[1] - var/obj/item/missile/M = new projectile(user.loc) - playsound(user.loc, 'sound/effects/bang.ogg', 50, 1) - M.primed = 1 - M.throw_at(target, missile_range, missile_speed,user) - message_admins("[key_name_admin(user)] fired a rocket from a rocket launcher ([src.name]).") - log_game("[key_name_admin(user)] used a rocket launcher ([src.name]).") - rockets -= I - qdel(I) - return - else - to_chat(usr, "\red [src] is empty.") diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm new file mode 100644 index 00000000000..097f5fb4a58 --- /dev/null +++ b/code/modules/projectiles/guns/projectile/saw.dm @@ -0,0 +1,157 @@ +/obj/item/weapon/gun/projectile/automatic/l6_saw + name = "\improper L6 SAW" + desc = "A heavily modified 7.62 light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the reciever below the designation." + icon_state = "l6closed100" + item_state = "l6closedmag" + w_class = 5 + slot_flags = 0 + origin_tech = "combat=5;materials=1;syndicate=2" + mag_type = /obj/item/ammo_box/magazine/mm556x45 + weapon_weight = WEAPON_MEDIUM + fire_sound = 'sound/weapons/Gunshot3.ogg' + var/cover_open = 0 + can_suppress = 0 + burst_size = 3 + fire_delay = 1 + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user) + cover_open = !cover_open + to_chat(user, "You [cover_open ? "open" : "close"] [src]'s cover.") + update_icon() + +/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon() + icon_state = "l6[cover_open ? "open" : "closed"][magazine ? Ceiling(get_ammo(0)/12.5)*25 : "-empty"][suppressed ? "-suppressed" : ""]" + item_state = "l6[cover_open ? "openmag" : "closedmag"]" + +/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays + if(cover_open) + to_chat(user, "[src]'s cover is open! Close it before firing!") + else + ..() + update_icon() + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user) + if(loc != user) + ..() + return //let them pick it up + if(!cover_open || (cover_open && !magazine)) + ..() + else if(cover_open && magazine) + //drop the mag + magazine.update_icon() + magazine.loc = get_turf(loc) + user.put_in_hands(magazine) + magazine = null + update_icon() + to_chat(user, "You remove the magazine from [src].") + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attackby(obj/item/A, mob/user, params) + . = ..() + if(.) + return + if(!cover_open) + to_chat(user, "[src]'s cover is closed! You can't insert a new mag.") + return + ..() + +//ammo// + +/obj/item/projectile/bullet/saw + damage = 45 + armour_penetration = 5 + +/obj/item/projectile/bullet/saw/bleeding + damage = 20 + armour_penetration = 0 + +/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = 0, hit_zone) + . = ..() + if((blocked != 100) && istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + H.drip(350) + +/obj/item/projectile/bullet/saw/hollow + damage = 60 + armour_penetration = -10 + +/obj/item/projectile/bullet/saw/ap + damage = 40 + armour_penetration = 75 + +/obj/item/projectile/bullet/saw/incen + damage = 7 + armour_penetration = 0 + +obj/item/projectile/bullet/saw/incen/Move() + ..() + var/turf/location = get_turf(src) + if(location) + PoolOrNew(/obj/effect/hotspot, location) + location.hotspot_expose(700, 50, 1) + +/obj/item/projectile/bullet/saw/incen/on_hit(atom/target, blocked = 0) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/M = target + M.adjust_fire_stacks(3) + M.IgniteMob() + +//magazines// + +/obj/item/ammo_box/magazine/mm556x45 + name = "box magazine (5.56x45mm)" + icon_state = "a762-50" + origin_tech = "combat=2" + ammo_type = /obj/item/ammo_casing/mm556x45 + caliber = "mm55645" + max_ammo = 50 + +/obj/item/ammo_box/magazine/mm556x45/bleeding + name = "box magazine (Bleeding 5.56x45mm)" + origin_tech = "combat=3" + ammo_type = /obj/item/ammo_casing/mm556x45/bleeding + +/obj/item/ammo_box/magazine/mm556x45/hollow + name = "box magazine (Hollow-Point 5.56x45mm)" + origin_tech = "combat=3" + ammo_type = /obj/item/ammo_casing/mm556x45/hollow + +/obj/item/ammo_box/magazine/mm556x45/ap + name = "box magazine (Armor Penetrating 5.56x45mm)" + origin_tech = "combat=4" + ammo_type = /obj/item/ammo_casing/mm556x45/ap + +/obj/item/ammo_box/magazine/mm556x45/incen + name = "box magazine (Incendiary 5.56x45mm)" + origin_tech = "combat=4" + ammo_type = /obj/item/ammo_casing/mm556x45/incen + +/obj/item/ammo_box/magazine/mm556x45/update_icon() + ..() + icon_state = "a762-[round(ammo_count(),10)]" + +//casings// + +/obj/item/ammo_casing/mm556x45 + desc = "A 556x45mm bullet casing." + icon_state = "762-casing" + caliber = "mm55645" + projectile_type = /obj/item/projectile/bullet/saw + +/obj/item/ammo_casing/mm556x45/bleeding + desc = "A 556x45mm bullet casing with specialized inner-casing, that when it makes contact with a target, release tiny shrapnel to induce internal bleeding." + icon_state = "762-casing" + projectile_type = /obj/item/projectile/bullet/saw/bleeding + +/obj/item/ammo_casing/mm556x45/hollow + desc = "A 556x45mm bullet casing designed to cause more damage to unarmored targets." + projectile_type = /obj/item/projectile/bullet/saw/hollow + +/obj/item/ammo_casing/mm556x45/ap + desc = "A 556x45mm bullet casing designed with a hardened-tipped core to help penetrate armored targets." + projectile_type = /obj/item/projectile/bullet/saw/ap + +/obj/item/ammo_casing/mm556x45/incen + desc = "A 556x45mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames. " + projectile_type = /obj/item/projectile/bullet/saw/incen diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 7ae951ad908..ddec7543009 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -8,40 +8,34 @@ flags = CONDUCT slot_flags = SLOT_BACK origin_tech = "combat=4;materials=2" + mag_type = /obj/item/ammo_box/magazine/internal/shot var/recentpump = 0 // to prevent spammage - mag_type = "/obj/item/ammo_box/magazine/internal/shot" -/obj/item/weapon/gun/projectile/shotgun/attackby(var/obj/item/A as obj, mob/user as mob, params) - var/num_loaded = 0 - if(istype(A, /obj/item/ammo_box)) - var/obj/item/ammo_box/AM = A - for(var/obj/item/ammo_casing/AC in AM.stored_ammo) - var/didload = magazine.give_round(AC) - if(didload) - AM.stored_ammo -= AC - num_loaded++ - if(!didload || !magazine.multiload) - break - if(istype(A, /obj/item/ammo_casing)) - var/obj/item/ammo_casing/AC = A - if(magazine && magazine.give_round(AC)) - user.drop_item() - AC.loc = src - num_loaded++ +/obj/item/weapon/gun/projectile/shotgun/attackby(obj/item/A, mob/user, params) + . = ..() + if(.) + return + var/num_loaded = magazine.attackby(A, user, params, 1) if(num_loaded) to_chat(user, "You load [num_loaded] shell\s into \the [src]!") A.update_icon() update_icon() -/obj/item/weapon/gun/projectile/shotgun/process_chambered() +/obj/item/weapon/gun/projectile/shotgun/process_chamber() return ..(0, 0) /obj/item/weapon/gun/projectile/shotgun/chamber_round() return -/obj/item/weapon/gun/projectile/shotgun/attack_self(mob/living/user as mob) - if(recentpump) return +/obj/item/weapon/gun/projectile/shotgun/can_shoot() + if(!chambered) + return 0 + return (chambered.BB ? 1 : 0) + +/obj/item/weapon/gun/projectile/shotgun/attack_self(mob/living/user) + if(recentpump) + return pump(user) recentpump = 1 spawn(10) @@ -49,7 +43,7 @@ return -/obj/item/weapon/gun/projectile/shotgun/proc/pump(mob/M as mob) +/obj/item/weapon/gun/projectile/shotgun/proc/pump(mob/M) playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1) pump_unload(M) pump_reload(M) @@ -61,36 +55,41 @@ chambered.loc = get_turf(src)//Eject casing chambered.SpinAnimation(5, 1) chambered = null - if(in_chamber) - in_chamber = null /obj/item/weapon/gun/projectile/shotgun/proc/pump_reload(mob/M) - if(!magazine.ammo_count()) return 0 + if(!magazine.ammo_count()) + return 0 var/obj/item/ammo_casing/AC = magazine.get_round() //load next casing. chambered = AC /obj/item/weapon/gun/projectile/shotgun/examine(mob/user) - ..(user) + ..() if (chambered) to_chat(user, "A [chambered.BB ? "live" : "spent"] one is in the chamber.") /obj/item/weapon/gun/projectile/shotgun/isHandgun() //You cannot, in fact, holster a shotgun. return 0 +/obj/item/weapon/gun/projectile/shotgun/lethal + mag_type = /obj/item/ammo_box/magazine/internal/shot/lethal + // RIOT SHOTGUN // /obj/item/weapon/gun/projectile/shotgun/riot //for spawn in the armory name = "riot shotgun" desc = "A sturdy shotgun with a longer magazine and a fixed tactical stock designed for non-lethal riot control." icon_state = "riotshotgun" - mag_type = "/obj/item/ammo_box/magazine/internal/shotriot" + mag_type = /obj/item/ammo_box/magazine/internal/shot/riot sawn_desc = "Come with me if you want to live." -/obj/item/weapon/gun/projectile/shotgun/riot/attackby(var/obj/item/A as obj, mob/user as mob, params) +/obj/item/weapon/gun/projectile/shotgun/riot/attackby(obj/item/A, mob/user, params) ..() - if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/gun/energy/plasmacutter)) + if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/gun/energy/plasmacutter)) sawoff(user) - + if(istype(A, /obj/item/weapon/melee/energy)) + var/obj/item/weapon/melee/energy/W = A + if(W.active) + sawoff(user) /////////////////////// // BOLT ACTION RIFLE // @@ -102,7 +101,7 @@ icon_state = "moistnugget" item_state = "moistnugget" slot_flags = 0 //no SLOT_BACK sprite, alas - mag_type = "/obj/item/ammo_box/magazine/internal/boltaction" + mag_type = /obj/item/ammo_box/magazine/internal/boltaction var/bolt_open = 0 /obj/item/weapon/gun/projectile/shotgun/boltaction/pump(mob/M) @@ -115,21 +114,27 @@ update_icon() //I.E. fix the desc return 1 -/obj/item/weapon/gun/projectile/shotgun/boltaction/attackby(var/obj/item/A as obj, mob/user as mob) +/obj/item/weapon/gun/projectile/shotgun/blow_up(mob/user) + . = 0 + if(chambered && chambered.BB) + process_fire(user, user,0) + . = 1 + +/obj/item/weapon/gun/projectile/shotgun/boltaction/attackby(obj/item/A, mob/user, params) if(!bolt_open) to_chat(user, "The bolt is closed!") return . = ..() /obj/item/weapon/gun/projectile/shotgun/boltaction/examine(mob/user) - ..(user) + ..() to_chat(user, "The bolt is [bolt_open ? "open" : "closed"].") /obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted name = "enchanted bolt action rifle" desc = "Careful not to lose your head." var/guns_left = 30 - mag_type = "/obj/item/ammo_box/magazine/internal/boltaction/enchanted" + mag_type = /obj/item/ammo_box/magazine/internal/boltaction/enchanted /obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/New() ..() @@ -137,13 +142,14 @@ pump() /obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/dropped() + ..() guns_left = 0 -/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/Fire(atom/target as mob|obj|turf|area, mob/living/carbon/user as mob|obj, params, reflex = 0) +/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1) ..() if(guns_left) var/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/GUN = new - GUN.guns_left = src.guns_left - 1 + GUN.guns_left = guns_left - 1 user.drop_item() user.swap_hand() user.put_in_hands(GUN) @@ -153,205 +159,59 @@ throw_at(pick(oview(7,get_turf(user))),1,1) user.visible_message("[user] tosses aside the spent rifle!") +// Automatic Shotguns// -/obj/item/ammo_box/magazine/internal/boltaction/enchanted - max_ammo =1 +/obj/item/weapon/gun/projectile/shotgun/automatic -///////////////////////////// -// DOUBLE BARRELED SHOTGUN // -///////////////////////////// - -/obj/item/weapon/gun/projectile/revolver/doublebarrel - name = "double-barreled shotgun" - desc = "A true classic." - icon_state = "dshotgun" - item_state = "shotgun" - w_class = 4.0 - force = 10 - flags = CONDUCT - slot_flags = SLOT_BACK - origin_tech = "combat=3;materials=1" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/dualshot" - sawn_desc = "Omar's coming!" - -/obj/item/weapon/gun/projectile/revolver/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob, params) - ..() - if(istype(A, /obj/item/ammo_box) || istype(A, /obj/item/ammo_casing)) - chamber_round() - if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/gun/energy/plasmacutter)) - sawoff(user) - -/obj/item/weapon/gun/projectile/revolver/doublebarrel/attack_self(mob/living/user as mob) - var/num_unloaded = 0 - while (get_ammo() > 0) - var/obj/item/ammo_casing/CB - CB = magazine.get_round(0) - chambered = null - CB.loc = get_turf(src.loc) - CB.update_icon() - num_unloaded++ - if (num_unloaded) - to_chat(user, "You break open \the [src] and unload [num_unloaded] shell\s.") - else - to_chat(user, "[src] is empty.") - -/obj/item/weapon/gun/projectile/revolver/doublebarrel/isHandgun() //contrary to popular opinion, double barrels are not, shockingly, handguns - return 0 - -// IMPROVISED SHOTGUN // - -/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised - name = "improvised shotgun" - desc = "Essentially a tube that aims shotgun shells." - icon_state = "ishotgun" - item_state = "shotgun" - w_class = 4.0 - force = 10 - slot_flags = null - origin_tech = "combat=2;materials=2" - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/improvised" - sawn_desc = "I'm just here for the gasoline." - -/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/attackby(var/obj/item/A as obj, mob/user as mob, params) - ..() - if(istype(A, /obj/item/stack/cable_coil) && !sawn_state) - var/obj/item/stack/cable_coil/C = A - if(C.use(10)) - slot_flags = SLOT_BACK - icon_state = "ishotgunsling" - to_chat(user, "You tie the lengths of cable to the shotgun, making a sling.") - update_icon() - else - to_chat(user, "You need at least ten lengths of cable if you want to make a sling.") - return - -// Sawing guns related procs // - -/obj/item/weapon/gun/projectile/proc/blow_up(mob/user as mob) - if(get_ammo()) - afterattack(user, user) - playsound(user, fire_sound, 50, 1) - user.visible_message("The [src] goes off!", "The [src] goes off in your face!") - return - -/obj/item/weapon/gun/projectile/proc/sawoff(mob/user as mob) - if(sawn_state == SAWN_OFF) - to_chat(user, "\The [src] is already shortened.") - return - - if(sawn_state == SAWN_SAWING) - return - - user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src].") - - //if there's any live ammo inside the gun, makes it go off - if(blow_up(user)) - user.visible_message("\The [src] goes off!", "\The [src] goes off in your face!") - return - - sawn_state = SAWN_SAWING - - if(do_after(user, 30, target = src)) - user.visible_message("[user] shortens \the [src]!", "You shorten \the [src]!") - name = "sawn-off [src.name]" - desc = sawn_desc - icon_state = "[icon_state]-sawn" - w_class = 3.0 - item_state = "gun" - slot_flags &= ~SLOT_BACK //you can't sling it on your back - slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - sawn_state = SAWN_OFF - update_icon() - return - else - sawn_state = SAWN_INTACT - -/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog - name = "\improper 'Bulldog' Shotgun" - desc = "A compact, mag-fed semi-automatic shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines." - icon_state = "bulldog" - item_state = "bulldog" - w_class = 3.0 - origin_tech = "combat=5;materials=4;syndicate=6" - mag_type = "/obj/item/ammo_box/magazine/m12g" - fire_sound = 'sound/weapons/Gunshot4.ogg' - can_suppress = 0 - burst_size = 1 - fire_delay = 0 - action_button_name = null - -/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/New() - ..() - update_icon() - return - -/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/proc/update_magazine() - if(magazine) - overlays.Cut() - overlays += "[magazine.icon_state]" - return - -/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/update_icon() - overlays.Cut() - update_magazine() - icon_state = "bulldog[chambered ? "" : "-e"]" - return - -/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag) - ..() - empty_alarm() - return - -/obj/item/weapon/gun/projectile/shotgun/automatic/Fire(mob/living/user as mob|obj) +/obj/item/weapon/gun/projectile/shotgun/automatic/shoot_live_shot(mob/living/user as mob|obj) ..() pump(user) -// COMBAT SHOTGUN // - /obj/item/weapon/gun/projectile/shotgun/automatic/combat name = "combat shotgun" desc = "A semi automatic shotgun with tactical furniture and a six-shell capacity underneath." icon_state = "cshotgun" origin_tech = "combat=5;materials=2" - mag_type = "/obj/item/ammo_box/magazine/internal/shotcom" + mag_type = /obj/item/ammo_box/magazine/internal/shot/com w_class = 5 -//caneshotgun +//Dual Feed Shotgun -/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane - name = "cane" - desc = "A cane used by a true gentlemen. Or a clown." - icon = 'icons/obj/weapons.dmi' - icon_state = "cane" - item_state = "stick" - sawn_state = SAWN_OFF - w_class = 2 - force = 10 - can_unsuppress = 0 - slot_flags = null - origin_tech = "" // NO GIVAWAYS - mag_type = "/obj/item/ammo_box/magazine/internal/cylinder/improvised" - sawn_desc = "I'm sorry, but why did you saw your cane in the first place?" - attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") - fire_sound = 'sound/weapons/Gunshot_silenced.ogg' - silenced = 1 - needs_permit = 0 //its just a cane beepsky..... +/obj/item/weapon/gun/projectile/shotgun/automatic/dual_tube + name = "cycler shotgun" + desc = "An advanced shotgun with two separate magazine tubes, allowing you to quickly toggle between ammo types." + icon_state = "cycler" + origin_tech = "combat=4;materials=2" + mag_type = /obj/item/ammo_box/magazine/internal/shot/tube + w_class = 5 + var/toggled = 0 + var/obj/item/ammo_box/magazine/internal/shot/alternate_magazine -/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane/attackby(obj/item/A, mob/user, params) +/obj/item/weapon/gun/projectile/shotgun/automatic/dual_tube/New() ..() - if(istype(A, /obj/item/stack/cable_coil)) + if (!alternate_magazine) + alternate_magazine = new mag_type(src) + +/obj/item/weapon/gun/projectile/shotgun/automatic/dual_tube/attack_self(mob/living/user) + if(!chambered && magazine.contents.len) + pump() + else + toggle_tube(user) + +/obj/item/weapon/gun/projectile/shotgun/automatic/dual_tube/proc/toggle_tube(mob/living/user) + var/current_mag = magazine + var/alt_mag = alternate_magazine + magazine = alt_mag + alternate_magazine = current_mag + toggled = !toggled + if(toggled) + to_chat(user, "You switch to tube B.") + else + to_chat(user, "You switch to tube A.") + +/obj/item/weapon/gun/projectile/shotgun/automatic/dual_tube/AltClick(mob/living/user) + if(user.incapacitated() || !Adjacent(user) || !istype(user)) return + pump() -/obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised/cane/examine(mob/user) // HAD TO REPEAT EXAMINE CODE BECAUSE GUN CODE DOESNT STEALTH - var/f_name = "\a [src]." - if(src.blood_DNA && !istype(src, /obj/effect/decal)) - if(gender == PLURAL) - f_name = "some " - else - f_name = "a " - f_name += "blood-stained [name]!" - - to_chat(user, "\icon[src] That's [f_name]") - - if(desc) - to_chat(user, desc) \ No newline at end of file +// DOUBLE BARRELED SHOTGUN, IMPROVISED SHOTGUN, and CANE SHOTGUN are in revolver.dm diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index ee70bb3f80b..59bd7fb649b 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -4,8 +4,8 @@ icon_state = "sniper" item_state = "sniper" recoil = 2 - heavy_weapon = 1 - mag_type = "/obj/item/ammo_box/magazine/sniper_rounds" + weapon_weight = WEAPON_MEDIUM + mag_type = /obj/item/ammo_box/magazine/sniper_rounds fire_delay = 40 origin_tech = "combat=8" can_unsuppress = 1 @@ -35,18 +35,18 @@ max_ammo = 6 caliber = ".50" -/obj/item/ammo_casing/point50 - desc = "A .50 bullet casing." - caliber = ".50" - projectile_type = /obj/item/projectile/bullet/sniper - icon_state = ".50" - /obj/item/ammo_box/magazine/sniper_rounds/update_icon() if(ammo_count()) icon_state = "[initial(icon_state)]-ammo" else icon_state = "[initial(icon_state)]" +/obj/item/ammo_casing/point50 + desc = "A .50 bullet casing." + caliber = ".50" + projectile_type = /obj/item/projectile/bullet/sniper + icon_state = ".50" + /obj/item/projectile/bullet/sniper damage = 70 stun = 5 @@ -69,8 +69,6 @@ origin_tech = "combat=6;syndicate=3" ammo_type = /obj/item/ammo_casing/soporific max_ammo = 3 - caliber = ".50" - icon_state = ".50" /obj/item/ammo_casing/soporific desc = "A .50 bullet casing, specialised in sending the target to sleep, instead of hell." @@ -79,10 +77,10 @@ icon_state = ".50" /obj/item/projectile/bullet/sniper/soporific + armour_penetration = 0 nodamage = 1 stun = 0 weaken = 0 - armour_penetration = 0 breakthings = FALSE /obj/item/projectile/bullet/sniper/soporific/on_hit(atom/target, blocked = 0, hit_zone) @@ -102,8 +100,6 @@ origin_tech = "combat=7;syndicate=5" ammo_type = /obj/item/ammo_casing/haemorrhage max_ammo = 5 - caliber = ".50" - icon_state = ".50" /obj/item/ammo_casing/haemorrhage desc = "A .50 bullet casing, specialised in causing massive bloodloss" @@ -112,11 +108,11 @@ icon_state = ".50" /obj/item/projectile/bullet/sniper/haemorrhage + armour_penetration = 15 damage = 15 stun = 0 weaken = 0 breakthings = FALSE - armour_penetration = 15 /obj/item/projectile/bullet/sniper/haemorrhage/on_hit(atom/target, blocked = 0, hit_zone) if((blocked != 100) && istype(target, /mob/living/carbon/human)) @@ -145,4 +141,4 @@ forcedodge = 1 stun = 0 weaken = 0 - breakthings = FALSE \ No newline at end of file + breakthings = FALSE diff --git a/code/modules/projectiles/guns/projectile/toy.dm b/code/modules/projectiles/guns/projectile/toy.dm index 7bb290f4f46..c0465a83beb 100644 --- a/code/modules/projectiles/guns/projectile/toy.dm +++ b/code/modules/projectiles/guns/projectile/toy.dm @@ -1,10 +1,11 @@ /obj/item/weapon/gun/projectile/automatic/toy name = "foam force SMG" desc = "A prototype three-round burst toy submachine gun. Ages 8 and up." - icon = 'icons/obj/toyguns.dmi' + icon = 'icons/obj/guns/toy.dmi' icon_state = "saber" item_state = "gun" - mag_type = "/obj/item/ammo_box/magazine/toy/smg" + mag_type = /obj/item/ammo_box/magazine/toy/smg + fire_sound = 'sound/weapons/Gunshot_smg.ogg' force = 0 throwforce = 0 burst_size = 3 @@ -12,15 +13,15 @@ clumsy_check = 0 needs_permit = 0 -/obj/item/weapon/gun/projectile/automatic/toy/process_chambered() - return ..(0, 1) +/obj/item/weapon/gun/projectile/automatic/toy/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() /obj/item/weapon/gun/projectile/automatic/toy/pistol name = "foam force pistol" desc = "A small, easily concealable toy handgun. Ages 8 and up." icon_state = "pistol" w_class = 2 - mag_type = "/obj/item/ammo_box/magazine/toy/pistol" + mag_type = /obj/item/ammo_box/magazine/toy/pistol fire_sound = 'sound/weapons/Gunshot.ogg' can_suppress = 0 burst_size = 1 @@ -34,67 +35,65 @@ /obj/item/weapon/gun/projectile/automatic/toy/pistol/riot name = "foam force riot pistol" desc = "RIOT! Ages 8 and up." + mag_type = /obj/item/ammo_box/magazine/toy/pistol/riot /obj/item/weapon/gun/projectile/automatic/toy/pistol/riot/New() magazine = new /obj/item/ammo_box/magazine/toy/pistol/riot(src) ..() -/obj/item/weapon/gun/projectile/automatic/c20r/toy - name = "donksoft SMG" - desc = "A bullpup two-round burst toy SMG, designated 'C-20r'. Ages 8 and up." - icon = 'icons/obj/toyguns.dmi' - can_suppress = 0 - needs_permit = 0 - mag_type = "/obj/item/ammo_box/magazine/toy/smgm45" - -/obj/item/weapon/gun/projectile/automatic/c20r/toy/process_chambered() - return ..(0, 1) - -/obj/item/weapon/gun/projectile/automatic/l6_saw/toy - name = "donksoft LMG" - desc = "A heavily modified toy light machine gun, designated 'L6 SAW'. Ages 8 and up." - icon = 'icons/obj/toyguns.dmi' - can_suppress = 0 - needs_permit = 0 - mag_type = "/obj/item/ammo_box/magazine/toy/m762" - -/obj/item/weapon/gun/projectile/automatic/l6_saw/toy/process_chambered() - return ..(0, 1) - - - /obj/item/weapon/gun/projectile/shotgun/toy name = "foam force shotgun" desc = "A toy shotgun with wood furniture and a four-shell capacity underneath. Ages 8 and up." - icon = 'icons/obj/toyguns.dmi' + icon = 'icons/obj/guns/toy.dmi' force = 0 throwforce = 0 origin_tech = null - mag_type = "/obj/item/ammo_box/magazine/internal/shot/toy" + mag_type = /obj/item/ammo_box/magazine/internal/shot/toy clumsy_check = 0 needs_permit = 0 -/obj/item/weapon/gun/projectile/shotgun/toy/pump_unload() - if(chambered)//We have a shell in the chamber - chambered = null - if(in_chamber) - in_chamber = null +/obj/item/weapon/gun/projectile/shotgun/toy/process_chamber() + ..() + if(chambered && !chambered.BB) + qdel(chambered) /obj/item/weapon/gun/projectile/shotgun/toy/crossbow name = "foam force crossbow" desc = "A weapon favored by many overactive children. Ages 8 and up." icon_state = "crossbow" item_state = "crossbow" - mag_type = "/obj/item/ammo_box/magazine/internal/shot/toy/crossbow" + mag_type = /obj/item/ammo_box/magazine/internal/shot/toy/crossbow fire_sound = 'sound/items/syringeproj.ogg' slot_flags = SLOT_BELT w_class = 2 +/obj/item/weapon/gun/projectile/automatic/c20r/toy + name = "donksoft SMG" + desc = "A bullpup two-round burst toy SMG, designated 'C-20r'. Ages 8 and up." + icon = 'icons/obj/guns/toy.dmi' + can_suppress = 0 + needs_permit = 0 + mag_type = /obj/item/ammo_box/magazine/toy/smgm45 + +/obj/item/weapon/gun/projectile/automatic/c20r/toy/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() + +/obj/item/weapon/gun/projectile/automatic/l6_saw/toy + name = "donksoft LMG" + desc = "A heavily modified toy light machine gun, designated 'L6 SAW'. Ages 8 and up." + icon = 'icons/obj/guns/toy.dmi' + can_suppress = 0 + needs_permit = 0 + mag_type = /obj/item/ammo_box/magazine/toy/m762 + +/obj/item/weapon/gun/projectile/automatic/l6_saw/toy/process_chamber(eject_casing = 0, empty_chamber = 1) + ..() + /obj/item/weapon/gun/projectile/shotgun/toy/tommygun name = "tommy gun" desc = "Looks almost like the real thing! Great for practicing Drive-bys. Ages 8 and up." - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/projectile.dmi' icon_state = "tommy" item_state = "shotgun" - mag_type = "/obj/item/ammo_box/magazine/internal/shot/toy/tommygun" + mag_type = /obj/item/ammo_box/magazine/internal/shot/toy/tommygun w_class = 2 diff --git a/code/modules/projectiles/guns/rocket.dm b/code/modules/projectiles/guns/rocket.dm new file mode 100644 index 00000000000..72ab89bf40e --- /dev/null +++ b/code/modules/projectiles/guns/rocket.dm @@ -0,0 +1,58 @@ +/obj/item/weapon/gun/rocketlauncher + var/projectile + name = "rocket launcher" + desc = "Say hello to my little friend" + icon_state = "rocket" + item_state = "rocket" + w_class = 4.0 + throw_speed = 2 + throw_range = 10 + force = 5.0 + flags = CONDUCT + origin_tech = "combat=8;materials=5" + var/missile_speed = 2 + var/missile_range = 30 + var/max_rockets = 1 + var/list/rockets = new/list() + +/obj/item/weapon/gun/rocketlauncher/examine(mob/user) + ..() + to_chat(user, "[rockets.len] / [max_rockets] rockets.") + +/obj/item/weapon/gun/rocketlauncher/Destroy() + for(var/datum/D in rockets) + qdel(D) + rockets = null + + return ..() + +/obj/item/weapon/gun/rocketlauncher/update_icon() + return + +/obj/item/weapon/gun/rocketlauncher/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/ammo_casing/rocket)) + if(rockets.len < max_rockets) + user.drop_item() + I.loc = src + rockets += I + to_chat(user, "You put the rocket in [src].") + to_chat(user, "[rockets.len] / [max_rockets] rockets.") + else + to_chat(usr, "[src] cannot hold more rockets.") + +/obj/item/weapon/gun/rocketlauncher/can_shoot() + return rockets.len + +/obj/item/weapon/gun/rocketlauncher/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override = "") + if(rockets.len) + var/obj/item/ammo_casing/rocket/I = rockets[1] + var/obj/item/missile/M = new /obj/item/missile(user.loc) + playsound(user.loc, 'sound/effects/bang.ogg', 50, 1) + M.primed = 1 + M.throw_at(target, missile_range, missile_speed, user, 1) + message_admins("[key_name_admin(user)] fired a rocket from a rocket launcher ([name]).") + log_game("[key_name_admin(user)] used a rocket launcher ([name]).") + rockets -= I + qdel(I) + else + to_chat(usr, "[src] is empty.") diff --git a/code/modules/projectiles/guns/syringe_gun.dm b/code/modules/projectiles/guns/syringe_gun.dm index 0e43d550c85..332d279376b 100644 --- a/code/modules/projectiles/guns/syringe_gun.dm +++ b/code/modules/projectiles/guns/syringe_gun.dm @@ -13,25 +13,41 @@ var/list/syringes = list() var/max_syringes = 1 -/obj/item/weapon/gun/syringe/process_chambered() - if(!syringes.len) return 0 +/obj/item/weapon/gun/syringe/New() + ..() + chambered = new /obj/item/ammo_casing/syringegun(src) + +/obj/item/weapon/gun/syringe/newshot() + if(!syringes.len) + return var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] - if(!S) return 0 + if(!S) + return - in_chamber = new /obj/item/projectile/bullet/dart/syringe(src) - S.reagents.trans_to(in_chamber, S.reagents.total_volume) - in_chamber.name = S.name + chambered.BB = new S.projectile_type (src) + + S.reagents.trans_to(chambered.BB, S.reagents.total_volume) + chambered.BB.name = S.name syringes.Remove(S) qdel(S) - return 1 + return + +/obj/item/weapon/gun/syringe/process_chamber() + return + +/obj/item/weapon/gun/syringe/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) + if(target == loc) + return + newshot() + ..() /obj/item/weapon/gun/syringe/examine(mob/user) - ..(user) + ..() to_chat(user, "Can hold [max_syringes] syringe\s. Has [syringes.len] syringe\s remaining.") - + /obj/item/weapon/gun/syringe/attack_self(mob/living/user as mob) if(!syringes.len) to_chat(user, "[src] is empty.") @@ -39,24 +55,26 @@ var/obj/item/weapon/reagent_containers/syringe/S = syringes[syringes.len] - if(!S) return 0 - S.forceMove(user.loc) + if(!S) + return 0 + S.loc = user.loc syringes.Remove(S) to_chat(user, "You unload [S] from \the [src]!") return 1 -/obj/item/weapon/gun/syringe/attackby(var/obj/item/A as obj, mob/user as mob, var/show_msg = 1, params) +/obj/item/weapon/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = 1) if(istype(A, /obj/item/weapon/reagent_containers/syringe)) if(syringes.len < max_syringes) - user.drop_item() + if(!user.unEquip(A)) + return to_chat(user, "You load [A] into \the [src]!") syringes.Add(A) - A.forceMove(src) + A.loc = src return 1 else - to_chat(usr, "[src] cannot hold more syringes.") + to_chat(user, "[src] cannot hold more syringes.") return 0 /obj/item/weapon/gun/syringe/rapidsyringe @@ -64,7 +82,7 @@ desc = "A modification of the syringe gun design, using a rotating cylinder to store up to six syringes." icon_state = "rapidsyringegun" max_syringes = 6 - + /obj/item/weapon/gun/syringe/syndicate name = "dart pistol" desc = "A small spring-loaded sidearm that functions identically to a syringe gun." @@ -73,5 +91,5 @@ w_class = 2 origin_tech = "combat=2;syndicate=2" force = 2 //Also very weak because it's smaller - silenced = 1 //Softer fire sound + suppressed = 1 //Softer fire sound can_unsuppress = 0 //Permanently silenced diff --git a/code/modules/projectiles/guns/throw.dm b/code/modules/projectiles/guns/throw.dm new file mode 100644 index 00000000000..d1bcda59067 --- /dev/null +++ b/code/modules/projectiles/guns/throw.dm @@ -0,0 +1,93 @@ +/obj/item/weapon/gun/throw + name = "abstract item thrower" + desc = "This shouldn't be here, yell at a coder." + fire_sound = 'sound/weapons/punchmiss.ogg' + fire_sound_text = "thwock" + + var/obj/item/to_launch + var/list/valid_projectile_type + var/max_capacity = 1 + var/list/loaded_projectiles = list() + + var/projectile_speed = 1 + var/projectile_range = 1 + +/obj/item/weapon/gun/throw/proc/notify_ammo_count(mob/user) + return + +/obj/item/weapon/gun/throw/proc/get_throwrange() + return projectile_speed + +/obj/item/weapon/gun/throw/proc/get_throwspeed() + return projectile_range + +/obj/item/weapon/gun/throw/proc/modify_projectile(obj/item/I, on_chamber = 0) + return + +/obj/item/weapon/gun/throw/proc/get_ammocount(include_loaded = 1) + var/count = loaded_projectiles.len + if(include_loaded && to_launch) + count++ + return count + +/obj/item/weapon/gun/throw/examine(mob/user) + ..() + to_chat(user, "It is [to_launch ? "loaded with \a [to_launch]" : "not loaded"].") + notify_ammo_count(user) + +/obj/item/weapon/gun/throw/Destroy() + qdel(to_launch) + to_launch = null + for(var/atom/A in loaded_projectiles) + qdel(A) + loaded_projectiles = null + + return ..() + +/obj/item/weapon/gun/throw/update_icon() + return + +/obj/item/weapon/gun/throw/attackby(obj/item/I, mob/user, params) + if(istype(I, valid_projectile_type) && !(I.flags & NODROP)) + if(get_ammocount() < max_capacity) + user.drop_item() + I.forceMove(src) + loaded_projectiles += I + to_chat(user, "You load [I] into [src].") + if(!to_launch) + process_chamber() + notify_ammo_count(user) + else + to_chat(user, "[src] cannot hold any more projectiles.") + else + to_chat(user, "You cannot load [I] into [src]!") + +/obj/item/weapon/gun/throw/process_chamber() + if(!to_launch && loaded_projectiles.len) + to_launch = loaded_projectiles[1] + loaded_projectiles -= to_launch + return + +/obj/item/weapon/gun/throw/can_shoot() + if(to_launch) + return 1 + return 0 + +/obj/item/weapon/gun/throw/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) + add_fingerprint(user) + if(semicd) + return + + var/obj/item/I = to_launch + I.forceMove(get_turf(src)) + to_launch = null + modify_projectile(I) + playsound(user, fire_sound, 50, 1) + I.throw_at(target, get_throwrange(), get_throwspeed(), user, 1) + message_admins("[key_name_admin(user)] fired \a [I] from a [src].") + log_game("[key_name_admin(user)] used \a [src].") + process_chamber() + + semicd = 1 + spawn(fire_delay) + semicd = 0 diff --git a/code/modules/projectiles/guns/throw/crossbow.dm b/code/modules/projectiles/guns/throw/crossbow.dm new file mode 100644 index 00000000000..55e76bec6b7 --- /dev/null +++ b/code/modules/projectiles/guns/throw/crossbow.dm @@ -0,0 +1,181 @@ +#define XBOW_TENSION_20 "20%" +#define XBOW_TENSION_40 "40%" +#define XBOW_TENSION_60 "60%" +#define XBOW_TENSION_80 "80%" +#define XBOW_TENSION_FULL "100%" + +/obj/item/weapon/gun/throw/crossbow + name = "powered crossbow" + desc = "A modern twist on an old classic. Pick up that can." + icon_state = "crossbow" + item_state = "crossbow-solid" + fire_sound_text = "a solid thunk" + fire_delay = 25 + + valid_projectile_type = /obj/item/weapon/arrow + + var/tension = 0 + var/drawtension = 5 + var/maxtension = 5 + var/speed_multiplier = 5 + var/range_multiplier = 3 + var/obj/item/weapon/stock_parts/cell/cell = null // Used for firing superheated rods. + var/list/possible_tensions = list(XBOW_TENSION_20, XBOW_TENSION_40, XBOW_TENSION_60, XBOW_TENSION_80, XBOW_TENSION_FULL) + +/obj/item/weapon/gun/throw/crossbow/emp_act(severity) + if(cell && severity) + emp_act(severity) + +/obj/item/weapon/gun/throw/crossbow/update_icon() + if(!tension) + if(!to_launch) + icon_state = "[initial(icon_state)]" + else + icon_state = "[initial(icon_state)]-nocked" + else + icon_state = "[initial(icon_state)]-drawn" + +/obj/item/weapon/gun/throw/crossbow/examine(mob/user) + ..() + if(cell) + to_chat(user, "\A [cell] is mounted onto [src]. Battery cell charge: [cell.charge]/[cell.maxcharge]") + else + to_chat(user, "It has an empty mount for a battery cell.") + +/obj/item/weapon/gun/throw/crossbow/modify_projectile(obj/item/I, on_chamber = 0) + if(cell && on_chamber && istype(I, /obj/item/weapon/arrow/rod)) + var/obj/item/weapon/arrow/rod/R = I + visible_message("[R] plinks and crackles as it begins to glow red-hot.") + R.throwforce = 15 + R.superheated = 1 + cell.use(500) + +/obj/item/weapon/gun/throw/crossbow/get_throwspeed() + return tension * speed_multiplier + +/obj/item/weapon/gun/throw/crossbow/get_throwrange() + return tension * range_multiplier + +/obj/item/weapon/gun/throw/crossbow/process_chamber() + ..() + if(to_launch) + modify_projectile(to_launch, 1) + update_icon() + +/obj/item/weapon/gun/throw/crossbow/attack_self(mob/living/user) + if(tension) + if(to_launch) + user.visible_message("[user] relaxes the tension on [src]'s string and removes [to_launch].","You relax the tension on [src]'s string and remove [to_launch].") + to_launch.forceMove(get_turf(src)) + var/obj/item/weapon/arrow/A = to_launch + to_launch = null + A.removed() + process_chamber() + else + user.visible_message("[user] relaxes the tension on [src]'s string.","You relax the tension on [src]'s string.") + tension = 0 + update_icon() + else + draw(user) + +/obj/item/weapon/gun/throw/crossbow/proc/draw(mob/living/user) + if(user.incapacitated()) + return + if(!to_launch) + to_chat(user, "You can't draw [src] without a bolt nocked.") + return + + user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].") + if(do_after(user, 25 * drawtension, target = user)) + tension = drawtension + user.visible_message("[usr] draws back the string of [src]!","[src] clunks as you draw the string to its maximum tension!!") + update_icon() + +/obj/item/weapon/gun/throw/crossbow/attackby(obj/item/W as obj, mob/user as mob, params) + if(istype(W, /obj/item/weapon/stock_parts/cell)) + if(!cell) + user.drop_item() + W.loc = src + cell = W + to_chat(user, "You jam [cell] into [src] and wire it to the firing coil.") + process_chamber() + else + to_chat(user, "[src] already has a cell installed.") + else if(istype(W, /obj/item/weapon/screwdriver)) + if(cell) + cell.loc = get_turf(src) + to_chat(user, "You jimmy [cell] out of [src] with [W].") + cell = null + else + to_chat(user, "[src] doesn't have a cell installed.") + else + ..() + +/obj/item/weapon/gun/throw/crossbow/verb/set_tension() + set name = "Adjust Tension" + set category = "Object" + set src in range(0) + + var/mob/user = usr + if(user.incapacitated()) + return + var/choice = input("Select tension to draw to:", "[src]", XBOW_TENSION_FULL) as null|anything in possible_tensions + if(!choice) + return + + switch(choice) + if(XBOW_TENSION_20) + drawtension = Ceiling(0.2 * maxtension) + if(XBOW_TENSION_40) + drawtension = Ceiling(0.4 * maxtension) + if(XBOW_TENSION_60) + drawtension = Ceiling(0.6 * maxtension) + if(XBOW_TENSION_80) + drawtension = Ceiling(0.8 * maxtension) + if(XBOW_TENSION_FULL) + drawtension = maxtension + +/obj/item/weapon/gun/throw/crossbow/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) + ..() + tension = 0 + update_icon() +/obj/item/weapon/gun/throw/crossbow/french + name = "french powered crossbow" + icon_state = "fcrossbow" + valid_projectile_type = /obj/item/weapon/reagent_containers/food/snacks/baguette + +/obj/item/weapon/gun/throw/crossbow/french/modify_projectile(obj/item/I, on_chamber = 0) + return + +/obj/item/weapon/arrow + name = "bolt" + desc = "It's got a tip for you - get the point?" + icon_state = "bolt" + item_state = "bolt" + throwforce = 20 + w_class = 3.0 + sharp = 1 + edge = 0 + +/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart. + return + +/obj/item/weapon/arrow/rod + name = "makeshift bolt" + desc = "A sharpened metal rod that can be fired out of a crossbow." + icon_state = "metal-rod" + throwforce = 8 + var/superheated = 0 + +/obj/item/weapon/arrow/rod/removed() + if(superheated) // The rod has been superheated - we don't want it to be useable when removed from the bow. + visible_message("[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.") + var/obj/item/weapon/shard/shrapnel/S = new /obj/item/weapon/shard/shrapnel + S.loc = get_turf(src) + qdel(src) + +#undef XBOW_TENSION_20 +#undef XBOW_TENSION_40 +#undef XBOW_TENSION_60 +#undef XBOW_TENSION_80 +#undef XBOW_TENSION_FULL diff --git a/code/modules/projectiles/guns/throw/pielauncher.dm b/code/modules/projectiles/guns/throw/pielauncher.dm new file mode 100644 index 00000000000..f6405f47194 --- /dev/null +++ b/code/modules/projectiles/guns/throw/pielauncher.dm @@ -0,0 +1,36 @@ +/obj/item/weapon/gun/throw/piecannon + name = "pie cannon" + desc = "A projectile weapon that fires pies." + icon_state = "piecannon" + w_class = 5 + throw_speed = 2 + throw_range = 3 + force = 5 + + clumsy_check = 0 + valid_projectile_type = /obj/item/weapon/reagent_containers/food/snacks/pie + max_capacity = 5 + projectile_speed = 2 + projectile_range = 30 + + +/obj/item/weapon/gun/throw/piecannon/New() + ..() + for(var/i in 1 to max_capacity) + var/obj/item/weapon/reagent_containers/food/snacks/pie/P = new /obj/item/weapon/reagent_containers/food/snacks/pie(src) + loaded_projectiles += P + process_chamber() + +/obj/item/weapon/gun/throw/piecannon/notify_ammo_count(mob/user) + to_chat(user, "[src] has [get_ammocount()] of [max_capacity] pies left.") + +/obj/item/weapon/gun/throw/piecannon/update_icon() + if(to_launch) + icon_state = "piecannon1" + else + icon_state = "piecannon0" + item_state = icon_state + +/obj/item/weapon/gun/throw/piecannon/process_chamber() + ..() + update_icon() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 5a028a1084a..5a8fa77e268 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1,353 +1,223 @@ -/* -#define BRUTE "brute" -#define BURN "burn" -#define TOX "tox" -#define OXY "oxy" -#define CLONE "clone" - -#define ADD "add" -#define SET "set" -*/ - /obj/item/projectile name = "projectile" icon = 'icons/obj/projectiles.dmi' icon_state = "bullet" - density = 1 + density = 0 unacidable = 1 anchored = 1 //There's a reason this is here, Mport. God fucking damn it -Agouri. Find&Fix by Pete. The reason this is here is to stop the curving of emitter shots. + flags = ABSTRACT pass_flags = PASSTABLE mouse_opacity = 0 hitsound = 'sound/weapons/pierce.ogg' - animate_movement = 0 - var/bumped = 0 //Prevents it from hitting more than one guy at once + var/hitsound_wall = "" + pressure_resistance = INFINITY var/def_zone = "" //Aiming at var/mob/firer = null//Who shot it - var/silenced = 0 //Attack message + var/obj/item/ammo_casing/ammo_casing = null + var/suppressed = 0 //Attack message var/yo = null var/xo = null var/current = null - var/obj/shot_from = null // the object which shot us var/atom/original = null // the original target clicked var/turf/starting = null // the projectile's starting turf var/list/permutated = list() // we've passed through these atoms, don't try to hit them again var/paused = FALSE //for suspending the projectile midair - var/p_x = 16 var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center + var/speed = 1 //Amount of deciseconds it takes for projectile to travel + var/Angle = 0 + var/spread = 0 //amount (in degrees) of projectile spread + var/legacy = 0 //legacy projectile system + animate_movement = 0 var/damage = 10 var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid var/projectile_type = "/obj/item/projectile" - var/kill_count = 50 //This will de-increment every process(). When 0, it will delete the projectile. - //Effects + var/range = 50 //This will de-increment every step. When 0, it will delete the projectile. + //Effects var/stun = 0 var/weaken = 0 var/paralyze = 0 var/irradiate = 0 - var/slur = 0 var/stutter = 0 + var/slur = 0 var/eyeblur = 0 var/drowsy = 0 var/stamina = 0 var/jitter = 0 var/embed = 0 // whether or not the projectile can embed itself in the mob - var/forcedodge = 0 + var/forcedodge = 0 //to pass through everything - var/range = 0 - var/proj_hit = 0 +/obj/item/projectile/New() + permutated = list() + return ..() - var/chatlog_attacks = 1 +/obj/item/projectile/proc/Range() + range-- + if(range <= 0 && loc) + on_range() - var/speed = 1 //Amount of deciseconds it takes for projectile to travel. Animation is adjusted accordingly. - var/Angle = 0 //For new projectiles - var/spread = 0 //Amount of degrees by which the projectiles will be spread DURING MOVEMENT. It exists for chaotic types of projectiles, like bees or something. - var/legacy = 0 //Use the legacy projectile system or new pixel movement? +/obj/item/projectile/proc/on_range() //if we want there to be effects when they reach the end of their range + qdel(src) - proc/delete() - // Garbage collect the projectiles - loc = null - - proc/Range() - if(range) - range-- - if(range <= 0) - on_range() - else - return - - proc/on_range() //if we want there to be effects when they reach the end of their range - proj_hit = 1 - del(src) - - proc/on_hit(var/atom/target, var/blocked = 0, var/hit_zone) - if(!isliving(target)) return 0 - if(isanimal(target)) return 0 - var/mob/living/L = target - return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) - - proc/OnFired() //if assigned, allows for code when the projectile gets fired - return 1 - - proc/check_fire(var/mob/living/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not. - if(!istype(target) || !istype(user)) - return 0 - var/obj/item/projectile/test/in_chamber = new /obj/item/projectile/test(get_step_to(user,target)) //Making the test.... - in_chamber.target = target - in_chamber.flags = flags //Set the flags... - in_chamber.pass_flags = pass_flags //And the pass flags to that of the real projectile... - in_chamber.firer = user - var/output = in_chamber.process() //Test it! - del(in_chamber) //No need for it anymore - return output //Send it back to the gun! - - Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return 0 //cannot shoot yourself - - if(bumped) - return 1 - bumped = 1 - if(firer && istype(A, /mob)) - var/mob/M = A - if(!istype(A, /mob/living)) - loc = A.loc - return 0// nope.avi - - var/reagent_note - if(reagents && reagents.reagent_list) - reagent_note = " REAGENTS:" - for(var/datum/reagent/R in reagents.reagent_list) - reagent_note += R.id + " (" - reagent_note += num2text(R.volume) + ") " - //Lower accurancy/longer range tradeoff. Distance matters a lot here, so at - // close distance, actually RAISE the chance to hit. - var/distance = get_dist(get_turf(A), starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. - def_zone = ran_zone(def_zone, max(100-(7*distance), 5)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use. - /* - if(!def_zone) - visible_message("\blue \The [src] misses [M] narrowly!") - forcedodge = -1 - else - */ - if(ishuman(A)) - var/mob/living/carbon/human/H = A - var/obj/item/organ/external/organ = H.get_organ(check_zone(def_zone)) - if(isnull(organ)) - return - if(silenced) - playsound(loc, hitsound, 5, 1, -1) - to_chat(M, "\red You've been shot in the [parse_zone(def_zone)] by the [src.name]!") - else - playsound(loc, hitsound, 20, 1, -1) - visible_message("\red [A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter - if(istype(firer, /mob)) - M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [M]/[M.ckey] with a [src.type][reagent_note]" - firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [M]/[M.ckey] with a [src.type][reagent_note]" - if(M.ckey && chatlog_attacks) - msg_admin_attack("[key_name_admin(firer)] shot [key_name_admin(M)] with a [src][reagent_note]") //BS12 EDIT ALG - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer - else - M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [key_name(M)] with a [src][reagent_note]" - if(M.ckey && chatlog_attacks) - msg_admin_attack("UNKNOWN shot [key_name_admin(M)] with a [src][reagent_note] (JMP)") //BS12 EDIT ALG - - spawn(0) - if(A) - var/turf/new_loc = get_turf(A) - var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null - if(permutation == -1 || forcedodge)// the bullet passes through a dense object! - spawn(1) - bumped = 0 // reset bumped variable... after a delay. We don't want the projectile to hit AGAIN. Fixes deflecting projectiles. - loc = new_loc - permutated.Add(A) - return 0 - if(istype(A,/turf)) - for(var/obj/O in A) - O.bullet_act(src) - for(var/mob/M in A) - M.bullet_act(src, def_zone) - if(!istype(src, /obj/item/projectile/beam/lightning)) - density = 0 - invisibility = 101 - del(src) - return 1 - - - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover, /obj/item/projectile)) - return prob(95) - else - return 1 - - - Process_Spacemove(var/movement_dir = 0) - return 1 //Bullets don't drift in space - - - - process(var/setAngle) - if(setAngle) Angle = setAngle - if(!legacy) - spawn() //New projectile system - while(loc) - if(kill_count < 1) - del(src) - return - if(!paused) - kill_count-- - if((!( current ) || loc == current)) - current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) - - if(!Angle) - Angle=round(Get_Angle(src,current)) -// to_chat(world, "[Angle] angle") - //overlays.Cut() - //var/icon/I=new(initial(icon),icon_state) //using initial(icon) makes sure that the angle for that is reset as well - //I.Turn(Angle) - //I.DrawBox(rgb(255,0,0,50),1,1,32,32) - //icon = I - if(spread) //Chaotic spread - Angle += (rand() - 0.5) * spread - var/matrix/M = new//matrix(transform) - M.Turn(Angle) - transform = M - - var/Pixel_x=round(sin(Angle)+16*sin(Angle)*2) - var/Pixel_y=round(cos(Angle)+16*cos(Angle)*2) - var/pixel_x_offset = pixel_x + Pixel_x - var/pixel_y_offset = pixel_y + Pixel_y - var/new_x = x - var/new_y = y - //Not sure if using whiles for this is good - while(pixel_x_offset > 16) -// to_chat(world, "Pre-adjust coords (x++): xy [pixel_x] xy offset [pixel_x_offset]") - pixel_x_offset -= 32 - pixel_x -= 32 - new_x++// x++ - while(pixel_x_offset < -16) -// to_chat(world, "Pre-adjust coords (x--): xy [pixel_x] xy offset [pixel_x_offset]") - pixel_x_offset += 32 - pixel_x += 32 - new_x-- - - while(pixel_y_offset > 16) -// to_chat(world, "Pre-adjust coords (y++): py [pixel_y] py offset [pixel_y_offset]") - pixel_y_offset -= 32 - pixel_y -= 32 - new_y++ - while(pixel_y_offset < -16) -// to_chat(world, "Pre-adjust coords (y--): py [pixel_y] py offset [pixel_y_offset]") - pixel_y_offset += 32 - pixel_y += 32 - new_y-- - - speed = round(speed) //Just in case. - step_towards(src, locate(new_x, new_y, z)) //Original projectiles stepped towards 'current' - if(speed <= 1) //We should really only animate at speed 2 - pixel_x = pixel_x_offset - pixel_y = pixel_y_offset - else - animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (speed <= 3 ? speed - 1 : speed))) - - /* - var/turf/T = get_turf(src) - if(T) - T.color = "#6666FF" - spawn(10) - T.color = initial(T.color) - */ - - if(!bumped && ((original && original.layer>=2.75) || ismob(original))) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - Range() - sleep(max(1, speed)) - else - spawn() //Old projectile system - while(loc) - if(kill_count < 1) - del(src) - return - if(!paused) - kill_count-- - if((!( current ) || loc == current)) - current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) - if(!Angle) - Angle=round(Get_Angle(src,current)) - var/matrix/M = new//matrix(transform) - M.Turn(Angle) - transform = M //So there's no need to give icons directions again - step_towards(src, current) - if(!bumped && ((original && original.layer>=2.75) || ismob(original))) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - Range() - sleep(1) - - proc/dumbfire(var/dir) - current = get_ranged_target_turf(src, dir, world.maxx) //world.maxx is the range. Not sure how to handle this better. - process() - -/obj/item/projectile/test //Used to see if you can hit them. - invisibility = 101 //Nope! Can't see me! - yo = null - xo = null - var/target = null - var/result = 0 //To pass the message back to the gun. - - Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return //cannot shoot yourself - if(istype(A, /obj/item/projectile)) - return - if(istype(A, /mob/living) || istype(A, /obj/mecha) || istype(A, /obj/spacepod) || istype(A, /obj/vehicle)) - result = 2 //We hit someone, return 1! - return - result = 1 - return - - process() - var/turf/curloc = get_turf(src) - var/turf/targloc = get_turf(target) - if(!curloc || !targloc) - return 0 - yo = targloc.y - curloc.y - xo = targloc.x - curloc.x - target = targloc - while(src) //Loop on through! - if(result) - return (result - 1) - if((!( target ) || loc == target)) - target = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge - step_towards(src, target) - var/mob/living/M = locate() in get_turf(src) - if(istype(M)) //If there is someting living... - return 1 //Return 1 - else - M = locate() in get_step(src,target) - if(istype(M)) - return 1 - -/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not. - if(!istype(target) || !istype(firer)) +/obj/item/projectile/proc/on_hit(atom/target, blocked = 0, hit_zone) + if(!isliving(target)) return 0 - var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_turf(firer)) //Making the test.... - trace.target = target - if(!isnull(flags)) - trace.flags = flags //Set the flags... - trace.pass_flags = pass_flags //And the pass flags to that of the real projectile... - var/output = trace.process() //Test it! - qdel(trace) //No need for it anymore - return output //Send it back to the gun! + var/mob/living/L = target + if(blocked < 100) // not completely blocked + var/organ_hit_text = "" + if(L.has_limbs) + organ_hit_text = " in \the [parse_zone(def_zone)]" + if(suppressed) + playsound(loc, hitsound, 5, 1, -1) + to_chat(L, "You're shot by \a [src][organ_hit_text]!") + else + if(hitsound) + var/volume = vol_by_damage() + playsound(loc, hitsound, volume, 1, -1) + L.visible_message("[L] is hit by \a [src][organ_hit_text]!", \ + "[L] is hit by \a [src][organ_hit_text]!") //X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter + + var/reagent_note + if(reagents && reagents.reagent_list) + reagent_note = " REAGENTS:" + for(var/datum/reagent/R in reagents.reagent_list) + reagent_note += R.id + " (" + reagent_note += num2text(R.volume) + ") " + add_logs(L, firer, "shot", src, reagent_note) + return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) + +/obj/item/projectile/proc/vol_by_damage() + if(damage) + return Clamp((damage) * 0.67, 30, 100)// Multiply projectile damage by 0.67, then clamp the value between 30 and 100 + else + return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume + +/obj/item/projectile/Bump(atom/A, yes) + if(!yes) //prevents double bumps. + return + if(firer) + if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech + loc = A.loc + return 0 + + var/distance = get_dist(get_turf(A), starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. + def_zone = ran_zone(def_zone, max(100-(7*distance), 5)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use. + + if(isturf(A) && hitsound_wall) + var/volume = Clamp(vol_by_damage() + 20, 0, 100) + if(suppressed) + volume = 5 + playsound(loc, hitsound_wall, volume, 1, -1) + else if(ishuman(A)) + var/mob/living/carbon/human/H = A + var/obj/item/organ/external/organ = H.get_organ(check_zone(def_zone)) + if(isnull(organ)) + return + + var/turf/target_turf = get_turf(A) + + var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null + if(permutation == -1 || forcedodge)// the bullet passes through a dense object! + loc = target_turf + if(A) + permutated.Add(A) + return 0 + else + if(A && A.density && !ismob(A) && !(A.flags & ON_BORDER)) //if we hit a dense non-border obj or dense turf then we also hit one of the mobs on that tile. + var/list/mobs_list = list() + for(var/mob/living/L in target_turf) + mobs_list += L + if(mobs_list.len) + var/mob/living/picked_mob = pick(mobs_list) + picked_mob.bullet_act(src, def_zone) + qdel(src) + +/obj/item/projectile/Process_Spacemove(var/movement_dir = 0) + return 1 //Bullets don't drift in space + +/obj/item/projectile/proc/fire(var/setAngle) + if(setAngle) + Angle = setAngle + if(!legacy) //new projectiles + set waitfor = 0 + while(loc) + if(!paused) + if((!( current ) || loc == current)) + current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) + + if(!Angle) + Angle=round(Get_Angle(src,current)) + if(spread) + Angle += (rand() - 0.5) * spread + var/matrix/M = new + M.Turn(Angle) + transform = M + + var/Pixel_x=round(sin(Angle)+16*sin(Angle)*2) + var/Pixel_y=round(cos(Angle)+16*cos(Angle)*2) + var/pixel_x_offset = pixel_x + Pixel_x + var/pixel_y_offset = pixel_y + Pixel_y + var/new_x = x + var/new_y = y + + while(pixel_x_offset > 16) + pixel_x_offset -= 32 + pixel_x -= 32 + new_x++// x++ + while(pixel_x_offset < -16) + pixel_x_offset += 32 + pixel_x += 32 + new_x-- + + while(pixel_y_offset > 16) + pixel_y_offset -= 32 + pixel_y -= 32 + new_y++ + while(pixel_y_offset < -16) + pixel_y_offset += 32 + pixel_y += 32 + new_y-- + + speed = round(speed) + step_towards(src, locate(new_x, new_y, z)) + if(speed <= 1) + pixel_x = pixel_x_offset + pixel_y = pixel_y_offset + else + animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (speed <= 3 ? speed - 1 : speed))) + + if(original && (original.layer>=2.75) || ismob(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original, 1) + Range() + sleep(max(1, speed)) + else //old projectile system + set waitfor = 0 + while(loc) + if(!paused) + if((!( current ) || loc == current)) + current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) + step_towards(src, current) + if(original && (original.layer>=2.75) || ismob(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original, 1) + Range() + sleep(1) + +obj/item/projectile/Crossed(atom/movable/AM) //A mob moving on a tile with a projectile is hit by it. + ..() + if(isliving(AM) && AM.density && !checkpass(PASSMOB)) + Bump(AM, 1) + +/obj/item/projectile/Destroy() + ammo_casing = null + return ..() + +/obj/item/projectile/proc/dumbfire(var/dir) + current = get_ranged_target_turf(src, dir, world.maxx) //world.maxx is the range. Not sure how to handle this better. + fire() diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index e86d8e7a739..d9cf8360d2a 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -5,56 +5,34 @@ damage = 20 damage_type = BURN hitsound = 'sound/weapons/sear.ogg' + hitsound_wall = 'sound/weapons/effects/searwall.ogg' flag = "laser" eyeblur = 2 -/obj/item/projectile/practice - name = "laser" - icon_state = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE +/obj/item/projectile/beam/laser + +/obj/item/projectile/beam/laser/heavylaser + name = "heavy laser" + icon_state = "heavylaser" + damage = 40 + +/obj/item/projectile/beam/practice + name = "practice laser" damage = 0 - hitsound = null - damage_type = BURN - flag = "laser" - eyeblur = 2 - chatlog_attacks = 0 + nodamage = 1 /obj/item/projectile/beam/scatter name = "laser pellet" icon_state = "scatterlaser" damage = 5 - -/obj/item/projectile/beam/heavylaser - name = "heavy laser" - icon_state = "heavylaser" - damage = 40 - -/obj/item/projectile/beam/sniper - name = "sniper beam" - icon_state = "sniperlaser" - damage = 60 - stun = 5 - weaken = 5 - stutter = 5 - - -/obj/item/projectile/beam/immolator - name = "immolation beam" - -/obj/item/projectile/beam/immolator/on_hit(var/atom/target, var/blocked = 0) - . = ..() - if(istype(target, /mob/living/carbon)) - var/mob/living/carbon/M = target - M.adjust_fire_stacks(1) - M.IgniteMob() - /obj/item/projectile/beam/xray name = "xray beam" icon_state = "xray" damage = 15 irradiate = 30 forcedodge = 1 + range = 15 /obj/item/projectile/beam/disabler name = "disabler beam" @@ -82,204 +60,75 @@ name = "emitter beam" icon_state = "emitter" damage = 30 + legacy = 1 + animate_movement = SLIDE_STEPS /obj/item/projectile/beam/emitter/singularity_pull() return //don't want the emitters to miss -/obj/item/projectile/lasertag +/obj/item/projectile/beam/lasertag name = "laser tag beam" icon_state = "omnilaser" hitsound = null damage = 0 damage_type = STAMINA flag = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE var/suit_types = list(/obj/item/clothing/suit/redtag, /obj/item/clothing/suit/bluetag) - chatlog_attacks = 0 -/obj/item/projectile/lasertag/on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) +/obj/item/projectile/beam/lasertag/on_hit(atom/target, blocked = 0) + . = ..() + if(ishuman(target)) var/mob/living/carbon/human/M = target if(istype(M.wear_suit)) if(M.wear_suit.type in suit_types) M.adjustStaminaLoss(34) return 1 -/obj/item/projectile/lasertag/omni +/obj/item/projectile/beam/lasertag/omni name = "laser tag beam" icon_state = "omnilaser" -/obj/item/projectile/lasertag/red +/obj/item/projectile/beam/lasertag/redtag icon_state = "laser" suit_types = list(/obj/item/clothing/suit/bluetag) -/obj/item/projectile/lasertag/blue +/obj/item/projectile/beam/lasertag/bluetag icon_state = "bluelaser" suit_types = list(/obj/item/clothing/suit/redtag) -/obj/item/projectile/beam/lightning - invisibility = 101 - name = "lightning" - damage = 0 - icon = 'icons/obj/lightning.dmi' - icon_state = "lightning" - stun = 10 - weaken = 10 - stutter = 50 - eyeblur = 50 - var/tang = 0 - layer = 3 - var/turf/last = null - kill_count = 6 - var/bullet_acted = 0 +/obj/item/projectile/beam/sniper + name = "sniper beam" + icon_state = "sniperlaser" + damage = 60 + stun = 5 + weaken = 5 + stutter = 5 - Bump(var/atom/A) - if((A != firer) && !bullet_acted) - A.bullet_act(src) - bullet_acted = 1 +/obj/item/projectile/beam/immolator + name = "immolation beam" - proc/adjustAngle(angle) - angle = round(angle) + 45 - if(angle > 180) - angle -= 180 - else - angle += 180 - if(!angle) - angle = 1 - /*if(angle < 0) - //angle = (round(abs(get_angle(A, user))) + 45) - 90 - angle = round(angle) + 45 + 180 - else - angle = round(angle) + 45*/ - return angle +/obj/item/projectile/beam/immolator/on_hit(var/atom/target, var/blocked = 0) + . = ..() + if(istype(target, /mob/living/carbon)) + var/mob/living/carbon/M = target + M.adjust_fire_stacks(1) + M.IgniteMob() - process() - var/first = 1 //So we don't make the overlay in the same tile as the firer - var/broke = 0 - var/broken - var/atom/curr = current - var/Angle=round(Get_Angle(firer,curr)) - var/icon/I=new('icons/obj/zap.dmi',"lightning") - I.Turn(Angle) - var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) - var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) - var/N=0 - var/length=round(sqrt((DX)**2+(DY)**2)) - var/count = 0 - for(N,N= kill_count) - break - count++ - var/obj/effect/overlay/beam/X=new(loc) - X.BeamSource=src - if(N+32>length) - var/icon/II=new(icon,icon_state) - II.DrawBox(null,1,(length-N),32,32) - II.Turn(Angle) - X.icon=II - else X.icon=I - var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) - var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) - if(DX==0) Pixel_x=0 - if(DY==0) Pixel_y=0 - if(Pixel_x>32) - for(var/a=0, a<=Pixel_x,a+=32) - X.x++ - Pixel_x-=32 - if(Pixel_x<-32) - for(var/a=0, a>=Pixel_x,a-=32) - X.x-- - Pixel_x+=32 - if(Pixel_y>32) - for(var/a=0, a<=Pixel_y,a+=32) - X.y++ - Pixel_y-=32 - if(Pixel_y<-32) - for(var/a=0, a>=Pixel_y,a-=32) - X.y-- - Pixel_y+=32 - X.pixel_x=Pixel_x - X.pixel_y=Pixel_y - var/turf/TT = get_turf(X.loc) - if(TT == firer.loc) - continue - if(TT.density) - qdel(X) - break - for(var/atom/O in TT) - if(istype(O,/mob/living)) - if(O.density) - qdel(X) - broke = 1 - break - if(!O.CanPass(src)) - qdel(X) - broke = 1 - break - if(broke) - if(X) - qdel(X) - break - spawn - while(src) //Move until we hit something - if(first) - icon = midicon - if((!( current ) || loc == current)) //If we pass our target - broken = 1 - icon = endicon - tang = adjustAngle(get_angle(original,current)) - if(tang > 180) - tang -= 180 - else - tang += 180 - icon_state = "[tang]" - var/turf/simulated/floor/f = current - if(f && istype(f)) - if(!bullet_acted) - f.break_tile() - f.hotspot_expose(1000,CELL_VOLUME) - if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) -// to_chat(world, "deleting") - //qdel(src) //Delete if it passes the world edge - broken = 1 - return - if(kill_count < 1) -// to_chat(world, "deleting") - //qdel(src) - broken = 1 - kill_count-- -// to_chat(world, "[x] [y]") - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - icon = endicon - if(!broken) - tang = adjustAngle(get_angle(original,current)) - if(tang > 180) - tang -= 180 - else - tang += 180 - icon_state = "[tang]" - Bump(original) - first = 0 - if(broken) -// to_chat(world, "breaking") - break - else - last = get_turf(src.loc) - step_towards(src, current) //Move~ - if(src.loc != current) - tang = adjustAngle(get_angle(src.loc,current)) - icon_state = "[tang]" - qdel(src) - return - /*cleanup(reference) //Waits .3 seconds then removes the overlay. -// to_chat(world, "setting invisibility") - sleep(50) - src.invisibility = 101 - return*/ - on_hit(atom/target, blocked = 0) - if(istype(target, /mob/living)) - var/mob/living/M = target - M.playsound_local(src, "explosion", 50, 1) - ..() \ No newline at end of file +/obj/item/projectile/beam/instakill + name = "instagib laser" + icon_state = "purple_laser" + damage = 200 + damage_type = BURN + +/obj/item/projectile/beam/instakill/blue + icon_state = "blue_laser" + +/obj/item/projectile/beam/instakill/red + icon_state = "red_laser" + +/obj/item/projectile/beam/instakill/on_hit(atom/target) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/M = target + M.visible_message("[M] explodes into a shower of gibs!") + M.gib() diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 879bbf7fad0..8f8809c504f 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -3,21 +3,10 @@ icon_state = "bullet" damage = 60 damage_type = BRUTE - nodamage = 0 flag = "bullet" embed = 1 sharp = 1 - -/obj/item/projectile/bullet/cap - name = "cap" - damage = 0 - nodamage = 1 - embed = 0 - sharp = 0 - -/obj/item/projectile/bullet/cap/process() - loc = null - del(src) + hitsound_wall = "ricochet" /obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage damage = 5 @@ -27,6 +16,26 @@ embed = 0 sharp = 0 +/obj/item/projectile/bullet/weakbullet/booze + embed = 0 + +/obj/item/projectile/bullet/weakbullet/booze/on_hit(atom/target, blocked = 0) + if(..(target, blocked)) + var/mob/living/M = target + M.dizziness += 20 + M.slurring += 20 + M.confused += 20 + M.eye_blurry += 20 + M.drowsyness += 20 + for(var/datum/reagent/ethanol/A in M.reagents.reagent_list) + M.AdjustParalysis(2) + M.dizziness += 10 + M.slurring += 10 + M.confused += 10 + M.eye_blurry += 10 + M.drowsyness += 10 + A.volume += 5 //Because we can + /obj/item/projectile/bullet/weakbullet2 //detective revolver instastuns, but multiple shots are better for keeping punks down damage = 5 weaken = 3 @@ -44,6 +53,15 @@ damage = 15 damage_type = TOX +/obj/item/projectile/bullet/incendiary + +/obj/item/projectile/bullet/incendiary/on_hit(var/atom/target, var/blocked = 0) + ..() + if(istype(target, /mob/living/carbon)) + var/mob/living/carbon/M = target + M.adjust_fire_stacks(1) + M.IgniteMob() + /obj/item/projectile/bullet/incendiary/firebullet damage = 10 @@ -55,15 +73,34 @@ name = "pellet" damage = 15 -/obj/item/projectile/bullet/blank - name = "blankshot" - nodamage = 1 - /obj/item/projectile/bullet/pellet/weak + damage = 6 + +/obj/item/projectile/bullet/pellet/weak/New() + range = rand(8) + +/obj/item/projectile/bullet/pellet/weak/on_range() + var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread + sparks.set_up(1, 1, src) + sparks.start() + ..() + +/obj/item/projectile/bullet/pellet/overload damage = 3 -/obj/item/projectile/bullet/pellet/random/New() - damage = rand(10) +/obj/item/projectile/bullet/pellet/overload/New() + range = rand(10) + +/obj/item/projectile/bullet/pellet/overload/on_hit(atom/target, blocked = 0) + ..() + explosion(target, 0, 0, 2) + +/obj/item/projectile/bullet/pellet/overload/on_range() + explosion(src, 0, 0, 2) + var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread + sparks.set_up(3, 3, src) + sparks.start() + ..() /obj/item/projectile/bullet/midbullet damage = 20 @@ -89,39 +126,11 @@ weaken = 5 stutter = 5 jitter = 20 - icon_state = "spark" range = 7 embed = 0 sharp = 0 - - -/obj/item/projectile/bullet/weakbullet/booze - embed = 0 - on_hit(var/atom/target, var/blocked = 0) - if(..(target, blocked)) - var/mob/living/M = target - M.dizziness += 20 - M.slurring += 20 - M.confused += 20 - M.eye_blurry += 20 - M.drowsyness += 20 - for(var/datum/reagent/ethanol/A in M.reagents.reagent_list) - M.AdjustParalysis(2) - M.dizziness += 10 - M.slurring += 10 - M.confused += 10 - M.eye_blurry += 10 - M.drowsyness += 10 - A.volume += 5 //Because we can - -/obj/item/projectile/bullet/incendiary - -/obj/item/projectile/bullet/incendiary/on_hit(var/atom/target, var/blocked = 0) - ..() - if(istype(target, /mob/living/carbon)) - var/mob/living/carbon/M = target - M.adjust_fire_stacks(1) - M.IgniteMob() + icon_state = "spark" + color = "#FFFF00" /obj/item/projectile/bullet/incendiary/shell name = "incendiary slug" @@ -130,8 +139,9 @@ /obj/item/projectile/bullet/incendiary/shell/Move() ..() var/turf/location = get_turf(src) - new /obj/effect/hotspot(location) - location.hotspot_expose(700, 50, 1) + if(location) + new /obj/effect/hotspot(location) + location.hotspot_expose(700, 50, 1) /obj/item/projectile/bullet/incendiary/shell/dragonsbreath name = "dragonsbreath round" @@ -157,7 +167,26 @@ ..() SpinAnimation() +/obj/item/projectile/bullet/meteorshot/weak + damage = 10 + weaken = 4 + stun = 4 +/obj/item/projectile/bullet/honker + damage = 0 + weaken = 5 + stun = 5 + forcedodge = 1 + nodamage = 1 + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + hitsound = 'sound/items/bikehorn.ogg' + icon = 'icons/obj/harvest.dmi' + icon_state = "banana" + range = 200 + +/obj/item/projectile/bullet/honker/New() + ..() + SpinAnimation() /obj/item/projectile/bullet/mime damage = 0 @@ -168,7 +197,7 @@ /obj/item/projectile/bullet/mime/on_hit(var/atom/target, var/blocked = 0) ..(target, blocked) - if(istype(target, /mob/living/carbon)) + if(iscarbon(target)) var/mob/living/carbon/M = target M.silent = max(M.silent, 10) else if(istype(target, /obj/mecha/combat/honker)) @@ -184,32 +213,38 @@ damage = 6 embed = 0 sharp = 0 + var/piercing = 0 - New() - ..() - flags |= NOREACT - create_reagents(50) +/obj/item/projectile/bullet/dart/New() + ..() + flags |= NOREACT + create_reagents(50) - on_hit(var/atom/target, var/blocked = 0, var/hit_zone) - if(istype(target, /mob/living/carbon)) - var/mob/living/carbon/M = target +/obj/item/projectile/bullet/dart/on_hit(var/atom/target, var/blocked = 0, var/hit_zone) + if(iscarbon(target)) + var/mob/living/carbon/M = target + if(blocked != 100) if(M.can_inject(null,0,hit_zone)) // Pass the hit zone to see if it can inject by whether it hit the head or the body. + ..() reagents.reaction(M, INGEST) reagents.trans_to(M, reagents.total_volume) return 1 else + blocked = 100 target.visible_message("The [name] was deflected!", \ - "You were protected against the [name]!") - flags &= ~NOREACT - reagents.handle_reactions() - return 1 + "You were protected against the [name]!") + ..(target, blocked, hit_zone) + flags &= ~NOREACT + reagents.handle_reactions() + return 1 /obj/item/projectile/bullet/dart/metalfoam - New() - ..() - reagents.add_reagent("aluminum", 15) - reagents.add_reagent("fluorosurfactant", 5) - reagents.add_reagent("sacid", 5) + +/obj/item/projectile/bullet/dart/metalfoam/New() + ..() + reagents.add_reagent("aluminum", 15) + reagents.add_reagent("fluorosurfactant", 5) + reagents.add_reagent("sacid", 5) //This one is for future syringe guns update /obj/item/projectile/bullet/dart/syringe @@ -218,9 +253,9 @@ icon_state = "syringeproj" /obj/item/projectile/bullet/dart/syringe/tranquilizer - New() - ..() - reagents.add_reagent("haloperidol", 15) +/obj/item/projectile/bullet/dart/syringe/tranquilizer/New() + ..() + reagents.add_reagent("haloperidol", 15) /obj/item/projectile/bullet/neurotoxin name = "neurotoxin spit" @@ -231,5 +266,17 @@ /obj/item/projectile/bullet/neurotoxin/on_hit(var/atom/target, var/blocked = 0) if(isalien(target)) - return 0 - ..() // Execute the rest of the code. + weaken = 0 + nodamage = 1 + . = ..() // Execute the rest of the code. + +/obj/item/projectile/bullet/cap + name = "cap" + damage = 0 + nodamage = 1 + embed = 0 + sharp = 0 + +/obj/item/projectile/bullet/cap/fire() + loc = null + qdel(src) diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index b5665a6af1c..79ffc1d0898 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -5,7 +5,6 @@ damage_type = BURN flag = "energy" - /obj/item/projectile/energy/electrode name = "electrode" icon_state = "spark" @@ -20,26 +19,23 @@ //Damage will be handled on the MOB side, to prevent window shattering. /obj/item/projectile/energy/electrode/on_hit(var/atom/target, var/blocked = 0) - if(!proj_hit) - if(!ismob(target) || blocked >= 2) //Fully blocked by mob or collided with dense object - burst into sparks! - var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread - sparks.set_up(1, 1, src) - sparks.start() - proj_hit = 1 - else if(iscarbon(target)) - var/mob/living/carbon/C = target - if(HULK in C.mutations) - C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - else if(C.status_flags & CANWEAKEN) - C.do_jitter_animation(jitter) - ..() - -/obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet - if(!proj_hit) + . = ..() + if(!ismob(target) || blocked >= 100) //Fully blocked by mob or collided with dense object - burst into sparks! var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread sparks.set_up(1, 1, src) sparks.start() - proj_hit = 1 + else if(iscarbon(target)) + var/mob/living/carbon/C = target + if(HULK in C.mutations) + C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + else if(C.status_flags & CANWEAKEN) + spawn(5) + C.do_jitter_animation(jitter) + +/obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet + var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread + sparks.set_up(1, 1, src) + sparks.start() ..() /obj/item/projectile/energy/declone @@ -49,7 +45,6 @@ damage_type = CLONE irradiate = 10 - /obj/item/projectile/energy/dart name = "dart" icon_state = "toxin" @@ -63,7 +58,6 @@ icon_state = "toxin" damage = 10 damage_type = TOX - nodamage = 0 weaken = 5 stutter = 5 @@ -77,12 +71,28 @@ stutter = 5 /obj/item/projectile/energy/bolt/large - name = "largebolt" damage = 20 -/obj/item/projectile/energy/plasma +/obj/item/projectile/energy/shock_revolver + name = "shock bolt" + icon_state = "purple_laser" + var/chain + +/obj/item/ammo_casing/energy/shock_revolver/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") + ..() + var/obj/item/projectile/energy/shock_revolver/P = BB + spawn(1) + P.chain = P.Beam(user,icon_state="purple_lightning",icon = 'icons/effects/effects.dmi',time=1000, maxdistance = 30) + +/obj/item/projectile/energy/shock_revolver/on_hit(atom/target) + . = ..() + if(isliving(target)) + tesla_zap(src, 3, 10000) + qdel(chain) + +/obj/item/projectile/energy/toxplasma name = "plasma bolt" icon_state = "energy" damage = 20 damage_type = TOX - irradiate = 20 \ No newline at end of file + irradiate = 20 diff --git a/code/modules/projectiles/projectile/force.dm b/code/modules/projectiles/projectile/force.dm index 2fab1a4da18..4e5c6d27700 100644 --- a/code/modules/projectiles/projectile/force.dm +++ b/code/modules/projectiles/projectile/force.dm @@ -10,21 +10,8 @@ name = "force bolt" /obj/item/projectile/forcebolt/on_hit(var/atom/target, var/blocked = 0) - - var/obj/T = target - var/throwdir = get_dir(firer,target) - T.throw_at(get_edge_target_turf(target, throwdir),10,10) - return 1 - -/* -/obj/item/projectile/forcebolt/strong/on_hit(var/atom/target, var/blocked = 0) - - // NONE OF THIS WORKS. DO NOT USE. - var/throwdir = null - - for(var/mob/M in hearers(2, src)) - if(M.loc != src.loc) - throwdir = get_dir(src,target) - M.throw_at(get_edge_target_turf(M, throwdir),15,1) - return ..() -*/ \ No newline at end of file + . = ..() + if(blocked < 100) + var/obj/T = target + var/throwdir = get_dir(firer,target) + T.throw_at(get_edge_target_turf(target, throwdir),10,10) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index ecbbfb530f8..d91fd3898f7 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -4,15 +4,15 @@ damage = 0 damage_type = OXY nodamage = 1 + armour_penetration = 100 flag = "magic" /obj/item/projectile/magic/death name = "bolt of death" icon_state = "pulse1_bl" - damage = 9001 - damage_type = OXY + damage_type = BURN //OXY does not kill IPCs + damage = 50000 nodamage = 0 - flag = "magic" /obj/item/projectile/magic/fireball name = "bolt of fireball" @@ -20,9 +20,22 @@ damage = 10 damage_type = BRUTE nodamage = 0 - flag = "magic" + +/obj/item/projectile/magic/fireball/Range() + var/turf/T1 = get_step(src,turn(dir, -45)) + var/turf/T2 = get_step(src,turn(dir, 45)) + var/mob/living/L = locate(/mob/living) in T1 //if there's a mob alive in our front right diagonal, we hit it. + if(L && L.stat != DEAD) + Bump(L) //Magic Bullet #teachthecontroversy + return + L = locate(/mob/living) in T2 + if(L && L.stat != DEAD) + Bump(L) + return + ..() /obj/item/projectile/magic/fireball/on_hit(var/target) + . = ..() var/turf/T = get_turf(target) explosion(T, -1, 0, 2, 3, 0, flame_range = 2) if(ismob(target)) //multiple flavors of pain @@ -32,35 +45,13 @@ /obj/item/projectile/magic/resurrection name = "bolt of resurrection" icon_state = "ion" - damage = 0 - damage_type = OXY - nodamage = 1 - flag = "magic" /obj/item/projectile/magic/resurrection/on_hit(var/mob/living/carbon/target) - - if(istype(target,/mob)) + . = ..() + if(ismob(target)) var/old_stat = target.stat - if(isanimal(target) && target.stat == DEAD) - var/mob/living/simple_animal/O = target - var/mob/living/simple_animal/A = new O.type(O.loc) - A.real_name = O.real_name - A.name = O.name - if(iscorgi(O)) - var/mob/living/simple_animal/pet/corgi/C = O - if(C.inventory_head) - C.inventory_head.loc = C.loc - if(C.inventory_back) - C.inventory_back.loc = C.loc - if(O.mind) - O.mind.transfer_to(A) - else - A.key = O.key - qdel(O) - target = A - else - target.revive() - target.suiciding = 0 + target.suiciding = 0 + target.revive() if(!target.ckey) for(var/mob/dead/observer/ghost in player_list) if(target.real_name == ghost.real_name) @@ -74,14 +65,11 @@ /obj/item/projectile/magic/teleport name = "bolt of teleportation" icon_state = "bluespace" - damage = 0 - damage_type = OXY - nodamage = 1 - flag = "magic" var/inner_tele_radius = 0 var/outer_tele_radius = 6 /obj/item/projectile/magic/teleport/on_hit(var/mob/target) + . = ..() var/teleammount = 0 var/teleloc = target if(!isturf(target)) @@ -97,37 +85,46 @@ /obj/item/projectile/magic/door name = "bolt of door creation" icon_state = "energy" - damage = 0 - damage_type = OXY - nodamage = 1 - flag = "magic" + var/list/door_types = list(/obj/structure/mineral_door/wood,/obj/structure/mineral_door/iron,/obj/structure/mineral_door/silver,\ + /obj/structure/mineral_door/gold,/obj/structure/mineral_door/uranium,/obj/structure/mineral_door/sandstone,/obj/structure/mineral_door/transparent/plasma,\ + /obj/structure/mineral_door/transparent/diamond) /obj/item/projectile/magic/door/on_hit(var/atom/target) + . = ..() var/atom/T = target.loc - if(isturf(target)) - if(target.density) - new /obj/structure/mineral_door/wood(target) - target:ChangeTurf(/turf/simulated/floor/plating) - else if (isturf(T)) - if(T.density) - new /obj/structure/mineral_door/wood(T) - T:ChangeTurf(/turf/simulated/floor/plating) + if(isturf(target) && target.density) + CreateDoor(target) + else if (isturf(T) && T.density) + CreateDoor(T) + else if(istype(target, /obj/machinery/door)) + OpenDoor(target) + +/obj/item/projectile/magic/door/proc/CreateDoor(turf/T) + var/door_type = pick(door_types) + var/obj/structure/mineral_door/D = new door_type(T) + T.ChangeTurf(/turf/simulated/floor/plasteel) + D.Open() + +/obj/item/projectile/magic/door/proc/OpenDoor(var/obj/machinery/door/D) + if(istype(D,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/A = D + A.locked = 0 + D.open() /obj/item/projectile/magic/change name = "bolt of change" icon_state = "ice_1" - damage = 0 damage_type = BURN - nodamage = 1 - flag = "magic" /obj/item/projectile/magic/change/on_hit(var/atom/change) + . = ..() wabbajack(change) proc/wabbajack(mob/living/M) if(istype(M)) if(istype(M, /mob/living) && M.stat != DEAD) - if(M.notransform) return + if(M.notransform) + return M.notransform = 1 M.canmove = 0 M.icon = null @@ -136,7 +133,9 @@ proc/wabbajack(mob/living/M) if(istype(M, /mob/living/silicon/robot)) var/mob/living/silicon/robot/Robot = M - if(Robot.mmi) qdel(Robot.mmi) + if(Robot.mmi) + qdel(Robot.mmi) + Robot.notify_ai(1) else if(ishuman(M)) var/mob/living/carbon/human/H = M @@ -146,7 +145,8 @@ proc/wabbajack(mob/living/M) for(var/i in H.internal_organs) qdel(i) for(var/obj/item/W in M) - M.unEquip(W) + M.unEquip(W, 1) + qdel(W) var/mob/living/new_mob @@ -166,8 +166,6 @@ proc/wabbajack(mob/living/M) Robot.mmi.transfer_identity(M) //Does not transfer key/client. if("slime") new_mob = new /mob/living/carbon/slime(M.loc) -/* if(prob(50)) - new_mob.is_adult = 1*/ new_mob.universal_speak = 1 if("xeno") if(prob(50)) @@ -175,14 +173,6 @@ proc/wabbajack(mob/living/M) else new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) new_mob.universal_speak = 1 - - /*var/alien_caste = pick("Hunter","Sentinel","Drone","Larva") - switch(alien_caste) - if("Hunter") new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) - if("Sentinel") new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - if("Drone") new_mob = new /mob/living/carbon/alien/humanoid/drone(M.loc) - else new_mob = new /mob/living/carbon/alien/larva(M.loc) - new_mob.universal_speak = 1*/ if("animal") if(prob(50)) var/beast = pick("carp","bear","mushroom","statue", "bat", "goat", "tomato") @@ -225,7 +215,6 @@ proc/wabbajack(mob/living/M) randomize = picked_species var/datum/preferences/A = new() //Randomize appearance for the human A.copy_to(new_mob) - else return @@ -246,13 +235,10 @@ proc/wabbajack(mob/living/M) /obj/item/projectile/magic/animate name = "bolt of animation" icon_state = "red_1" - damage = 0 damage_type = BURN - nodamage = 1 - flag = "magic" /obj/item/projectile/magic/animate/Bump(var/atom/change) - . = ..() + ..() if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, protected_objects)) if(istype(change, /obj/structure/closet/statue)) for(var/mob/living/carbon/human/H in change.contents) @@ -269,8 +255,11 @@ 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 - C.ChangeOwner(firer) \ No newline at end of file + C.ChangeOwner(firer) diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm index 81defd55743..12e7b30c759 100644 --- a/code/modules/projectiles/projectile/reusable.dm +++ b/code/modules/projectiles/projectile/reusable.dm @@ -1,42 +1,63 @@ /obj/item/projectile/bullet/reusable name = "reusable bullet" desc = "How do you even reuse a bullet?" - var/obj/item/ammo_casing/caseless/ammo_type = /obj/item/ammo_casing/caseless/ - var/hit = 0 + var/ammo_type = /obj/item/ammo_casing/caseless/ + var/dropped = 0 -/obj/item/projectile/bullet/reusable/on_hit(var/atom/target, var/blocked = 0) - if(!proj_hit) - proj_hit = 1 - if (src.contents.len) - var/obj/content - for(content in src.contents) - content.loc = src.loc - else - new ammo_type(src.loc) - ..() +/obj/item/projectile/bullet/reusable/on_hit(atom/target, blocked = 0) + . = ..() + handle_drop() /obj/item/projectile/bullet/reusable/on_range() - if(!proj_hit) - if (src.contents.len) - var/obj/content - for(content in src.contents) - content.loc = src.loc - else - new ammo_type(src.loc) + handle_drop() ..() +/obj/item/projectile/bullet/reusable/proc/handle_drop() + if(!dropped) + new ammo_type(loc) + dropped = 1 + +/obj/item/projectile/bullet/reusable/magspear + name = "magnetic spear" + desc = "WHITE WHALE, HOLY GRAIL" + damage = 30 //takes 3 spears to kill a mega carp, one to kill a normal carp + icon_state = "magspear" + ammo_type = /obj/item/ammo_casing/caseless/magspear + /obj/item/projectile/bullet/reusable/foam_dart name = "foam dart" desc = "I hope you're wearing eye protection." damage = 0 // It's a damn toy. damage_type = OXY nodamage = 1 - edge = 0 - embed = 0 - icon = 'icons/obj/toyguns.dmi' + icon = 'icons/obj/guns/toy.dmi' icon_state = "foamdart" ammo_type = /obj/item/ammo_casing/caseless/foam_dart - range = 10 + range = 10 + var/obj/item/weapon/pen/pen = null + edge = 0 + embed = 0 + +/obj/item/projectile/bullet/reusable/foam_dart/handle_drop() + if(dropped) + return + dropped = 1 + var/obj/item/ammo_casing/caseless/foam_dart/newdart = new ammo_type(loc) + var/obj/item/ammo_casing/caseless/foam_dart/old_dart = ammo_casing + newdart.modified = old_dart.modified + if(pen) + var/obj/item/projectile/bullet/reusable/foam_dart/newdart_FD = newdart.BB + newdart_FD.pen = pen + pen.loc = newdart_FD + pen = null + newdart.BB.damage = damage + newdart.BB.nodamage = nodamage + newdart.BB.damage_type = damage_type + newdart.update_icon() + +/obj/item/projectile/bullet/reusable/foam_dart/Destroy() + pen = null + return ..() /obj/item/projectile/bullet/reusable/foam_dart/riot name = "riot foam dart" diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index ed64d73df4e..53527ef326e 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -6,15 +6,15 @@ nodamage = 1 flag = "energy" - - on_hit(var/atom/target, var/blocked = 0) - empulse(target, 1, 1) - return 1 - +/obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0) + ..() + empulse(target, 1, 1) + return 1 /obj/item/projectile/ion/weak /obj/item/projectile/ion/weak/on_hit(atom/target, blocked = 0) + ..() empulse(target, 0, 0) return 1 @@ -26,9 +26,10 @@ sharp = 1 edge = 1 - on_hit(var/atom/target, var/blocked = 0) - explosion(target, -1, 0, 2) - return 1 +/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) + ..() + explosion(target, -1, 0, 2) + return 1 /obj/item/projectile/bullet/a40mm name ="40mm grenade" @@ -43,90 +44,84 @@ return 1 /obj/item/projectile/temp - name = "freeze beam" + name = "temperature beam" icon_state = "temp_4" damage = 0 damage_type = BURN nodamage = 1 flag = "energy" var/temperature = 300 - var/obj/item/weapon/gun/energy/temperature/T = null + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - OnFired() - T = shot_from - temperature = T.temperature - 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" + ..() - on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob - if(istype(target, /mob/living)) - var/mob/living/M = target - M.bodytemperature = temperature - if(temperature > 500)//emagged - M.adjust_fire_stacks(0.5) - M.IgniteMob() - playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0) - return 1 +/obj/item/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob + ..() + if(isliving(target)) + var/mob/living/M = target + M.bodytemperature = temperature + if(temperature > 500)//emagged + M.adjust_fire_stacks(0.5) + M.IgniteMob() + playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0) + return 1 /obj/item/projectile/meteor name = "meteor" icon = 'icons/obj/meteor.dmi' - icon_state = "smallf" + icon_state = "small" damage = 0 damage_type = BRUTE nodamage = 1 flag = "bullet" - Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return - - sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits - - if(src)//Do not add to this if() statement, otherwise the meteor won't delete them - if(A) - - A.ex_act(2) - playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) - - for(var/mob/M in range(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) - return 1 - else - return 0 +/obj/item/projectile/meteor/Bump(atom/A, yes) + if(yes) + return + if(A == firer) + loc = A.loc + return + playsound(loc, 'sound/effects/meteorimpact.ogg', 40, 1) + for(var/mob/M in urange(10, src)) + if(!M.stat) + shake_camera(M, 3, 1) + qdel(src) /obj/item/projectile/energy/floramut name = "alpha somatoray" @@ -136,36 +131,31 @@ nodamage = 1 flag = "energy" - on_hit(var/atom/target, var/blocked = 0) - var/mob/living/M = target - if(ishuman(target)) - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - if(prob(15)) - M.apply_effect((rand(30,80)),IRRADIATE) - M.Weaken(5) - for (var/mob/V in viewers(src)) - V.show_message("\red [M] writhes in pain as \his vacuoles boil.", 3, "\red You hear the crunching of leaves.", 2) - if(prob(35)) - // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan - // V.show_message("\red [M] is mutated by the radiation beam.", 3, "\red You hear the snapping of twigs.", 2) - if(prob(80)) - randmutb(M) - domutcheck(M,null) - else - randmutg(M) - domutcheck(M,null) +/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) + ..() + var/mob/living/M = target + if(ishuman(target)) + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + if(prob(15)) + M.apply_effect((rand(30,80)),IRRADIATE) + M.Weaken(5) + for (var/mob/V in viewers(src)) + V.show_message("[M] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) + if(prob(35)) + if(prob(80)) + randmutb(M) + domutcheck(M,null) else - M.adjustFireLoss(rand(5,15)) - M.show_message("\red The radiation beam singes you!") - // for (var/mob/V in viewers(src)) - // V.show_message("\red [M] is singed by the radiation beam.", 3, "\red You hear the crackle of burning leaves.", 2) - else if(istype(target, /mob/living/carbon/)) - // for (var/mob/V in viewers(src)) - // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) - M.show_message("\blue The radiation beam dissipates harmlessly through your body.") - else - return 1 + randmutg(M) + domutcheck(M,null) + else + M.adjustFireLoss(rand(5,15)) + M.show_message("The radiation beam singes you!") + else if(istype(target, /mob/living/carbon/)) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/energy/florayield name = "beta somatoray" @@ -175,40 +165,42 @@ nodamage = 1 flag = "energy" - on_hit(var/atom/target, var/blocked = 0) - var/mob/M = target - if(ishuman(target)) //These rays make plantmen fat. - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - M.nutrition += 30 - else if (istype(target, /mob/living/carbon/)) - M.show_message("\blue The radiation beam dissipates harmlessly through your body.") - else - return 1 +/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) + ..() + var/mob/M = target + if(ishuman(target)) //These rays make plantmen fat. + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + M.nutrition += 30 + else if (istype(target, /mob/living/carbon/)) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/beam/mindflayer name = "flayer ray" - on_hit(var/atom/target, var/blocked = 0) - if(ishuman(target)) - var/mob/living/carbon/human/M = target - M.adjustBrainLoss(20) - M.hallucination += 20 +/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) + . = ..() + if(ishuman(target)) + var/mob/living/carbon/human/M = target + M.adjustBrainLoss(20) + M.hallucination += 20 /obj/item/projectile/clown name = "snap-pop" icon = 'icons/obj/toy.dmi' icon_state = "snappop" - Bump(atom/A as mob|obj|turf|area) - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) +/obj/item/projectile/clown/Bump(atom/A as mob|obj|turf|area) + var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + new /obj/effect/decal/cleanable/ash(loc) + visible_message("The [name] explodes!","You hear a snap!") + playsound(src, 'sound/effects/snap.ogg', 50, 1) + qdel(src) /obj/item/projectile/kinetic name = "kinetic force" @@ -239,11 +231,9 @@ obj/item/projectile/kinetic/New() damage *= 4 ..() -/obj/item/projectile/kinetic/Range() - range-- - if(range <= 0) - new /obj/item/effect/kinetic_blast(src.loc) - qdel(src) +/obj/item/projectile/kinetic/on_range() + new /obj/effect/kinetic_blast(loc) + ..() /obj/item/projectile/kinetic/on_hit(atom/target) . = ..() @@ -251,23 +241,57 @@ obj/item/projectile/kinetic/New() if(istype(target_turf, /turf/simulated/mineral)) var/turf/simulated/mineral/M = target_turf M.gets_drilled(firer) - new /obj/item/effect/kinetic_blast(target_turf) - if(src.splash) + new /obj/effect/kinetic_blast(target_turf) + if(splash) for(var/turf/T in range(splash, target_turf)) if(istype(T, /turf/simulated/mineral)) var/turf/simulated/mineral/M = T M.gets_drilled(firer) -/obj/item/effect/kinetic_blast +/obj/effect/kinetic_blast name = "kinetic explosion" icon = 'icons/obj/projectiles.dmi' icon_state = "kinetic_blast" layer = 4.1 -/obj/item/effect/kinetic_blast/New() +/obj/effect/kinetic_blast/New() spawn(4) qdel(src) +/obj/item/projectile/beam/wormhole + name = "bluespace beam" + icon_state = "spark" + hitsound = "sparks" + damage = 3 + var/obj/item/weapon/gun/energy/wormhole_projector/gun + color = "#33CCFF" + +/obj/item/projectile/beam/wormhole/orange + name = "orange bluespace beam" + color = "#FF6600" + +/obj/item/projectile/beam/wormhole/New(var/obj/item/ammo_casing/energy/wormhole/casing) + if(casing) + gun = casing.gun + +/obj/item/projectile/beam/wormhole/on_hit(atom/target) + if(ismob(target)) + var/turf/portal_destination = pick(orange(6, src)) + do_teleport(target, portal_destination) + return ..() + if(!gun) + qdel(src) + gun.create_portal(src) + +/obj/item/projectile/beam/wormhole/on_hit(atom/target) + if(ismob(target)) + var/turf/portal_destination = pick(orange(6, src)) + do_teleport(target, portal_destination) + return ..() + if(!gun) + qdel(src) + gun.create_portal(src) + /obj/item/projectile/bullet/frag12 name ="explosive slug" damage = 25 @@ -278,25 +302,6 @@ obj/item/projectile/kinetic/New() explosion(target, -1, 0, 1) return 1 -/obj/item/projectile/energy/teleport - name = "teleportation burst" - icon_state = "bluespace" - damage = 0 - nodamage = 1 - var/obj/item/weapon/gun/energy/telegun/T = null - var/teleport_target = null - - OnFired() - T = shot_from - teleport_target = T.teleport_target - -/obj/item/projectile/energy/teleport/on_hit(var/atom/target, var/blocked = 0) - if(isliving(target)) - if(teleport_target) - do_teleport(target, teleport_target, 0)//teleport what's in the tile to the beacon - else - do_teleport(target, target, 15) //Otherwise it just warps you off somewhere. - /obj/item/projectile/plasma name = "plasma blast" icon_state = "plasmacutter" @@ -321,8 +326,9 @@ obj/item/projectile/kinetic/New() if(istype(target, /turf/simulated/mineral)) var/turf/simulated/mineral/M = target M.gets_drilled(firer) - range = max(range - 1, 1) - return -1 + Range() + if(range > 0) + return -1 /obj/item/projectile/plasma/adv range = 5 @@ -331,29 +337,24 @@ obj/item/projectile/kinetic/New() damage = 10 range = 6 -/obj/item/projectile/beam/wormhole - name = "bluespace beam" - icon_state = "spark" - hitsound = "sparks" - damage = 3 - var/obj/item/weapon/gun/energy/wormhole_projector/gun = null - color = "#33CCFF" +/obj/item/projectile/energy/teleport + name = "teleportation burst" + icon_state = "bluespace" + damage = 0 + nodamage = 1 + var/teleport_target = null -/obj/item/projectile/beam/wormhole/orange - name = "orange bluespace beam" - color = "#FF6600" +/obj/item/projectile/energy/teleport/New(loc, tele_target) + ..(loc) + if(tele_target) + teleport_target = tele_target -/obj/item/projectile/beam/wormhole/OnFired() - gun = shot_from - -/obj/item/projectile/beam/wormhole/on_hit(atom/target) - if(ismob(target)) - var/turf/portal_destination = pick(orange(6, src)) - do_teleport(target, portal_destination) - return ..() - if(!gun) - qdel(src) - gun.create_portal(src) +/obj/item/projectile/energy/teleport/on_hit(var/atom/target, var/blocked = 0) + if(isliving(target)) + if(teleport_target) + do_teleport(target, teleport_target, 0)//teleport what's in the tile to the beacon + else + do_teleport(target, target, 15) //Otherwise it just warps you off somewhere. /obj/item/projectile/snowball name = "snowball" @@ -363,6 +364,7 @@ obj/item/projectile/kinetic/New() damage_type = BURN /obj/item/projectile/snowball/on_hit(atom/target) //chilling + . = ..() if(istype(target, /mob/living)) var/mob/living/M = target M.bodytemperature = max(0, M.bodytemperature - 50) //each hit will drop your body temp, so don't get surrounded! @@ -380,9 +382,38 @@ obj/item/projectile/kinetic/New() ..() /obj/item/projectile/ornament/on_hit(atom/target) //knockback + ..() if(istype(target, /turf)) return 0 var/obj/T = target var/throwdir = get_dir(firer,target) T.throw_at(get_edge_target_turf(target, throwdir),10,10) - return 1 \ No newline at end of file + 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/grenade_launcher.dm b/code/modules/reagents/grenade_launcher.dm deleted file mode 100644 index 9b9484ba60e..00000000000 --- a/code/modules/reagents/grenade_launcher.dm +++ /dev/null @@ -1,111 +0,0 @@ - - -/obj/item/weapon/gun/grenadelauncher - name = "grenade launcher" - icon = 'icons/obj/gun.dmi' - icon_state = "riotgun" - item_state = "riotgun" - w_class = 4.0 - throw_speed = 2 - throw_range = 10 - force = 5.0 - var/list/grenades = new/list() - var/max_grenades = 3 - var/ammo_name = "grenade" - var/ammo_type = /obj/item/weapon/grenade - var/unloaded - - materials = list(MAT_METAL=2000) - -/obj/item/weapon/gun/grenadelauncher/examine(mob/user) - if(..(user, 2)) - to_chat(user, "\blue [grenades.len] / [max_grenades] [ammo_name]s.") - -/obj/item/weapon/gun/grenadelauncher/attackby(obj/item/I as obj, mob/user as mob, params) - - if((istype(I, ammo_type))) - if(grenades.len < max_grenades) - user.drop_item() - I.loc = src - grenades += I - to_chat(user, "\blue You put the [ammo_name] in the [name].") - to_chat(user, "\blue [grenades.len] / [max_grenades] [ammo_name]s.") - else - to_chat(usr, "\red The grenade launcher cannot hold more [ammo_name]s.") - -/obj/item/weapon/gun/grenadelauncher/afterattack(obj/target, mob/user , flag) - - if (istype(target, /obj/item/weapon/storage/backpack )) - return - - else if (locate (/obj/structure/table, src.loc)) - return - - else if(target == user) - return - - if(grenades.len) - spawn(0) fire_grenade(target,user) - else - to_chat(usr, "\red The [name] is empty.") - -/obj/item/weapon/gun/grenadelauncher/proc/fire_grenade(atom/target, mob/user) - for(var/mob/O in viewers(world.view, user)) - O.show_message(text("\red [] fired a [ammo_name]!", user), 1) - to_chat(user, "\red You fire the [name]!") - var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta! - grenades -= F - F.loc = user.loc - F.throw_at(target, 30, 2, user) - message_admins("[key_name_admin(user)] fired a [ammo_name] ([F.name]) from a launcher ([name]).") - log_game("[key_name_admin(user)] used a [ammo_name] ([name]).") - F.active = 1 - F.icon_state = initial(icon_state) + "_active" - playsound(user.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - spawn(15) - F.prime() - - -/obj/item/weapon/gun/grenadelauncher/piecannon - name = "pie cannon" - icon = 'icons/obj/gun.dmi' - icon_state = "piecannon1" - item_state = "piecannon1" - w_class = 4.0 - throw_speed = 2 - throw_range = 10 - force = 5.0 - clumsy_check = 0 - grenades = new/list() - max_grenades = 5 - ammo_name = "cream pie" - ammo_type = /obj/item/weapon/reagent_containers/food/snacks/pie - -/obj/item/weapon/gun/grenadelauncher/piecannon/New() - ..() - for(var/i=0, i < max_grenades, i++) - var/obj/item/weapon/reagent_containers/food/snacks/pie/P = new /obj/item/weapon/reagent_containers/food/snacks/pie(src) - grenades += P - -/obj/item/weapon/gun/grenadelauncher/piecannon/attackby(obj/item/I as obj, mob/user as mob, params) - if((istype(I, ammo_type))) - if(grenades.len < max_grenades) - user.drop_item() - I.loc = src - grenades += I - to_chat(user, "\blue You put the [ammo_name] in the [name].") - to_chat(user, "\blue [grenades.len] / [max_grenades] [ammo_name]s.") - icon_state = "piecannon1" - else - to_chat(usr, "\red The grenade launcher cannot hold more [ammo_name]s.") - -/obj/item/weapon/gun/grenadelauncher/piecannon/fire_grenade(atom/target, mob/user) - for(var/mob/O in viewers(world.view, user)) - O.show_message(text("\red [] fired a [ammo_name]!", user), 1) - to_chat(user, "\red You fire the [name]!") - var/obj/item/weapon/reagent_containers/food/snacks/pie/P = grenades[1] //Now with less copypasta! - grenades -= P - P.loc = user.loc - P.throw_at(target, 30, 2, user) - if(!grenades.len) - icon_state = "piecannon0" 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 4479d24aa7c..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 @@ -509,6 +509,14 @@ result_amount = 2 mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' +/datum/chemical_reaction/cafe_mocha + name = "Cafe Mocha" + id = "cafe_mocha" + result = "cafe_mocha" + required_reagents = list("cafe_latte" = 1, "chocolate" = 1) + result_amount = 2 + mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' + /datum/chemical_reaction/acidspit name = "Acid Spit" id = "acidspit" @@ -667,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/chemical_reaction/chemical_reaction_food.dm b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_food.dm index 65b19133fa3..5f96f794b34 100644 --- a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_food.dm +++ b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_food.dm @@ -110,6 +110,16 @@ mix_message = "Ice forms as the water freezes." mix_sound = null +/datum/chemical_reaction/water + name = "Water" + id = "water" + result = "water" + required_reagents = list("ice" = 1) + result_amount = 1 + min_temp = 301 // In Space.....ice melts at 82F...don't ask + mix_message = "Water pools as the ice melts." + mix_sound = null + /datum/chemical_reaction/dough name = "Dough" id = "dough" 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/oldchem/reagents/drink/reagents_drink.dm b/code/modules/reagents/oldchem/reagents/drink/reagents_drink.dm index 45e0e2e8ac2..d52743c6ae6 100644 --- a/code/modules/reagents/oldchem/reagents/drink/reagents_drink.dm +++ b/code/modules/reagents/oldchem/reagents/drink/reagents_drink.dm @@ -241,6 +241,12 @@ M.adjustBruteLoss(-1) return +/datum/reagent/drink/coffee/cafe_latte/cafe_mocha + name = "Cafe Mocha" + id = "cafe_mocha" + description = "The perfect blend of coffe, milk, and chocolate." + color = "#673629" + /datum/reagent/drink/tea name = "Tea" id = "tea" diff --git a/code/modules/reagents/oldchem/reagents/reagents_water.dm b/code/modules/reagents/oldchem/reagents/reagents_water.dm index df9e0b29b64..11a5759fa5b 100644 --- a/code/modules/reagents/oldchem/reagents/reagents_water.dm +++ b/code/modules/reagents/oldchem/reagents/reagents_water.dm @@ -297,6 +297,13 @@ if(data >= 75 && prob(33)) // 30 units, 150 seconds if (!M.confused) M.confused = 1 M.confused += 3 + if(isvampirethrall(M)) + ticker.mode.remove_vampire_mind(M.mind) + holder.remove_reagent(src.id, src.volume) + M.jitteriness = 0 + M.stuttering = 0 + M.confused = 0 + return if(iscultist(M)) ticker.mode.remove_cultist(M.mind) holder.remove_reagent(src.id, src.volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? 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/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm index c7351d1c3fd..981bb7148a2 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm @@ -459,6 +459,10 @@ icon_state = "cafe_latte" name = "Cafe Latte" desc = "A nice, strong and refreshing beverage while you are reading." + if("cafe_mocha") + icon_state = "cafe_latte" + name = "Cafe Mocha" + desc = "The perfect blend of coffe, milk, and chocolate." if("acidspit") icon_state = "acidspitglass" name = "Acid Spit" diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 32a0e752913..efc6a48b1f9 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -155,7 +155,7 @@ /obj/item/weapon/reagent_containers/spray/chemsprayer name = "chem sprayer" desc = "A utility used to spray large amounts of reagents in a given area." - icon = 'icons/obj/gun.dmi' + icon = 'icons/obj/guns/projectile.dmi' icon_state = "chemsprayer" item_state = "chemsprayer" throwforce = 0 @@ -234,4 +234,4 @@ if (istype(A, /obj/effect/blob)) // blob damage in blob code return - ..() \ No newline at end of file + ..() diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index bd8a22cd06f..610abd27950 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -17,6 +17,7 @@ w_class = 1 sharp = 1 var/mode = SYRINGE_DRAW + var/projectile_type = /obj/item/projectile/bullet/dart/syringe /obj/item/weapon/reagent_containers/syringe/on_reagent_change() update_icon() @@ -247,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() @@ -533,4 +540,4 @@ reagents.add_reagent("capulettium_plus", 5) reagents.add_reagent("sodium_thiopental", 5) mode = SYRINGE_INJECT - update_icon() \ No newline at end of file + 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/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 00530d2a8a3..7bcc42e4979 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -280,6 +280,17 @@ build_path = /obj/item/organ/internal/cyberimp/brain/anti_stun category = list("Misc", "Medical") +/datum/design/cyberimp_clownvoice + name = "Comical implant" + desc = "Uh oh." + id = "ci-clownvoice" + req_tech = list("materials" = 2, "biotech" = 2) + build_type = PROTOLATHE | MECHFAB + construction_time = 60 + materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_BANANIUM = 200) + build_path = /obj/item/organ/internal/cyberimp/brain/clown_voice + category = list("Misc", "Medical") + /datum/design/cyberimp_nutriment name = "Nutriment pump implant" desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are starving." 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/experimentor.dm b/code/modules/research/experimentor.dm index 38004bd49fa..c9ed686645a 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -219,6 +219,7 @@ --cloneCount if(cloneCount == 0) cloneMode = FALSE + return var/turf/dropturf = get_turf(pick(view(1,src))) if(!dropturf) //Failsafe to prevent the object being lost in the void forever. dropturf = get_turf(src) @@ -373,8 +374,7 @@ FB.current = start FB.yo = MT.y - start.y FB.xo = MT.x - start.x - spawn(1) - FB.process() + FB.fire() if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions, melting [exp_on] and releasing a burst of flame!") explosion(src.loc, -1, 0, 0, 0, 0, flame_range = 2) @@ -406,7 +406,7 @@ visible_message("[src] lowers [exp_on]'s temperature.") if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s emergency coolant system gives off a small ding!") - var/obj/machinery/vending/coffee/C = new /obj/machinery/vending/coffee(get_turf(pick(oview(1,src)))) + var/obj/item/weapon/reagent_containers/food/drinks/coffee/C = new /obj/item/weapon/reagent_containers/food/drinks/coffee(get_turf(pick(oview(1,src)))) playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) //Ding! Your death coffee is ready! chosenchem = pick("uranium","frostoil","ephedrine") C.reagents.remove_any(25) @@ -492,7 +492,7 @@ ejectItem() //Global reactions - + if(prob(EFFECT_PROB_VERYLOW) && prob(13)) visible_message("[src] improves [exp_on], drawing the life essence of those nearby!") for(var/mob/living/m in view(4,src)) @@ -504,7 +504,7 @@ reqs[T] = reqs[T] + 1 exp_on.origin_tech = list2params(reqs) investigate_log("Experimentor has set the origin tech of [exp_on] to [exp_on.origin_tech]", "experimentor") - + if(prob(EFFECT_PROB_VERYLOW-badThingCoeff) && prob(87)) var/globalMalf = rand(1,87) if(globalMalf < 15) 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/xenoarchaeology/machinery/coolant.dm b/code/modules/research/xenoarchaeology/machinery/coolant.dm index f6d844fb889..b2dd9ce2a9e 100644 --- a/code/modules/research/xenoarchaeology/machinery/coolant.dm +++ b/code/modules/research/xenoarchaeology/machinery/coolant.dm @@ -27,7 +27,7 @@ datum/chemical_reaction/coolant /obj/structure/reagent_dispensers/coolanttank/bullet_act(var/obj/item/projectile/Proj) if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)) - if(!istype(Proj ,/obj/item/projectile/lasertag) && !istype(Proj ,/obj/item/projectile/practice) ) + if(!Proj.damage) explode() /obj/structure/reagent_dispensers/coolanttank/blob_act() 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 119378d53f4..586d9945c56 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -136,6 +136,8 @@ var/turf_type = /turf/space var/area_type = /area/space + var/lock_shuttle_doors = 0 + /obj/docking_port/stationary/register() if(!shuttle_master) throw EXCEPTION("docking port [src] could not initialize.") @@ -166,6 +168,8 @@ name = "In Transit" turf_type = /turf/space/transit + lock_shuttle_doors = 1 + /obj/docking_port/stationary/transit/register() if(!..()) return 0 @@ -452,7 +456,7 @@ dir = S1.dir unlockPortDoors(S1) - if(S1 && S1.id != "[id]_transit") + if(S1 && !S1.lock_shuttle_doors) for(var/obj/machinery/door/airlock/A in door_unlock_list) spawn(-1) A.unlock() @@ -615,6 +619,7 @@ var/possible_destinations = "" var/admin_controlled var/max_connect_range = 7 + var/docking_request = 0 /obj/machinery/computer/shuttle/New(location, obj/item/weapon/circuitboard/shuttle/C) ..() @@ -667,6 +672,8 @@ if(admin_controlled) dat += "Authorized personnel only
    " dat += "Request Authorization
    " + if(docking_request) + dat += "Request docking at NSS Cyberiad
    " dat += "Close" var/datum/browser/popup = new(user, "computer", M ? M.name : "shuttle", 300, 200) @@ -768,6 +775,47 @@ 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 + +/obj/machinery/computer/shuttle/trade + name = "Freighter Console" + docking_request = 1 + var/possible_destinations_dock + var/possible_destinations_nodock + var/docking_request_message = "A trading ship has requested docking aboard the NSS Cyberiad for trading. This request can be accepted or denied using a communications console." + +/obj/machinery/computer/shuttle/trade/attack_hand(mob/user) + if(world.time < trade_dock_timelimit) + possible_destinations = possible_destinations_dock + else + possible_destinations = possible_destinations_nodock + + docking_request = (world.time > trade_dockrequest_timelimit && world.time > trade_dock_timelimit) + ..(user) + +/obj/machinery/computer/shuttle/trade/Topic(href, href_list) + ..() + if(href_list["request"]) + if(world.time < trade_dockrequest_timelimit || world.time < trade_dock_timelimit) + return + to_chat(usr, "Request sent.") + command_announcement.Announce(docking_request_message, "Docking Request") + trade_dockrequest_timelimit = world.time + 1200 // They have 2 minutes to approve the request. + +/obj/machinery/computer/shuttle/trade/sol + req_access = list(access_trade_sol) + possible_destinations_dock = "trade_sol_base;trade_sol_offstation;trade_dock" + possible_destinations_nodock = "trade_sol_base;trade_sol_offstation" + shuttleId = "trade_sol" + docking_request_message = "A trading ship of Sol origin has requested docking aboard the NSS Cyberiad for trading. This request can be accepted or denied using a communications console." + #undef DOCKING_PORT_HIGHLIGHT diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index 24c4fa5110b..07c49752d15 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -30,11 +30,9 @@ var/obj/item/projectile/projone = new proj_type(firstloc) var/obj/item/projectile/projtwo = new proj_type(secondloc) projone.starting = get_turf(my_atom) - projone.shot_from = src projone.firer = usr projone.def_zone = "chest" projtwo.starting = get_turf(my_atom) - projtwo.shot_from = src projtwo.firer = usr projtwo.def_zone = "chest" spawn() @@ -46,7 +44,7 @@ /datum/spacepod/equipment var/obj/spacepod/my_atom - var/list/obj/item/device/spacepod_equipment/installed_modules // holds an easy to access list of installed modules + var/list/obj/item/device/spacepod_equipment/installed_modules = list() // holds an easy to access list of installed modules var/obj/item/device/spacepod_equipment/weaponry/weapon_system // weapons system var/obj/item/device/spacepod_equipment/misc/misc_system // misc system diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 4d6393b3348..2156977d6fe 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -73,6 +73,7 @@ pr_int_temp_processor = new /datum/global_iterator/pod_preserve_temp(list(src)) pr_give_air = new /datum/global_iterator/pod_tank_give_air(list(src)) equipment_system = new(src) + equipment_system.installed_modules += battery spacepods_list += src cargo_hold = new/obj/item/weapon/storage/internal(src) cargo_hold.w_class = 5 //so you can put bags in @@ -491,21 +492,25 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment T.loc = equipment_system equipment_system.weapon_system = T equipment_system.weapon_system.my_atom = src + equipment_system.installed_modules += T var/obj/item/device/spacepod_equipment/misc/tracker/L = new /obj/item/device/spacepod_equipment/misc/tracker L.loc = equipment_system equipment_system.misc_system = L equipment_system.misc_system.my_atom = src equipment_system.misc_system.enabled = 1 + equipment_system.installed_modules += L var/obj/item/device/spacepod_equipment/sec_cargo/chair/C = new /obj/item/device/spacepod_equipment/sec_cargo/chair C.loc = equipment_system equipment_system.sec_cargo_system = C equipment_system.sec_cargo_system.my_atom = src + equipment_system.installed_modules += C max_passengers = 1 var/obj/item/device/spacepod_equipment/lock/keyed/K = new /obj/item/device/spacepod_equipment/lock/keyed K.loc = equipment_system equipment_system.lock_system = K equipment_system.lock_system.my_atom = src equipment_system.lock_system.id = 100000 + equipment_system.installed_modules += K /obj/spacepod/random/New() ..() diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index a5af2caca3d..b753bcf71a5 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -144,6 +144,13 @@ spawn(90 / severity) crit_fail = 0 +/obj/item/organ/internal/cyberimp/brain/clown_voice + name = "Comical implant" + desc = "Uh oh." + implant_color = "#DEDE00" + slot = "brain_clownvoice" + origin_tech = "materials=2;biotech=2" + //[[[[CHEST]]]] /obj/item/organ/internal/cyberimp/chest name = "cybernetic torso implant" @@ -315,7 +322,7 @@ organ_action_name = "Toggle Arm Cannon Taser" /obj/item/organ/internal/cyberimp/chest/arm_mod/tase/New()//when the implant is created... - holder = new /obj/item/weapon/gun/energy/advtaser/mounted(src)//assign a brand new item to it. (in this case, a gun) + holder = new /obj/item/weapon/gun/energy/gun/advtaser/mounted(src)//assign a brand new item to it. (in this case, a gun) /obj/item/organ/internal/cyberimp/chest/arm_mod/lase//mounted, self-charging laser! name = "Arm-cannon laser implant" @@ -351,4 +358,4 @@ var/implant while(contents.len <= amount + 1) // +1 for the autoimplanter. implant = pick(boxed) - new implant(src) \ No newline at end of file + new implant(src) 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 5982237cbac..f4a47c595cb 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -10,6 +10,7 @@ vital = 0 var/organ_action_name = null var/non_primary = 0 + action_button_custom_type = /datum/action/item_action/organ_action /obj/item/organ/internal/New(var/mob/living/carbon/holder) if(istype(holder)) @@ -80,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/dm.sh b/dm.sh index 3d04531b3f4..d77cabc637a 100644 --- a/dm.sh +++ b/dm.sh @@ -79,7 +79,7 @@ else then DreamMaker $dmepath.mdme 2>&1 | tee result.log retval=$? - if ! grep '0 errors, 0 warnings' result.log + if ! grep '\- 0 errors, 0 warnings' result.log then retval=1 #hard fail, due to warnings or errors fi @@ -94,4 +94,4 @@ mv $dmepath.mdme.rsc $dmepath.rsc rm $dmepath.mdme -exit $retval \ No newline at end of file +exit $retval diff --git a/html/changelog.html b/html/changelog.html index 095d98ad174..b29fcaa7de1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,216 @@ -->
    +

    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:

    +
      +
    • Fixed the long-lasting bug of handcuffed people keeping their chainsaws.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • No more language message-spam on roundstart
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Adds a new icon for the detective's scanner.
    • +
    • Detectives scanner now has access to DNA and fingerprint records.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds three new chaplain weapons: pirate saber, multiverse sword, and possessed/talking sword
    • +
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • +
    • Adds in a mocha drink
    • +
    • Fixes ice being unobtainable for the jobs that use it most
    • +
    • Fixes laser armor losing its reflecting ability
    • +
    • Fixes the lack of progress bars for more stack-based construction
    • +
    • Fixes Experimentor producing coffee machines instead of cups
    • +
    • Can deconvert mindslaves by removing their mindslave implant
    • +
    • Can deconvert Vampire thralls by feeding them holy water
    • +
    • Fixes mindslaves not having a HUD for the master and mindslave
    • +
    • Fixes being able to duplicate just about anything in the Experimentor
    • +
    • Fixes not being able to use tank transfer valves or one tank bombs in the Experimentor.
    • +
    • Fixes infinite-throw spam
    • +
    • Fixes being able to resist out of grabs by moving (that is to say, it'll actually work now)
    • +
    • Fixes passive grabs using the wrong HUD icon
    • +
    • Tabling duration reduced from 5 to 2
    • +
    • Can no longer wield double-bladed energy swords as a hulk
    • +
    • Fixes on map stools having the wrong offsets, making it look like you're not sitting on them
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added (Enabled) Mind Batterer for Traitors
    • +
    • Fixed uplink implant description (Said 5 when actually gave you 10 TCs)
    • +
    +

    Glorken updated:

    +
      +
    • Shifts Zeng-Hu left leg over in order to regain thigh gap.
    • +
    • Chops off a pixel on Bishop feet so that they fit into shoes.
    • +
    +

    KasparoVy updated:

    +
      +
    • Old placeholder IPC butt sprite replaced with the finished QR-code sprite.
    • +
    +

    Krausus updated:

    +
      +
    • Fixes ghosts failing to follow mobs that move in unusual ways
    • +
    • Fixed tape allowing mobs with sufficient access to move through solid objects.
    • +
    +

    Many -tg-station Coders, TheDZD updated:

    +
      +
    • Old gun code is now gone.
    • +
    • Ports the vast majority of TG's gun code and their guns (any previously unavailable guns, and newly-added guns will remain unavailable to players). Expect some changes that might not be listed here due to the sheer scope of this refactor.
    • +
    • Probably some new bugs.
    • +
    • A lot of old gun bugs.
    • +
    • Mouth suiciding with a gun no longer instantly kills you, you fire the gun at yourself at 5x damage (assuming it even did damage to begin with).
    • +
    • Mouth suicide shooting does not work on harm intent.
    • +
    • You can now bash people with guns while on harm intent instead of shooting them point-blank.
    • +
    • You can now mouth suicide other people, doing so still takes the full 12 seconds to mouth suicide, but has the same 5x damage multiplier.
    • +
    • Vox spike throwers are real guns that fire spike bullets now, instead of just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor piercing, cause a 1 second stun (not the kind that drops you to the floor), and cause some bleeding. They have 2 round burst fire as well, and have 10 shots per clip. A new should should recharge every 20 or so seconds.
    • +
    • Xray lasers now have a maximum range of 15 tiles.
    • +
    • Zoomed guns now actually fire accurately while zoomed.
    • +
    • Using Suicide with guns now actually does gun-like things.
    • +
    • The clown no longer deletes guns if he fucks up with them due to being clumsy.
    • +
    • Emitters no longer become inaccurate over long ranges.
    • +
    • Power gloves now override middle-click and alt-click when worn.
    • +
    • Power gloves give a notification when worn.
    • +
    • Power gloves now have special examine text when examined by an antagonist.
    • +
    • Proto SMGs now only have a 21 shot clip.
    • +
    +

    Spacemanspark updated:

    +
      +
    • Adds the ability to make a more irritated buzz noise at people as a synthetic. The original buzz is still there.
    • +
    +

    Tauka Usanake updated:

    +
      +
    • Adds more belt icon overlays
    • +
    +

    Twinmold updated:

    +
      +
    • Nar'Sie AI Hologram and Error Sprite
    • +
    • Fixes space pod equipment variable. Can now properly install/uninstall equipment.
    • +
    • Check Seat verb no longer pulls out installed equipment.
    • +
    • You can now have a passenger in your pod if you have a passenger seat.
    • +
    +

    monster860 updated:

    +
      +
    • Adds comical implant. It is an implant that causes you to have a comic sans voice. It can be made in the protolathe using bananium.
    • +
    • The comical implant now spawns by default inside IPC clowns
    • +
    • Fixes the window getting stuck when you try to drag or resize a NanoUI window too fast with Fancy NanoUI enabled
    • +
    • Fixes a small quirk with the resize handle.
    • +
    • Fix javascript error in cargo UI
    • +
    +

    pinatacolada updated:

    +
      +
    • removes atmos tech SOP from supply SOP
    • +
    • Fixes defibing people without a heart
    • +
    • Fixes defib saying it didn't work stopping a heart attack when they do
    • +
    + +

    02 June 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Fixed a text problem in virtual gameboard description.
    • +
    • Made gameboards deconstructable and movable.
    • +
    • Added a light to gameboards. Pretty!
    • +
    +

    Crazylemon64 updated:

    +
      +
    • There will no longer be a mountain of startup runtimes when people have custom languages.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Removes xenobio golem rune creation sound
    • +
    • Added overlays for sec belts that reflect the items stored therein.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Chapel and Chaplain's office not having a light switch
    • +
    • Fixes mass driver only being usable once due to weird pressure
    • +
    • Fixes chapel being overly dark near coffins
    • +
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • +
    +

    IK3I updated:

    +
      +
    • crate cargo system
    • +
    • passenger seat system
    • +
    • loot box secondary cargo system (install it and your pod has a standard inventory)
    • +
    • lock busters for the CE and Armory
    • +
    • incappacitated people can't operate the door controls anymore
    • +
    • Items dropped in a pod can now be scrounged up
    • +
    • security can rip you out of an unlocked pod
    • +
    • The pod code isn't full of tumors any more
    • +
    +

    Tastyfish updated:

    +
      +
    • Holsters now have an action button while on your suit again.
    • +
    +

    monster860 updated:

    +
      +
    • Adds the following words to the AI announcer: active, airlock, alcohol, arrival, arrivals, becoming, between, blob, briefing, camp, chair, chapel, closet, cyberiad, declared, detective, diona, dock, docked, docking, docks, drask, drunk, emag, equipment, evacuation, experimentor, gateway, hail, hallway, holoparasite, honk, hull, ian, imminent, interested, intruders, kida, kidan, labor, library, mime, mimes, miner, miners, mining, n2o, nuke, office, op, operational, ops, pod, pods, poly, pun, renault, representative, runtime, scrubbers, sequencer, skree, skrek, skrell, space, spider, spiders, still, stupid, swarmer, swarmers, sword, technology, teleport, teleported, teleporter, teleporting, tesla, tool, unathi, vacant, vault, vents, vulpkanin, weld, window, windows, yet
    • +
    +

    31 May 2016

    CrAzYPiLoT updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 9ae2b44105f..3cc2cf1b582 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1624,3 +1624,203 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. with any access. - rscadd: Adds the HoP guest pass computer to the HoP office. - rscadd: Moves the guest pass computer in robotics to RnD. +2016-06-02: + CrAzYPiLoT: + - bugfix: Fixed a text problem in virtual gameboard description. + - rscadd: Made gameboards deconstructable and movable. + - tweak: Added a light to gameboards. Pretty! + Crazylemon64: + - bugfix: There will no longer be a mountain of startup runtimes when people have + custom languages. + DaveTheHeadcrab: + - tweak: Removes xenobio golem rune creation sound + - rscadd: Added overlays for sec belts that reflect the items stored therein. + Fox McCloud: + - bugfix: Fixes Chapel and Chaplain's office not having a light switch + - bugfix: Fixes mass driver only being usable once due to weird pressure + - bugfix: Fixes chapel being overly dark near coffins + - bugfix: Fixes not being able to sheath the claymore in the Crusader Armor + IK3I: + - rscadd: crate cargo system + - rscadd: passenger seat system + - rscadd: loot box secondary cargo system (install it and your pod has a standard + inventory) + - rscadd: lock busters for the CE and Armory + - bugfix: incappacitated people can't operate the door controls anymore + - bugfix: Items dropped in a pod can now be scrounged up + - bugfix: security can rip you out of an unlocked pod + - bugfix: The pod code isn't full of tumors any more + Tastyfish: + - bugfix: Holsters now have an action button while on your suit again. + monster860: + - rscadd: 'Adds the following words to the AI announcer: active, airlock, alcohol, + arrival, arrivals, becoming, between, blob, briefing, camp, chair, chapel, closet, + cyberiad, declared, detective, diona, dock, docked, docking, docks, drask, drunk, + emag, equipment, evacuation, experimentor, gateway, hail, hallway, holoparasite, + honk, hull, ian, imminent, interested, intruders, kida, kidan, labor, library, + mime, mimes, miner, miners, mining, n2o, nuke, office, op, operational, ops, + pod, pods, poly, pun, renault, representative, runtime, scrubbers, sequencer, + skree, skrek, skrell, space, spider, spiders, still, stupid, swarmer, swarmers, + sword, technology, teleport, teleported, teleporter, teleporting, tesla, tool, + unathi, vacant, vault, vents, vulpkanin, weld, window, windows, yet' +2016-06-12: + CrAzYPiLoT: + - bugfix: Fixed the long-lasting bug of handcuffed people keeping their chainsaws. + Crazylemon64: + - bugfix: No more language message-spam on roundstart + DaveTheHeadcrab: + - rscadd: Adds a new icon for the detective's scanner. + - tweak: Detectives scanner now has access to DNA and fingerprint records. + Fox McCloud: + - rscadd: 'Adds three new chaplain weapons: pirate saber, multiverse sword, and + possessed/talking sword' + - bugfix: Fixes not being able to sheath the claymore in the Crusader Armor + - rscadd: Adds in a mocha drink + - bugfix: Fixes ice being unobtainable for the jobs that use it most + - bugfix: Fixes laser armor losing its reflecting ability + - bugfix: Fixes the lack of progress bars for more stack-based construction + - bugfix: Fixes Experimentor producing coffee machines instead of cups + - tweak: Can deconvert mindslaves by removing their mindslave implant + - tweak: Can deconvert Vampire thralls by feeding them holy water + - bugfix: Fixes mindslaves not having a HUD for the master and mindslave + - bugfix: Fixes being able to duplicate just about anything in the Experimentor + - bugfix: Fixes not being able to use tank transfer valves or one tank bombs in + the Experimentor. + - bugfix: Fixes infinite-throw spam + - bugfix: Fixes being able to resist out of grabs by moving (that is to say, it'll + actually work now) + - bugfix: Fixes passive grabs using the wrong HUD icon + - tweak: Tabling duration reduced from 5 to 2 + - tweak: Can no longer wield double-bladed energy swords as a hulk + - bugfix: Fixes on map stools having the wrong offsets, making it look like you're + not sitting on them + FreeStylaLT: + - rscadd: Added (Enabled) Mind Batterer for Traitors + - spellcheck: Fixed uplink implant description (Said 5 when actually gave you 10 + TCs) + Glorken: + - bugfix: Shifts Zeng-Hu left leg over in order to regain thigh gap. + - bugfix: Chops off a pixel on Bishop feet so that they fit into shoes. + KasparoVy: + - tweak: Old placeholder IPC butt sprite replaced with the finished QR-code sprite. + Krausus: + - bugfix: Fixes ghosts failing to follow mobs that move in unusual ways + - bugfix: Fixed tape allowing mobs with sufficient access to move through solid + objects. + Many -tg-station Coders, TheDZD: + - rscdel: Old gun code is now gone. + - rscadd: Ports the vast majority of TG's gun code and their guns (any previously + unavailable guns, and newly-added guns will remain unavailable to players). + Expect some changes that might not be listed here due to the sheer scope of + this refactor. + - rscadd: Probably some new bugs. + - bugfix: A lot of old gun bugs. + - rscadd: Mouth suiciding with a gun no longer instantly kills you, you fire the + gun at yourself at 5x damage (assuming it even did damage to begin with). + - tweak: Mouth suicide shooting does not work on harm intent. + - tweak: You can now bash people with guns while on harm intent instead of shooting + them point-blank. + - rscadd: You can now mouth suicide other people, doing so still takes the full + 12 seconds to mouth suicide, but has the same 5x damage multiplier. + - tweak: Vox spike throwers are real guns that fire spike bullets now, instead of + just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor + piercing, cause a 1 second stun (not the kind that drops you to the floor), + and cause some bleeding. They have 2 round burst fire as well, and have 10 shots + per clip. A new should should recharge every 20 or so seconds. + - tweak: Xray lasers now have a maximum range of 15 tiles. + - bugfix: Zoomed guns now actually fire accurately while zoomed. + - rscadd: Using Suicide with guns now actually does gun-like things. + - tweak: The clown no longer deletes guns if he fucks up with them due to being + clumsy. + - bugfix: Emitters no longer become inaccurate over long ranges. + - tweak: Power gloves now override middle-click and alt-click when worn. + - tweak: Power gloves give a notification when worn. + - tweak: Power gloves now have special examine text when examined by an antagonist. + - tweak: Proto SMGs now only have a 21 shot clip. + Spacemanspark: + - rscadd: Adds the ability to make a more irritated buzz noise at people as a synthetic. + The original buzz is still there. + Tauka Usanake: + - rscadd: Adds more belt icon overlays + Twinmold: + - rscadd: Nar'Sie AI Hologram and Error Sprite + - bugfix: Fixes space pod equipment variable. Can now properly install/uninstall + equipment. + - bugfix: Check Seat verb no longer pulls out installed equipment. + - bugfix: You can now have a passenger in your pod if you have a passenger seat. + monster860: + - rscadd: Adds comical implant. It is an implant that causes you to have a comic + sans voice. It can be made in the protolathe using bananium. + - rscadd: The comical implant now spawns by default inside IPC clowns + - bugfix: Fixes the window getting stuck when you try to drag or resize a NanoUI + window too fast with Fancy NanoUI enabled + - bugfix: Fixes a small quirk with the resize handle. + - bugfix: Fix javascript error in cargo UI + pinatacolada: + - 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-4383.yml b/html/changelogs/AutoChangeLog-pr-4383.yml deleted file mode 100644 index ea862e39a05..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4383.yml +++ /dev/null @@ -1,11 +0,0 @@ -author: IK3I -delete-after: True -changes: - - rscadd: "crate cargo system" - - rscadd: "passenger seat system" - - rscadd: "loot box secondary cargo system (install it and your pod has a standard inventory)" - - rscadd: "lock busters for the CE and Armory" - - bugfix: "incappacitated people can't operate the door controls anymore" - - bugfix: "Items dropped in a pod can now be scrounged up" - - bugfix: "security can rip you out of an unlocked pod" - - bugfix: "The pod code isn't full of tumors any more" 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-4541.yml b/html/changelogs/AutoChangeLog-pr-4541.yml deleted file mode 100644 index d8bb77d3f58..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4541.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: DaveTheHeadcrab -delete-after: True -changes: - - tweak: "Removes xenobio golem rune creation sound" diff --git a/html/changelogs/AutoChangeLog-pr-4545.yml b/html/changelogs/AutoChangeLog-pr-4545.yml deleted file mode 100644 index 03d1f21b0c6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4545.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Crazylemon64 -delete-after: True -changes: - - bugfix: "There will no longer be a mountain of startup runtimes when people have custom languages." 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-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-4694.yml b/html/changelogs/AutoChangeLog-pr-4694.yml new file mode 100644 index 00000000000..2e233d399e4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4694.yml @@ -0,0 +1,7 @@ +author: Kyep +delete-after: True +changes: + - rscadd: "Admins now hear boink sound when faxed, command sends ERT request, etc" + - rscadd: "Admins can reply to faxes via radio" + - rscadd: "Admins can reply to faxes with pre-written fax templates" + - rscadd: "Admins can reply to faxes with 'evil faxes', special faxes that have negative effects on their intended recipient (and nobody else)" 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/html/changelogs/AutoChangeLog-pr-4729.yml b/html/changelogs/AutoChangeLog-pr-4729.yml new file mode 100644 index 00000000000..566d5a8d623 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4729.yml @@ -0,0 +1,4 @@ +author: Twinmold +delete-after: True +changes: + - bugfix: "You can once again resist borer control with the Resist verb." diff --git a/html/changelogs/AutoChangeLog-pr-4734.yml b/html/changelogs/AutoChangeLog-pr-4734.yml new file mode 100644 index 00000000000..2650702dfb9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4734.yml @@ -0,0 +1,4 @@ +author: TheDZD +delete-after: True +changes: + - bugfix: "Unstable bluespace teleportation devices have been removed from energy guns, meaning they should no longer teleport from one hand to another when switching firing modes." 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/goonstation/objects/objects.dmi b/icons/goonstation/objects/objects.dmi index 41523d18541..8dadb400668 100644 Binary files a/icons/goonstation/objects/objects.dmi and b/icons/goonstation/objects/objects.dmi differ diff --git a/icons/mob/AI.dmi b/icons/mob/AI.dmi index 13c653883ef..4c879d066b1 100644 Binary files a/icons/mob/AI.dmi and b/icons/mob/AI.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index ce634c701d9..a4cd1d997a8 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index eeb5ecbbee3..c5115b3cbc5 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.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/cyberlimbs/bishop/bishop_main.dmi b/icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi index 3bf83ae98cd..819b01edafe 100644 Binary files a/icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi and b/icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi b/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi index 0d74250a3ea..0cb76d89420 100644 Binary files a/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi and b/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.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/inhands/guns_lefthand.dmi b/icons/mob/inhands/guns_lefthand.dmi index 63fbda7a4bd..3088c274007 100644 Binary files a/icons/mob/inhands/guns_lefthand.dmi and b/icons/mob/inhands/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/guns_righthand.dmi b/icons/mob/inhands/guns_righthand.dmi index d8fada37744..ea22f2728b1 100644 Binary files a/icons/mob/inhands/guns_righthand.dmi and b/icons/mob/inhands/guns_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 67313e46bfb..61c176bd08a 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 1462d26e344..652996f8d8c 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.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/screen_gen.dmi b/icons/mob/screen_gen.dmi index 4936936afde..c3843c0c967 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.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/uniform.dmi b/icons/mob/uniform.dmi index 07455bdf920..6fed8c42c66 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index 7e588ec2210..b6bbd8ab349 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/butts.dmi b/icons/obj/butts.dmi index 9a71d519a19..104906120d4 100644 Binary files a/icons/obj/butts.dmi and b/icons/obj/butts.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index afe27ae192d..ccf3bad52b5 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index 7427f32fd3e..f747338a5a7 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/obj/custom_items.dmi b/icons/obj/custom_items.dmi index 5e7c8e43981..a2c5117d204 100644 Binary files a/icons/obj/custom_items.dmi and b/icons/obj/custom_items.dmi differ diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi deleted file mode 100644 index 45e4265c292..00000000000 Binary files a/icons/obj/gun.dmi and /dev/null differ diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi new file mode 100644 index 00000000000..39b73d8052b Binary files /dev/null and b/icons/obj/guns/energy.dmi differ diff --git a/icons/obj/gun_temperature.dmi b/icons/obj/guns/gun_temperature.dmi similarity index 100% rename from icons/obj/gun_temperature.dmi rename to icons/obj/guns/gun_temperature.dmi diff --git a/icons/obj/guns/magic.dmi b/icons/obj/guns/magic.dmi new file mode 100644 index 00000000000..2f3fc52957a Binary files /dev/null and b/icons/obj/guns/magic.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi new file mode 100644 index 00000000000..cd1eed09f02 Binary files /dev/null and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/toyguns.dmi b/icons/obj/guns/toy.dmi similarity index 81% rename from icons/obj/toyguns.dmi rename to icons/obj/guns/toy.dmi index bd2ff273a40..d05231e7718 100644 Binary files a/icons/obj/toyguns.dmi and b/icons/obj/guns/toy.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 23ee204e96a..5a780217109 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 6e6d268c9bd..b7f40b4cdbb 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index a10524fb9b9..01609b50824 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index 589a5e0dc86..81fe75b269b 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -40,9 +40,7 @@ src << browse('html/changelog.html', "window=changes;size=675x650") if(prefs.lastchangelog != changelog_hash) //if it's already opened, no need to tell them they have unread changes - prefs.lastchangelog = changelog_hash - prefs.save_preferences() - winset(src, "rpane.changelog", "background-color=none;font-style=") + prefs.SetChangelog(src,changelog_hash) /client/verb/forum() set name = "forum" diff --git a/nano/assets/nano.js b/nano/assets/nano.js index 7e07be10238..656ed818227 100644 --- a/nano/assets/nano.js +++ b/nano/assets/nano.js @@ -1 +1 @@ -function NanoStateDefaultClass(){this.key="default",this.key=this.key.toLowerCase(),NanoStateManager.addState(this)}function NanoStatePDAClass(){this.key="pda",this.key=this.key.toLowerCase(),this.current_template="",NanoStateManager.addState(this)}function NanoStateClass(){}var NanoUtility=function(){var e={};return{init:function(){var t=$("body");e=t.data("urlParameters")},generateHref:function(t){var n="?";for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);for(var a in t)t.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+t[a]);return n},winset:function(e,t,n){var a,r;return null==n&&(n=NanoStateManager.getData().config.window.ref),a={},a[n+"."+e]=t,r=a,location.href=NanoUtility.href("winset",r)},extend:function(e,t){return Object.keys(t).forEach(function(n){var a;return a=t[n],a&&"[object Object]"===Object.prototype.toString.call(a)?(e[n]=e[n]||{},NanoUtility.extend(e[n],a)):e[n]=a}),e},href:function(e,t){return null==e&&(e=""),null==t&&(t={}),e=new Url("byond://"+e),NanoUtility.extend(e.query,t),e},close:function(){var t;return t={command:"nanoclose "+e.src},this.winset("is-visible","false"),location.href=NanoUtility.href("winset",t)}}}();"undefined"==typeof jQuery&&reportError("ERROR: Javascript library failed to load!"),"undefined"==typeof doT&&reportError("ERROR: Template engine failed to load!");var reportError=function(e){window.location="byond://?nano_err="+encodeURIComponent(e),alert(e)};$(document).ready(function(){NanoUtility.init(),NanoStateManager.init(),NanoTemplate.init(),NanoWindow.init()}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),String.prototype.format||(String.prototype.format=function(e){var t=this;return t.replace(String.prototype.format.regex,function(t){var n,a=parseInt(t.substring(1,t.length-1));return n=a>=0?e[a]:-1===a?"{":-2===a?"}":""})},String.prototype.format.regex=new RegExp("{-?[0-9]+}","g")),Object.size=function(e){var t,n=0;for(var t in e)e.hasOwnProperty(t)&&n++;return n},window.console||(window.console={log:function(e){return!1}}),String.prototype.toTitleCase=function(){var e=/^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;return this.replace(/([^\W_]+[^\s-]*) */g,function(t,n,a,r){return a>0&&a+n.length!==r.length&&n.search(e)>-1&&":"!==r.charAt(a-2)&&r.charAt(a-1).search(/[^\s-]/)<0?t.toLowerCase():n.substr(1).search(/[A-Z]|\../)>-1?t:t.charAt(0).toUpperCase()+t.substr(1)})},$.ajaxSetup({cache:!1}),Function.prototype.inheritsFrom=function(e){return this.prototype=new e,this.prototype.constructor=this,this.prototype.parent=e.prototype,this},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.ckey||(String.prototype.ckey=function(){return this.replace(/\W/g,"").toLowerCase()}),NanoStateManager=function(){var e=!1,t=null,n={},a={},r={},o=null,i=function(){t=$("body").data("initialData"),null!=t&&t.hasOwnProperty("config")&&t.hasOwnProperty("data")||reportError("Error: Initial data did not load correctly.");var n="default";t.config.hasOwnProperty("stateKey")&&t.config.stateKey&&(n=t.config.stateKey.toLowerCase()),NanoStateManager.setCurrentState(n),$(document).on("templatesLoaded",function(){l(t),e=!0})},s=function(n){var a;try{a=jQuery.parseJSON(n)}catch(r){return void reportError("recieveUpdateData failed.
      Error name: "+r.name+"
      Error Message: "+r.message)}a.hasOwnProperty("data")||(t&&t.hasOwnProperty("data")?a.data=t.data:a.data={}),e?l(a):t=a},l=function(e){if(null!=o){if(e=o.onBeforeUpdate(e),e===!1)return void reportError("data is false, return");t=e,o.onUpdate(t),o.onAfterUpdate(t)}},u=function(e,t){for(var n in e)e.hasOwnProperty(n)&&jQuery.isFunction(e[n])&&(t=e[n].call(this,t));return t};return{init:function(){i()},receiveUpdateData:function(e){s(e)},addBeforeUpdateCallback:function(e,t){n[e]=t},addBeforeUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addBeforeUpdateCallback(t,e[t])},removeBeforeUpdateCallback:function(e){n.hasOwnProperty(e)&&delete n[e]},executeBeforeUpdateCallbacks:function(e){return u(n,e)},addAfterUpdateCallback:function(e,t){a[e]=t},addAfterUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addAfterUpdateCallback(t,e[t])},removeAfterUpdateCallback:function(e){a.hasOwnProperty(e)&&delete a[e]},executeAfterUpdateCallbacks:function(e){return u(a,e)},addState:function(e){return e instanceof NanoStateClass?e.key?void(r[e.key]=e):void reportError("ERROR: Attempted to add a state with an invalid stateKey"):void reportError("ERROR: Attempted to add a state which is not instanceof NanoStateClass")},setCurrentState:function(e){if("undefined"==typeof e||!e)return reportError("ERROR: No state key was passed!"),!1;if(!r.hasOwnProperty(e))return reportError("ERROR: Attempted to set a current state which does not exist: "+e),!1;var t=o;return o=r[e],null!=t&&t.onRemove(o),o.onAdd(t),!0},getCurrentState:function(){return o},getData:function(){return t}}}(),NanoBaseCallbacks=function(){var e=!0,t={},n={status:function(t){var n;return 2==t.config.status?(n="good",$(".linkActive").removeClass("inactive")):1==t.config.status?(n="average",$(".linkActive").addClass("inactive")):(n="bad",$(".linkActive").addClass("inactive")),$(".statusicon").removeClass("good bad average").addClass(n),$(".linkActive").stopTime("linkPending"),$(".linkActive").removeClass("linkPending"),$(".linkActive").off("click").on("click",function(n){n.preventDefault();var a=$(this).data("href");null!=a&&e&&(e=!1,$("body").oneTime(300,"enableClick",function(){e=!0}),2==t.config.status&&$(this).oneTime(300,"linkPending",function(){$(this).addClass("linkPending")}),window.location.href=a)}),t},nanomap:function(e){return $(".mapIcon").off("mouseenter mouseleave").on("mouseenter",function(e){$("#uiMapTooltip").html($(this).children(".tooltip").html()).show().stopTime().oneTime(5e3,"hideTooltip",function(){$(this).fadeOut(500)})}),$(".zoomLink").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("zoomLevel"),n=$("#uiMap"),a=n.width()*t,r=n.height()*t;n.css({zoom:t,left:"50%",top:"50%",marginLeft:"-"+Math.floor(a/2)+"px",marginTop:"-"+Math.floor(r/2)+"px"})}),$("#uiMapImage").attr("src","nanomap_z"+e.config.mapZLevel+".png"),e}};return{addCallbacks:function(){NanoStateManager.addBeforeUpdateCallbacks(t),NanoStateManager.addAfterUpdateCallbacks(n)},removeCallbacks:function(){for(var e in t)t.hasOwnProperty(e)&&NanoStateManager.removeBeforeUpdateCallback(e);for(var e in n)n.hasOwnProperty(e)&&NanoStateManager.removeAfterUpdateCallback(e)}}}(),NanoBaseHelpers=function(){var e={syndicateMode:function(){return $("body").css("background-color","#8f1414"),$("body").css("background-image","url('uiBackground-Syndicate.png')"),$("body").css("background-position","50% 0"),$("body").css("background-repeat","repeat-x"),$("#uiTitleFluff").css("background-image","url('uiTitleFluff-Syndicate.png')"),$("#uiTitleFluff").css("background-position","50% 50%"),$("#uiTitleFluff").css("background-repeat","no-repeat"),""},combine:function(e,t){return e&&t?e.concat(t):e||t},dump:function(e){return JSON.stringify(e)},link:function(e,t,n,a,r,o){var i="",s="noIcon";"undefined"!=typeof t&&t&&(i='
      ',s="hasIcon"),"undefined"!=typeof r&&r||(r="link");var l="";"undefined"!=typeof o&&o&&(l='id="'+o+'"');var u=NanoTransition.allocID(l+"_"+e.toString().replace(/[^a-z0-9_]/gi,"_")+"_"+t);return"undefined"!=typeof a&&a?'':'
      "+i+e+'
      '},xor:function(e,t){return e^t},precisionRound:function(e,t){if(0==t)return Math.round(number);var n=Math.pow(10,t);return Math.round(e*n)/n},round:function(e){return Math.round(e)},fixed:function(e){return Math.round(10*e)/10},floor:function(e){return Math.floor(e)},ceil:function(e){return Math.ceil(e)},string:function(){if(0==arguments.length)return"";if(1==arguments.length)return arguments[0];if(arguments.length>1){stringArgs=[];for(var e=1;et?t>e?e=t:e>n&&(e=n):e>t?e=t:n>e&&(e=n),"undefined"!=typeof a&&a||(a=""),"undefined"!=typeof r&&r||(r="");var o=Math.round((e-t)/(n-t)*100),i=NanoTransition.allocID(t+"_"+n);return'
      '+r+'
      '},dangerToClass:function(e){return 0==e?"good":1==e?"average":"bad"},dangerToSpan:function(e){return 0==e?'"Good"':1==e?'"Minor Alert"':'"Major Alert"'},generateHref:function(e){var t=$("body");_urlParameters=t.data("urlParameters");var n="?";for(var a in _urlParameters)_urlParameters.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+_urlParameters[a]);for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);return n},displayDNABlocks:function(e,t,n,a,r){if(!e)return'
      Please place a valid subject into the DNA modifier.
      ';var o=e.split(""),i='
      ',s=1,l=1;for(var u in o)if(o.hasOwnProperty(u)&&"object"!=typeof o[u]){var c;c="UI"==r.toUpperCase()?{selectUIBlock:s,selectUISubblock:l}:{selectSEBlock:s,selectSESubblock:l};var d="linkActive";s==t&&l==n&&(d="selected"),i+='",u++,u%a==0&&u
      "):l++}return i+="
      "},cMirror:function(e){CodeMirror.fromTextArea(document.getElementById(e),{lineNumbers:!0,indentUnit:4,indentWithTabs:!0,theme:"lesser-dark"})},smoothNumber:function(e){var t=NanoTransition.allocID("n");return''},smoothRound:function(e,t){var n=NanoTransition.allocID(t);return void 0===t&&(placed=0),''}};return{addHelpers:function(){NanoTemplate.addHelpers(e)},removeHelpers:function(){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.removeHelper(t)}}}(),NanoStateDefaultClass.inheritsFrom(NanoStateClass);var NanoStateDefault=new NanoStateDefaultClass;NanoStatePDAClass.inheritsFrom(NanoStateClass);var NanoStatePDA=new NanoStatePDAClass;NanoStatePDAClass.prototype.onUpdate=function(e){NanoStateClass.prototype.onUpdate.call(this,e);var t=this;try{if(null!=e.data.app){var n=e.data.app.template;null!=n&&n!=t.current_template?$.when($.ajax({url:n+".tmpl",cache:!1,dataType:"text"})).done(function(a){a+='
      ';try{NanoTemplate.addTemplate("app",a),NanoTemplate.resetTemplate("app"),$("#uiApp").html(NanoTemplate.parse("app",e)),t.current_template=n,t.onAfterUpdate(e)}catch(r){return void reportError("ERROR: An error occurred while loading the PDA App UI: "+r.message)}}).fail(function(){reportError("ERROR: Loading template app("+n+") failed!")}):NanoTemplate.templateExists("app")&&$("#uiApp").html(NanoTemplate.parse("app",e))}}catch(a){return void reportError("ERROR: An error occurred while rendering the PDA App UI: "+a.message)}},NanoStateClass.prototype.key=null,NanoStateClass.prototype.layoutRendered=!1,NanoStateClass.prototype.contentRendered=!1,NanoStateClass.prototype.mapInitialised=!1,NanoStateClass.prototype.isCurrent=function(){return NanoStateManager.getCurrentState()==this},NanoStateClass.prototype.onAdd=function(e){NanoBaseCallbacks.addCallbacks(),NanoBaseHelpers.addHelpers()},NanoStateClass.prototype.onRemove=function(e){NanoBaseCallbacks.removeCallbacks(),NanoBaseHelpers.removeHelpers()},NanoStateClass.prototype.onBeforeUpdate=function(e){return e=NanoStateManager.executeBeforeUpdateCallbacks(e)},NanoStateClass.prototype.onUpdate=function(e){try{(!this.layoutRendered||e.config.hasOwnProperty("autoUpdateLayout")&&e.config.autoUpdateLayout)&&($("#uiLayout").html(NanoTemplate.parse("layout",e)),this.layoutRendered=!0),(!this.contentRendered||e.config.hasOwnProperty("autoUpdateContent")&&e.config.autoUpdateContent)&&($("#uiContent").html(NanoTemplate.parse("main",e)),this.contentRendered=!0),NanoTemplate.templateExists("mapContent")&&(this.mapInitialised||($("#uiMap").draggable(),$("#uiMapTooltip").off("click").on("click",function(e){e.preventDefault(),$(this).fadeOut(400)}),this.mapInitialised=!0),$("#uiMapContent").html(NanoTemplate.parse("mapContent",e)),e.config.hasOwnProperty("showMap")&&e.config.showMap?($("#uiContent").addClass("hidden"),$("#uiMapWrapper").removeClass("hidden")):($("#uiMapWrapper").addClass("hidden"),$("#uiContent").removeClass("hidden"))),NanoTemplate.templateExists("mapHeader")&&$("#uiMapHeader").html(NanoTemplate.parse("mapHeader",e)),NanoTemplate.templateExists("mapFooter")&&$("#uiMapFooter").html(NanoTemplate.parse("mapFooter",e))}catch(t){return void reportError("ERROR: An error occurred while rendering the UI: "+t.message)}},NanoStateClass.prototype.onAfterUpdate=function(e){NanoStateManager.executeAfterUpdateCallbacks(e)},NanoStateClass.prototype.alertText=function(e){alert(e)};var NanoTemplate=function(){var e={},t={},n={},a={},r=function(){e=$("body").data("templateData"),null==e&&reportError("Error: Template data did not load correctly."),o()},o=function(){var t=Object.size(e);if(!t)return void $(document).trigger("templatesLoaded");for(var n in e)if(e.hasOwnProperty(n))return void $.when($.ajax({url:e[n],cache:!1,dataType:"text"})).done(function(t){t+='
      ';try{NanoTemplate.addTemplate(n,t)}catch(a){return void reportError("ERROR: An error occurred while loading the UI: "+a.message)}delete e[n],o()}).fail(function(){reportError("ERROR: Loading template "+n+"("+e[n]+") failed!")})},i=function(){for(var e in t)try{n[e]=doT.template(t[e],null,t)}catch(a){reportError(a.message)}};return{init:function(){r()},addTemplate:function(e,n){t[e]=n},templateExists:function(e){return t.hasOwnProperty(e)},resetTemplate:function(e){n[e]=null},parse:function(e,r){if(!n.hasOwnProperty(e)||!n[e]){if(!t.hasOwnProperty(e))return reportError('ERROR: Template "'+e+'" does not exist in _compiledTemplates!'),"

      Template error (does not exist)

      ";i()}return"function"!=typeof n[e]?(reportError(n[e]),reportError('ERROR: Template "'+e+'" failed to compile!'),"

      Template error (failed to compile)

      "):n[e].call(this,r.data,r.config,a)},addHelper:function(e,t){return jQuery.isFunction(t)?void(a[e]=t):void reportError("NanoTemplate.addHelper failed to add "+e+" as it is not a function.")},addHelpers:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.addHelper(t,e[t])},removeHelper:function(e){helpers.hasOwnProperty(e)&&delete a[e]}}}();NanoTransition=function(){var e={},t={},n=0;NanoStateManager.addBeforeUpdateCallback("TransitionReset",function(e){return n=0,e});var a=function(e){return"_Hide_Map_close"==e?"transition__map":(void 0===e&&(e=""),"transition__"+n++ +"_"+e.toString())},r=function(n,a,r){var o,i=e[n];void 0===r&&(r=!1);var s=document.getElementsByClassName(n);if(0==s.length)return a;if(s=s[0],i&&i.tagName==s.tagName&&i.tabIndex==s.tabIndex&&i.parent==s.parentNode.tagName&&i.children==s.children.length){if(o=t[n],r){var l={};for(k in o)l[k]=o[k];for(k in a)l[k]=a[k];a=l}}else o=a,e[n]={tagName:s.tagName,tabIndex:s.tabIndex,parent:s.parentNode.tagName,children:s.children.length};return t[n]=a,o},o=function(e,t){var n=$("."+e);return t?$(n).children(t):$(n)},i=function(e,t,n,a,r){var i=o(e,t);void 0===r&&(r=1900),i.css(n).animate(a,{duration:r,queue:!1});var s=n["..class"],l=a["..class"];if(s&&l&&(i.addClass(s),s!=l)){var s=s.split(" "),l=l.split(" "),u=s.filter(function(e){return-1==l.indexOf(e)}),c=l.filter(function(e){return-1==s.indexOf(e)});s=u.join(" "),l=c.join(" "),i.switchClass(s,l,{duration:r,queue:!1})}},s=function(e,t,n,a,r,i){var s=o(e,t);void 0===i&&(i=1900),-1==n?s.text(a.toString()):s.text(a.toFixed(n)),a!=r&&s.animate({i:1},{duration:i,queue:!1,step:function(e,t){-1==n?t.elem.textContent=(a*(1-e)+r*e).toString():t.elem.textContent=(a*(1-e)+r*e).toFixed(n)}})},l=function(e,t,n,a,i){var s=o(e,t);void 0===i&&(i=200),n["..hover"]&&s.addClass("hover"),s.hover(function(){s.stop(1,1).addClass("hover",{duration:i,queue:!1}),r(e,{"..hover":!0},!0)},function(){s.stop(1,1).removeClass("hover",{duration:i,queue:!1}),r(e,{"..hover":!1},!0)})},u=function(e,t,n,a){var o=r(e,n);return i(e,t,o,n,a),o};return{allocID:a,updateElement:r,animateElement:i,animateTextValue:s,animateHover:l,transitionElement:u}}();var NanoWindow=function(){var e,t,n,a,r,o,i=function(e,t){NanoUtility.winset("pos",e+","+t)},s=function(e,t){NanoUtility.winset("size",e+","+t)},l=function(){NanoStateManager.getData().config.user.fancy&&(u(),c(),d(),f())},u=function(){NanoUtility.winset("titlebar",0),NanoUtility.winset("can-resize",0),$(".fancy").show(),$("#uiTitleFluff").css("right","65px")},c=function(){var e=function(){return NanoUtility.close()},t=function(){return NanoUtility.winset("is-minimized","true")};$(".close").on("click",function(t){e()}),$(".minimize").on("click",function(e){t()})},d=function(){$("#uiTitleWrapper").on("mousemove",function(e){p()}),$("#uiTitleWrapper").on("mousedown",function(t){e=!0}),$("#uiTitleWrapper").on("mouseup",function(a){e=!1,t=null,n=null})},p=function(a){var r,o;null==a&&(a=window.event),e&&(null==t&&(t=a.screenX),null==n&&(n=a.screenY),r=a.screenX-t+window.screenLeft,o=a.screenY-n+window.screenTop,i(r,o),t=a.screenX,n=a.screenY)},f=function(){$("#resize").on("mousemove",function(e){v()}),$("#resize").on("mousedown",function(e){a=!0}),$("#resize").on("mouseup",function(e){a=!1})},v=function(){var e,t;null==event&&(event=window.event),a&&(null==r&&(r=event.screenX),null==o&&(o=event.screenY),e=Math.max(150,event.screenX-r+window.innerWidth),t=Math.max(150,event.screenY-o+window.innerHeight),s(e,t),r=event.screenX,o=event.screenY)};return{init:function(){$(document).on("templatesLoaded",function(){l()})}}}(); \ No newline at end of file +function NanoStateDefaultClass(){this.key="default",this.key=this.key.toLowerCase(),NanoStateManager.addState(this)}function NanoStatePDAClass(){this.key="pda",this.key=this.key.toLowerCase(),this.current_template="",NanoStateManager.addState(this)}function NanoStateClass(){}var NanoUtility=function(){var e={};return{init:function(){var t=$("body");e=t.data("urlParameters")},generateHref:function(t){var n="?";for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);for(var a in t)t.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+t[a]);return n},winset:function(e,t,n){var a,r;return null==n&&(n=NanoStateManager.getData().config.window.ref),a={},a[n+"."+e]=t,r=a,location.href=NanoUtility.href("winset",r)},extend:function(e,t){return Object.keys(t).forEach(function(n){var a;return a=t[n],a&&"[object Object]"===Object.prototype.toString.call(a)?(e[n]=e[n]||{},NanoUtility.extend(e[n],a)):e[n]=a}),e},href:function(e,t){return null==e&&(e=""),null==t&&(t={}),e=new Url("byond://"+e),NanoUtility.extend(e.query,t),e},close:function(){var t;return t={command:"nanoclose "+e.src},this.winset("is-visible","false"),location.href=NanoUtility.href("winset",t)}}}();"undefined"==typeof jQuery&&reportError("ERROR: Javascript library failed to load!"),"undefined"==typeof doT&&reportError("ERROR: Template engine failed to load!");var reportError=function(e){window.location="byond://?nano_err="+encodeURIComponent(e),alert(e)};$(document).ready(function(){NanoUtility.init(),NanoStateManager.init(),NanoTemplate.init(),NanoWindow.init()}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),String.prototype.format||(String.prototype.format=function(e){var t=this;return t.replace(String.prototype.format.regex,function(t){var n,a=parseInt(t.substring(1,t.length-1));return n=a>=0?e[a]:-1===a?"{":-2===a?"}":""})},String.prototype.format.regex=new RegExp("{-?[0-9]+}","g")),Object.size=function(e){var t,n=0;for(var t in e)e.hasOwnProperty(t)&&n++;return n},window.console||(window.console={log:function(e){return!1}}),String.prototype.toTitleCase=function(){var e=/^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;return this.replace(/([^\W_]+[^\s-]*) */g,function(t,n,a,r){return a>0&&a+n.length!==r.length&&n.search(e)>-1&&":"!==r.charAt(a-2)&&r.charAt(a-1).search(/[^\s-]/)<0?t.toLowerCase():n.substr(1).search(/[A-Z]|\../)>-1?t:t.charAt(0).toUpperCase()+t.substr(1)})},$.ajaxSetup({cache:!1}),Function.prototype.inheritsFrom=function(e){return this.prototype=new e,this.prototype.constructor=this,this.prototype.parent=e.prototype,this},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.ckey||(String.prototype.ckey=function(){return this.replace(/\W/g,"").toLowerCase()}),NanoStateManager=function(){var e=!1,t=null,n={},a={},r={},o=null,i=function(){t=$("body").data("initialData"),null!=t&&t.hasOwnProperty("config")&&t.hasOwnProperty("data")||reportError("Error: Initial data did not load correctly.");var n="default";t.config.hasOwnProperty("stateKey")&&t.config.stateKey&&(n=t.config.stateKey.toLowerCase()),NanoStateManager.setCurrentState(n),$(document).on("templatesLoaded",function(){s(t),e=!0})},l=function(n){var a;try{a=jQuery.parseJSON(n)}catch(r){return void reportError("recieveUpdateData failed.
      Error name: "+r.name+"
      Error Message: "+r.message)}a.hasOwnProperty("data")||(t&&t.hasOwnProperty("data")?a.data=t.data:a.data={}),e?s(a):t=a},s=function(e){if(null!=o){if(e=o.onBeforeUpdate(e),e===!1)return void reportError("data is false, return");t=e,o.onUpdate(t),o.onAfterUpdate(t)}},c=function(e,t){for(var n in e)e.hasOwnProperty(n)&&jQuery.isFunction(e[n])&&(t=e[n].call(this,t));return t};return{init:function(){i()},receiveUpdateData:function(e){l(e)},addBeforeUpdateCallback:function(e,t){n[e]=t},addBeforeUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addBeforeUpdateCallback(t,e[t])},removeBeforeUpdateCallback:function(e){n.hasOwnProperty(e)&&delete n[e]},executeBeforeUpdateCallbacks:function(e){return c(n,e)},addAfterUpdateCallback:function(e,t){a[e]=t},addAfterUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addAfterUpdateCallback(t,e[t])},removeAfterUpdateCallback:function(e){a.hasOwnProperty(e)&&delete a[e]},executeAfterUpdateCallbacks:function(e){return c(a,e)},addState:function(e){return e instanceof NanoStateClass?e.key?void(r[e.key]=e):void reportError("ERROR: Attempted to add a state with an invalid stateKey"):void reportError("ERROR: Attempted to add a state which is not instanceof NanoStateClass")},setCurrentState:function(e){if("undefined"==typeof e||!e)return reportError("ERROR: No state key was passed!"),!1;if(!r.hasOwnProperty(e))return reportError("ERROR: Attempted to set a current state which does not exist: "+e),!1;var t=o;return o=r[e],null!=t&&t.onRemove(o),o.onAdd(t),!0},getCurrentState:function(){return o},getData:function(){return t}}}(),NanoBaseCallbacks=function(){var e=!0,t={},n={status:function(t){var n;return 2==t.config.status?(n="good",$(".linkActive").removeClass("inactive")):1==t.config.status?(n="average",$(".linkActive").addClass("inactive")):(n="bad",$(".linkActive").addClass("inactive")),$(".statusicon").removeClass("good bad average").addClass(n),$(".linkActive").stopTime("linkPending"),$(".linkActive").removeClass("linkPending"),$(".linkActive").off("click").on("click",function(n){n.preventDefault();var a=$(this).data("href");null!=a&&e&&(e=!1,$("body").oneTime(300,"enableClick",function(){e=!0}),2==t.config.status&&$(this).oneTime(300,"linkPending",function(){$(this).addClass("linkPending")}),window.location.href=a)}),t},nanomap:function(e){return $(".mapIcon").off("mouseenter mouseleave").on("mouseenter",function(e){$("#uiMapTooltip").html($(this).children(".tooltip").html()).show().stopTime().oneTime(5e3,"hideTooltip",function(){$(this).fadeOut(500)})}),$(".zoomLink").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("zoomLevel"),n=$("#uiMap"),a=n.width()*t,r=n.height()*t;n.css({zoom:t,left:"50%",top:"50%",marginLeft:"-"+Math.floor(a/2)+"px",marginTop:"-"+Math.floor(r/2)+"px"})}),$("#uiMapImage").attr("src","nanomap_z"+e.config.mapZLevel+".png"),e}};return{addCallbacks:function(){NanoStateManager.addBeforeUpdateCallbacks(t),NanoStateManager.addAfterUpdateCallbacks(n)},removeCallbacks:function(){for(var e in t)t.hasOwnProperty(e)&&NanoStateManager.removeBeforeUpdateCallback(e);for(var e in n)n.hasOwnProperty(e)&&NanoStateManager.removeAfterUpdateCallback(e)}}}(),NanoBaseHelpers=function(){var e={syndicateMode:function(){return $("body").css("background-color","#8f1414"),$("body").css("background-image","url('uiBackground-Syndicate.png')"),$("body").css("background-position","50% 0"),$("body").css("background-repeat","repeat-x"),$("#uiTitleFluff").css("background-image","url('uiTitleFluff-Syndicate.png')"),$("#uiTitleFluff").css("background-position","50% 50%"),$("#uiTitleFluff").css("background-repeat","no-repeat"),""},combine:function(e,t){return e&&t?e.concat(t):e||t},dump:function(e){return JSON.stringify(e)},link:function(e,t,n,a,r,o){var i="",l="noIcon";"undefined"!=typeof t&&t&&(i='
      ',l="hasIcon"),"undefined"!=typeof r&&r||(r="link");var s="";"undefined"!=typeof o&&o&&(s='id="'+o+'"');var c=NanoTransition.allocID(s+"_"+e.toString().replace(/[^a-z0-9_]/gi,"_")+"_"+t);return"undefined"!=typeof a&&a?'':'
      "+i+e+'
      '},xor:function(e,t){return e^t},precisionRound:function(e,t){if(0==t)return Math.round(number);var n=Math.pow(10,t);return Math.round(e*n)/n},round:function(e){return Math.round(e)},fixed:function(e){return Math.round(10*e)/10},floor:function(e){return Math.floor(e)},ceil:function(e){return Math.ceil(e)},string:function(){if(0==arguments.length)return"";if(1==arguments.length)return arguments[0];if(arguments.length>1){stringArgs=[];for(var e=1;et?t>e?e=t:e>n&&(e=n):e>t?e=t:n>e&&(e=n),"undefined"!=typeof a&&a||(a=""),"undefined"!=typeof r&&r||(r="");var o=Math.round((e-t)/(n-t)*100),i=NanoTransition.allocID(t+"_"+n);return'
      '+r+'
      '},dangerToClass:function(e){return 0==e?"good":1==e?"average":"bad"},dangerToSpan:function(e){return 0==e?'"Good"':1==e?'"Minor Alert"':'"Major Alert"'},generateHref:function(e){var t=$("body");_urlParameters=t.data("urlParameters");var n="?";for(var a in _urlParameters)_urlParameters.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+_urlParameters[a]);for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);return n},displayDNABlocks:function(e,t,n,a,r){if(!e)return'
      Please place a valid subject into the DNA modifier.
      ';var o=e.split(""),i='
      ',l=1,s=1;for(var c in o)if(o.hasOwnProperty(c)&&"object"!=typeof o[c]){var u;u="UI"==r.toUpperCase()?{selectUIBlock:l,selectUISubblock:s}:{selectSEBlock:l,selectSESubblock:s};var d="linkActive";l==t&&s==n&&(d="selected"),i+='",c++,c%a==0&&c
      "):s++}return i+="
      "},cMirror:function(e){CodeMirror.fromTextArea(document.getElementById(e),{lineNumbers:!0,indentUnit:4,indentWithTabs:!0,theme:"lesser-dark"})},smoothNumber:function(e){var t=NanoTransition.allocID("n");return''},smoothRound:function(e,t){var n=NanoTransition.allocID(t);return void 0===t&&(placed=0),''}};return{addHelpers:function(){NanoTemplate.addHelpers(e)},removeHelpers:function(){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.removeHelper(t)}}}(),NanoStateDefaultClass.inheritsFrom(NanoStateClass);var NanoStateDefault=new NanoStateDefaultClass;NanoStatePDAClass.inheritsFrom(NanoStateClass);var NanoStatePDA=new NanoStatePDAClass;NanoStatePDAClass.prototype.onUpdate=function(e){NanoStateClass.prototype.onUpdate.call(this,e);var t=this;try{if(null!=e.data.app){var n=e.data.app.template;null!=n&&n!=t.current_template?$.when($.ajax({url:n+".tmpl",cache:!1,dataType:"text"})).done(function(a){a+='
      ';try{NanoTemplate.addTemplate("app",a),NanoTemplate.resetTemplate("app"),$("#uiApp").html(NanoTemplate.parse("app",e)),t.current_template=n,t.onAfterUpdate(e)}catch(r){return void reportError("ERROR: An error occurred while loading the PDA App UI: "+r.message)}}).fail(function(){reportError("ERROR: Loading template app("+n+") failed!")}):NanoTemplate.templateExists("app")&&$("#uiApp").html(NanoTemplate.parse("app",e))}}catch(a){return void reportError("ERROR: An error occurred while rendering the PDA App UI: "+a.message)}},NanoStateClass.prototype.key=null,NanoStateClass.prototype.layoutRendered=!1,NanoStateClass.prototype.contentRendered=!1,NanoStateClass.prototype.mapInitialised=!1,NanoStateClass.prototype.isCurrent=function(){return NanoStateManager.getCurrentState()==this},NanoStateClass.prototype.onAdd=function(e){NanoBaseCallbacks.addCallbacks(),NanoBaseHelpers.addHelpers()},NanoStateClass.prototype.onRemove=function(e){NanoBaseCallbacks.removeCallbacks(),NanoBaseHelpers.removeHelpers()},NanoStateClass.prototype.onBeforeUpdate=function(e){return e=NanoStateManager.executeBeforeUpdateCallbacks(e)},NanoStateClass.prototype.onUpdate=function(e){try{(!this.layoutRendered||e.config.hasOwnProperty("autoUpdateLayout")&&e.config.autoUpdateLayout)&&($("#uiLayout").html(NanoTemplate.parse("layout",e)),this.layoutRendered=!0),(!this.contentRendered||e.config.hasOwnProperty("autoUpdateContent")&&e.config.autoUpdateContent)&&($("#uiContent").html(NanoTemplate.parse("main",e)),this.contentRendered=!0),NanoTemplate.templateExists("mapContent")&&(this.mapInitialised||($("#uiMap").draggable(),$("#uiMapTooltip").off("click").on("click",function(e){e.preventDefault(),$(this).fadeOut(400)}),this.mapInitialised=!0),$("#uiMapContent").html(NanoTemplate.parse("mapContent",e)),e.config.hasOwnProperty("showMap")&&e.config.showMap?($("#uiContent").addClass("hidden"),$("#uiMapWrapper").removeClass("hidden")):($("#uiMapWrapper").addClass("hidden"),$("#uiContent").removeClass("hidden"))),NanoTemplate.templateExists("mapHeader")&&$("#uiMapHeader").html(NanoTemplate.parse("mapHeader",e)),NanoTemplate.templateExists("mapFooter")&&$("#uiMapFooter").html(NanoTemplate.parse("mapFooter",e))}catch(t){return void reportError("ERROR: An error occurred while rendering the UI: "+t.message)}},NanoStateClass.prototype.onAfterUpdate=function(e){NanoStateManager.executeAfterUpdateCallbacks(e)},NanoStateClass.prototype.alertText=function(e){alert(e)};var NanoTemplate=function(){var e={},t={},n={},a={},r=function(){e=$("body").data("templateData"),null==e&&reportError("Error: Template data did not load correctly."),o()},o=function(){var t=Object.size(e);if(!t)return void $(document).trigger("templatesLoaded");for(var n in e)if(e.hasOwnProperty(n))return void $.when($.ajax({url:e[n],cache:!1,dataType:"text"})).done(function(t){t+='
      ';try{NanoTemplate.addTemplate(n,t)}catch(a){return void reportError("ERROR: An error occurred while loading the UI: "+a.message)}delete e[n],o()}).fail(function(){reportError("ERROR: Loading template "+n+"("+e[n]+") failed!")})},i=function(){for(var e in t)try{n[e]=doT.template(t[e],null,t)}catch(a){reportError(a.message)}};return{init:function(){r()},addTemplate:function(e,n){t[e]=n},templateExists:function(e){return t.hasOwnProperty(e)},resetTemplate:function(e){n[e]=null},parse:function(e,r){if(!n.hasOwnProperty(e)||!n[e]){if(!t.hasOwnProperty(e))return reportError('ERROR: Template "'+e+'" does not exist in _compiledTemplates!'),"

      Template error (does not exist)

      ";i()}return"function"!=typeof n[e]?(reportError(n[e]),reportError('ERROR: Template "'+e+'" failed to compile!'),"

      Template error (failed to compile)

      "):n[e].call(this,r.data,r.config,a)},addHelper:function(e,t){return jQuery.isFunction(t)?void(a[e]=t):void reportError("NanoTemplate.addHelper failed to add "+e+" as it is not a function.")},addHelpers:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.addHelper(t,e[t])},removeHelper:function(e){helpers.hasOwnProperty(e)&&delete a[e]}}}();NanoTransition=function(){var e={},t={},n=0;NanoStateManager.addBeforeUpdateCallback("TransitionReset",function(e){return n=0,e});var a=function(e){return"_Hide_Map_close"==e?"transition__map":(void 0===e&&(e=""),"transition__"+n++ +"_"+e.toString())},r=function(n,a,r){var o,i=e[n];void 0===r&&(r=!1);var l=$("."+n);if(0==l.length)return a;if(l=l[0],i&&i.tagName==l.tagName&&i.tabIndex==l.tabIndex&&i.parent==l.parentNode.tagName&&i.children==l.children.length){if(o=t[n],r){var s={};for(k in o)s[k]=o[k];for(k in a)s[k]=a[k];a=s}}else o=a,e[n]={tagName:l.tagName,tabIndex:l.tabIndex,parent:l.parentNode.tagName,children:l.children.length};return t[n]=a,o},o=function(e,t){var n=$("."+e);return t?$(n).children(t):$(n)},i=function(e,t,n,a,r){var i=o(e,t);void 0===r&&(r=1900),i.css(n).animate(a,{duration:r,queue:!1});var l=n["..class"],s=a["..class"];if(l&&s&&(i.addClass(l),l!=s)){var l=l.split(" "),s=s.split(" "),c=l.filter(function(e){return-1==s.indexOf(e)}),u=s.filter(function(e){return-1==l.indexOf(e)});l=c.join(" "),s=u.join(" "),i.switchClass(l,s,{duration:r,queue:!1})}},l=function(e,t,n,a,r,i){var l=o(e,t);void 0===i&&(i=1900),-1==n?l.text(a.toString()):l.text(a.toFixed(n)),a!=r&&l.animate({i:1},{duration:i,queue:!1,step:function(e,t){-1==n?t.elem.textContent=(a*(1-e)+r*e).toString():t.elem.textContent=(a*(1-e)+r*e).toFixed(n)}})},s=function(e,t,n,a,i){var l=o(e,t);void 0===i&&(i=200),n["..hover"]&&l.addClass("hover"),l.hover(function(){l.stop(1,1).addClass("hover",{duration:i,queue:!1}),r(e,{"..hover":!0},!0)},function(){l.stop(1,1).removeClass("hover",{duration:i,queue:!1}),r(e,{"..hover":!1},!0)})},c=function(e,t,n,a){var o=r(e,n);return i(e,t,o,n,a),o};return{allocID:a,updateElement:r,animateElement:i,animateTextValue:l,animateHover:s,transitionElement:c}}();var NanoWindow=function(){var e,t,n,a,r,o,i=function(e,t){NanoUtility.winset("pos",e+","+t)},l=function(e,t){NanoUtility.winset("size",e+","+t)},s=function(){NanoStateManager.getData().config.user.fancy&&(c(),u(),d())},c=function(){NanoUtility.winset("titlebar",0),NanoUtility.winset("can-resize",0),$(".fancy").show(),$("#uiTitleFluff").css("right","65px")},u=function(){var e=function(){return NanoUtility.close()},t=function(){return NanoUtility.winset("is-minimized","true")};$(".close").on("click",function(t){e()}),$(".minimize").on("click",function(e){t()})},d=function(){$(document).on("mousemove",function(e){p(),f()}),$(document).on("mouseup",function(i){e&&(e=!1,t=null,n=null),a&&(a=!1,r=null,o=null)}),$("#uiTitleWrapper").on("mousedown",function(t){e=!0}),$("#resize").on("mousedown",function(e){a=!0})},p=function(a){var r,o;null==a&&(a=window.event),e&&(null==t&&(t=a.screenX),null==n&&(n=a.screenY),r=a.screenX-t+window.screenLeft,o=a.screenY-n+window.screenTop,i(r,o),t=a.screenX,n=a.screenY)},f=function(){var e,t;null==event&&(event=window.event),a&&(null==r&&(r=event.screenX),null==o&&(o=event.screenY),e=Math.max(150,event.screenX-r+window.innerWidth),t=Math.max(150,event.screenY-o+window.innerHeight),l(e,t),r=event.screenX,o=event.screenY)};return{init:function(){$(document).on("templatesLoaded",function(){s()})}}}(); \ No newline at end of file diff --git a/nano/scripts/nano/nano_transition.js b/nano/scripts/nano/nano_transition.js index d40d9575bf3..ab124cc75f7 100644 --- a/nano/scripts/nano/nano_transition.js +++ b/nano/scripts/nano/nano_transition.js @@ -26,7 +26,7 @@ NanoTransition = function() { if(merge === undefined) merge = false; - var element = document.getElementsByClassName(id); + var element = $("." + id); if(element.length == 0) return newState; diff --git a/nano/scripts/nano/nano_window.js b/nano/scripts/nano/nano_window.js index 69be989b558..b3e74ac87c7 100644 --- a/nano/scripts/nano/nano_window.js +++ b/nano/scripts/nano/nano_window.js @@ -11,8 +11,7 @@ var NanoWindow = function () if(NanoStateManager.getData().config.user.fancy) { fancyChrome(); attachButtons(); - attachDrag(); - attachResize(); + attachDragAndResize(); } }; var fancyChrome = function() { @@ -35,20 +34,32 @@ var NanoWindow = function () minimize(); }); }; - var dragging, xDrag, yDrag; - var attachDrag = function() { - $("#uiTitleWrapper").on("mousemove", function (event) { + var attachDragAndResize = function() { + $(document).on("mousemove", function (event) { drag(); + resize(); + }); + + $(document).on("mouseup", function (event) { + if(dragging) { + dragging = false; + xDrag = null; + yDrag = null; + } + if(resizing) { + resizing = false; + xResize = null; + yResize = null; + } }); $("#uiTitleWrapper").on("mousedown", function (event) { dragging = true; }); - $("#uiTitleWrapper").on("mouseup", function (event) { - dragging = false; - xDrag = null; - yDrag = null; + $("#resize").on("mousedown", function (event) { + resizing = true; }); }; + var dragging, xDrag, yDrag; var drag = function(event) { var x, y; if (event == null) { @@ -75,17 +86,6 @@ var NanoWindow = function () yDrag = event.screenY; }; var resizing, xResize, yResize; - var attachResize = function () { - $("#resize").on("mousemove", function (event) { - resize(); - }); - $("#resize").on("mousedown", function (event) { - resizing = true; - }); - $("#resize").on("mouseup", function (event) { - resizing = false; - }); - }; var resize = function() { var x, y; if (event == null) { diff --git a/nano/templates/chem_dispenser.tmpl b/nano/templates/chem_dispenser.tmpl index dc2dd687d9f..cec3028652e 100644 --- a/nano/templates/chem_dispenser.tmpl +++ b/nano/templates/chem_dispenser.tmpl @@ -61,7 +61,7 @@ Used In File(s): \code\modules\reagents\Chemistry-Machinery.dm {{if data.beakerCurrentVolume}} Dispose: {{/if}} - Volume: {{:helper.smoothRound(data.beakerCurrentVolume)}} / {{:data.beakerMaxVolume}}
      + Volume: {{:data.beakerCurrentVolume}} / {{:data.beakerMaxVolume}}
      {{for data.beakerContents}}
      diff --git a/nano/templates/comm_console.tmpl b/nano/templates/comm_console.tmpl index f5e8578ea79..209ae5f0ee8 100644 --- a/nano/templates/comm_console.tmpl +++ b/nano/templates/comm_console.tmpl @@ -68,6 +68,11 @@ Used In File(s): /code/game/machinery/computers/communications.dm
      {{:helper.link('Message List','comment',{'operation':'messagelist'})}}
      + {{if data.dock_request}} +
      + {{:helper.link('Accept Docking Request','signal',{'operation':'AcceptDocking'})}} + {{:helper.link('Deny Docking Request','signal',{'operation':'DenyDocking'})}} + {{/if}}
      {{else data.screen==2}} diff --git a/nano/templates/order_console.tmpl b/nano/templates/order_console.tmpl index d89fe4e27a3..271e35c525a 100644 --- a/nano/templates/order_console.tmpl +++ b/nano/templates/order_console.tmpl @@ -4,7 +4,7 @@ Used In File(s): \code\game\supplyshuttle.dm -->