diff --git a/_maps/map_files/RandomZLevels/undergroundoutpost45.dmm b/_maps/map_files/RandomZLevels/undergroundoutpost45.dmm index 2ecba55d33a..c86a593a1ca 100644 --- a/_maps/map_files/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/map_files/RandomZLevels/undergroundoutpost45.dmm @@ -856,7 +856,7 @@ "qx" = (/obj/machinery/light/small{dir = 8},/obj/machinery/alarm/monitor{dir = 4; frequency = 1439; locked = 0; pixel_x = -23; pixel_y = 0; req_access = null},/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a2{has_gravity = 1; name = "UO45 Crew Quarters"}) "qy" = (/obj/structure/sink{dir = 4; icon_state = "sink"; pixel_x = 11; pixel_y = 0},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "freezerfloor"},/area/awaycontent/a2{has_gravity = 1; name = "UO45 Crew Quarters"}) "qz" = (/obj/structure/disposalpipe/segment,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating{heat_capacity = 1e+006},/area/awaycontent/a2{has_gravity = 1; name = "UO45 Crew Quarters"}) -"qA" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 173.4; heat_capacity = 1e+006; name = "Cave Floor"; nitrogen = 135.1; oxygen = 0; temperature = 363.9; toxins = 229.8},/area/awaycontent/a7{always_unpowered = 1; has_gravity = 1; name = "UO45 Caves"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0}) +"qA" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 4},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 173.4; heat_capacity = 1e+006; name = "Cave Floor"; nitrogen = 135.1; oxygen = 0; temperature = 363.9; toxins = 229.8},/area/awaycontent/a3{has_gravity = 1; name = "UO45 Engineering"}) "qB" = (/obj/machinery/atmospherics/pipe/manifold/hidden/purple{dir = 1},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 173.4; heat_capacity = 1e+006; name = "Cave Floor"; nitrogen = 135.1; oxygen = 0; temperature = 363.9; toxins = 229.8},/area/awaycontent/a7{always_unpowered = 1; has_gravity = 1; name = "UO45 Caves"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0}) "qC" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 9},/turf/simulated/floor/plating/airless/asteroid{carbon_dioxide = 173.4; heat_capacity = 1e+006; name = "Cave Floor"; nitrogen = 135.1; oxygen = 0; temperature = 363.9; toxins = 229.8},/area/awaycontent/a7{always_unpowered = 1; has_gravity = 1; name = "UO45 Caves"; power_environ = 0; power_equip = 0; power_light = 0; poweralm = 0}) "qD" = (/obj/machinery/vending/cola,/turf/simulated/floor{heat_capacity = 1e+006; icon_state = "dark"},/area/awaycontent/a3{has_gravity = 1; name = "UO45 Engineering"}) diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 484eab2b868..fe596449bdc 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{icon_state = "red"; dir = 8},/area/security/permabrig) "aes" = (/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{dir = 8; icon_state = "vault"; tag = "icon-vault (WEST)"},/area/security/securearmoury) -"aet" = (/obj/machinery/hologram/holopad,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) +"aet" = (/obj/structure/rack,/obj/item/key/security,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "aeu" = (/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{dir = 8; icon_state = "vault"; tag = "icon-vault (WEST)"},/area/security/securearmoury) "aev" = (/obj/structure/table/woodentable,/obj/machinery/photocopier/faxmachine{department = "Head of Security's Office"},/turf/simulated/floor{icon_state = "dark"},/area/security/hos) "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) @@ -242,7 +242,7 @@ "aeH" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/light/small,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{dir = 4; name = "Interrogation Observation APC"; pixel_x = 26; pixel_y = 0},/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/security/interrogationobs) "aeI" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/power/apc{cell_type = 5000; dir = 8; name = "Armory APC"; pixel_x = -24; pixel_y = 0},/obj/machinery/camera/motion{c_tag = "Secure Armory"; dir = 4; network = list("SS13")},/obj/machinery/light_switch{pixel_x = -25; pixel_y = -10},/obj/effect/decal/warning_stripes/southwest,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "aeJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/warning_stripes/southwestcorner,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) -"aeK" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) +"aeK" = (/obj/structure/stool/bed/chair/janicart/secway,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "aeL" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/decal/warning_stripes/southeastcorner,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "aeM" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/effect/decal/warning_stripes/southeast,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "aeN" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/light_switch{pixel_x = -25},/turf/simulated/floor{icon_state = "dark"},/area/security/hos) @@ -699,7 +699,7 @@ "anw" = (/obj/structure/grille,/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/obj/structure/shuttle/window,/turf/simulated/floor/plating,/area/shuttle/siberia/station) "anx" = (/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia/station) "any" = (/obj/machinery/flasher_button{id = "gulagshuttleflasher"; name = "Flash Control"; pixel_x = 0; pixel_y = -26; req_access_txt = "1"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia/station) -"anz" = (/obj/machinery/mineral/labor_claim_console{machinedir = 2; pixel_x = 30; pixel_y = 30},/obj/machinery/mineral/output,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia/station) +"anz" = (/obj/machinery/mineral/labor_claim_console{machinedir = 2; pixel_x = 30; pixel_y = 30},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia/station) "anA" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "labor_shuttle_hatch"; locked = 1; name = "Shuttle Hatch"; req_access = null; req_access_txt = "2"},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/siberia/station) "anB" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "labor_dock_north_outer"; locked = 1; name = "Labor Camp Airlock"; req_access_txt = "2"},/turf/simulated/floor/plating,/area/security/prisonershuttle) "anC" = (/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 2; frequency = 1379; id_tag = "labor_dock_north_pump"},/turf/simulated/floor/plating,/area/security/prisonershuttle) @@ -754,7 +754,7 @@ "aoz" = (/obj/structure/grille,/obj/structure/window/full/shuttle,/turf/simulated/shuttle/plating,/area/shuttle/escape_pod3/station) "aoA" = (/obj/machinery/door/airlock/external{name = "Labor Shuttle Airlock"; req_access_txt = "2"},/turf/simulated/shuttle/floor{icon = 'icons/turf/floors.dmi'; icon_state = "dark"},/area/shuttle/siberia/station) "aoB" = (/turf/simulated/shuttle/wall,/area/shuttle/siberia/station) -"aoC" = (/obj/machinery/mineral/stacking_machine/laborstacker,/turf/simulated/shuttle/floor{icon = 'icons/turf/floors.dmi'; icon_state = "dark"},/area/shuttle/siberia/station) +"aoC" = (/obj/machinery/mineral/stacking_machine/laborstacker{input_dir = 2; output_dir = 1},/turf/simulated/shuttle/floor{icon = 'icons/turf/floors.dmi'; icon_state = "dark"},/area/shuttle/siberia/station) "aoD" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden{dir = 5; icon_state = "intact"},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/security/prisonershuttle) "aoE" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/security/prisonershuttle) "aoF" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/manifold/hidden{dir = 1},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/security/prisonershuttle) @@ -798,7 +798,7 @@ "apr" = (/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,/area/space) "aps" = (/turf/space,/area/shuttle/syndicate_elite/station) "apt" = (/turf/simulated/shuttle/floor,/area/shuttle/siberia/station) -"apu" = (/obj/machinery/mineral/labor_claim_console{machinedir = 1; pixel_x = 30; pixel_y = 0},/obj/machinery/mineral/input,/turf/simulated/shuttle/floor,/area/shuttle/siberia/station) +"apu" = (/obj/machinery/mineral/labor_claim_console{machinedir = 1; pixel_x = 30; pixel_y = 0},/turf/simulated/shuttle/floor,/area/shuttle/siberia/station) "apv" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/wall/r_wall,/area/security/prisonershuttle) "apw" = (/turf/simulated/wall/r_wall,/area/security/prisonershuttle) "apx" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating,/area/security/prisonershuttle) @@ -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,/area/crew_quarters/heads) "bPe" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall/r_wall,/area/server) -"bPf" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/server) +"bPf" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/hologram/holopad,/turf/simulated/floor{icon_state = "dark"},/area/security/securearmoury) "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{tag = "icon-vault"; icon_state = "vault"},/area/engine/gravitygenerator) "bPi" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/hallway/primary/central/sw) @@ -5046,7 +5046,7 @@ "bTb" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bTc" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bTd" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/photocopier,/turf/simulated/floor{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) -"bTe" = (/obj/machinery/atmospherics/unary/outlet_injector/on,/turf/simulated/floor/plating/airless,/area/space) +"bTe" = (/obj/machinery/atmospherics/unary/outlet_injector/on,/turf/simulated/floor/plating/airless,/area/toxins/mixing) "bTf" = (/turf/simulated/shuttle/wall{icon_state = "swall_s6"; dir = 2},/area/shuttle/mining/station) "bTg" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/mining/station) "bTh" = (/obj/structure/window/full/shuttle,/obj/structure/grille,/turf/simulated/shuttle/plating,/area/shuttle/mining/station) @@ -5105,7 +5105,7 @@ "bUi" = (/obj/machinery/r_n_d/server/core,/obj/machinery/atmospherics/pipe/simple/heat_exchanging{tag = "icon-intact (NORTHEAST)"; icon_state = "intact"; dir = 5},/turf/simulated/floor/bluegrid{name = "Server Base"; nitrogen = 250; oxygen = 0; temperature = 0},/area/toxins/server_coldroom) "bUj" = (/obj/machinery/atmospherics/pipe/simple/heat_exchanging{dir = 4},/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/bluegrid{name = "Server Base"; nitrogen = 250; oxygen = 0; temperature = 0},/area/toxins/server_coldroom) "bUk" = (/obj/machinery/atmospherics/pipe/simple/heat_exchanging{dir = 9},/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Server Walkway"; nitrogen = 250; oxygen = 0; temperature = 0},/area/toxins/server_coldroom) -"bUl" = (/obj/effect/spawner/window/reinforced,/obj/structure/sign/securearea{desc = "A warning sign which reads 'SERVER ROOM'."; name = "SERVER ROOM"; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 4},/turf/simulated/floor/plating,/area/toxins/server) +"bUl" = (/obj/effect/spawner/window/reinforced,/obj/structure/sign/securearea{desc = "A warning sign which reads 'SERVER ROOM'."; name = "SERVER ROOM"; pixel_y = -32},/turf/simulated/floor/plating,/area/toxins/server) "bUm" = (/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/turf/simulated/floor{icon_state = "dark"},/area/toxins/server) "bUn" = (/obj/machinery/computer/rdservercontrol,/obj/machinery/light_switch{pixel_y = -23},/turf/simulated/floor{icon_state = "dark"},/area/toxins/server) "bUo" = (/obj/machinery/computer/message_monitor,/turf/simulated/floor{icon_state = "dark"},/area/toxins/server) @@ -5237,8 +5237,8 @@ "bWK" = (/obj/machinery/door/airlock/glass{name = "Central Access"},/turf/simulated/floor{dir = 2; icon_state = "yellowcorner"},/area/hallway/primary/aft) "bWL" = (/obj/structure/closet/jcloset,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/obj/item/device/radio/intercom{broadcasting = 0; name = "station intercom (General)"; pixel_y = 25},/turf/simulated/floor,/area/janitor) "bWM" = (/obj/structure/closet/l3closet/janitor,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/machinery/alarm{frequency = 1439; pixel_y = 23},/turf/simulated/floor,/area/janitor) -"bWN" = (/obj/item/weapon/storage/box/lights/mixed,/obj/item/weapon/storage/box/lights/mixed,/obj/machinery/camera{c_tag = "Custodial Closet"; network = list("SS13")},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor,/area/janitor) -"bWO" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{level = 1},/obj/machinery/newscaster{pixel_y = 30},/turf/simulated/floor,/area/janitor) +"bWN" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{level = 1},/obj/machinery/newscaster{pixel_y = 30},/obj/item/weapon/storage/box/lights/mixed,/obj/item/weapon/storage/box/lights/mixed,/turf/simulated/floor,/area/janitor) +"bWO" = (/obj/machinery/camera{c_tag = "Custodial Closet"; network = list("SS13")},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/stool/bed/chair/janicart,/turf/simulated/floor,/area/janitor) "bWP" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor,/area/janitor) "bWQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/reagent_dispensers/spacecleanertank{pixel_y = 30},/turf/simulated/floor,/area/janitor) "bWR" = (/obj/machinery/door/window/westleft{name = "Janitoral Delivery"; req_access_txt = "26"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor{icon_state = "delivery"},/area/janitor) @@ -5395,7 +5395,7 @@ "bZM" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment,/turf/simulated/floor{dir = 8; icon_state = "cautioncorner"},/area/hallway/primary/aft) "bZN" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor,/area/hallway/primary/aft) "bZO" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/turf/simulated/floor{dir = 2; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"bZP" = (/obj/structure/table,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/machinery/requests_console{department = "Janitorial"; name = "Janitor Requests Console"; departmentType = 1; pixel_y = -29},/obj/item/weapon/reagent_containers/spray/cleaner,/turf/simulated/floor,/area/janitor) +"bZP" = (/obj/structure/table,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/item/weapon/grenade/chem_grenade/cleaner,/obj/machinery/requests_console{department = "Janitorial"; name = "Janitor Requests Console"; departmentType = 1; pixel_y = -29},/obj/item/weapon/reagent_containers/spray/cleaner,/obj/item/key/janitor,/turf/simulated/floor,/area/janitor) "bZQ" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor,/area/janitor) "bZR" = (/obj/machinery/light,/obj/structure/janitorialcart,/turf/simulated/floor,/area/janitor) "bZS" = (/obj/item/weapon/restraints/legcuffs/beartrap,/obj/item/weapon/restraints/legcuffs/beartrap,/obj/item/weapon/storage/box/mousetraps,/obj/item/weapon/storage/box/mousetraps,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor,/area/janitor) @@ -6696,10 +6696,10 @@ "cyN" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cyO" = (/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint) "cyP" = (/obj/structure/disposalpipe/segment,/obj/machinery/light/small{dir = 4},/turf/simulated/floor/engine,/area/toxins/xenobiology) -"cyQ" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) +"cyQ" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/medical/virology) "cyR" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Monkey Pen"; req_access_txt = "39"},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) -"cyS" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) -"cyT" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) +"cyS" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/medical/virology) +"cyT" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/medical/virology) "cyU" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/wall/r_wall,/area/medical/surgery) "cyV" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cyW" = (/obj/structure/flora/kirbyplants,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) @@ -6767,7 +6767,7 @@ "cAg" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/engine,/area/toxins/test_chamber) "cAh" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/asmaint) "cAi" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{dir = 1; icon_state = "whitegreen"},/area/toxins/xenobiology) -"cAj" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 8},/turf/simulated/floor/plating/airless,/area/space) +"cAj" = (/obj/machinery/atmospherics/unary/outlet_injector/on,/turf/simulated/floor/plating/airless,/area/maintenance/incinerator) "cAk" = (/turf/simulated/floor/plating/airless,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating/airless/catwalk{tag = "icon-catwalk3"; icon_state = "catwalk3"},/area/solar/port) "cAl" = (/obj/item/weapon/pen,/turf/simulated/floor{icon_state = "floorgrime"},/area/assembly/assembly_line) "cAm" = (/obj/machinery/atmospherics/unary/vent_pump{on = 0},/turf/simulated/floor{icon_state = "floorgrime"},/area/assembly/assembly_line) @@ -6965,12 +6965,12 @@ "cDW" = (/obj/machinery/disease2/incubator{name = "Pathogenic incubator"},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cDX" = (/obj/structure/stool/bed/chair/office/light{dir = 4},/obj/effect/landmark/start{name = "Virologist"},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cDY" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) -"cDZ" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) +"cDZ" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/medical/virology) "cEa" = (/obj/structure/table,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEb" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEc" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEd" = (/obj/structure/rack{dir = 1},/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint2) -"cEe" = (/obj/structure/table/glass,/obj/structure/reagent_dispensers/virusfood{pixel_x = -30},/obj/item/weapon/reagent_containers/syringe/antiviral,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/dropper/precision,/obj/item/weapon/reagent_containers/spray/cleaner,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) +"cEe" = (/obj/structure/table/glass,/obj/structure/reagent_dispensers/virusfood{pixel_x = -30},/obj/item/weapon/reagent_containers/syringe/antiviral,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/dropper/precision,/obj/item/weapon/reagent_containers/spray/cleaner,/obj/item/weapon/storage/fancy/vials,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEf" = (/obj/structure/table,/obj/item/weapon/storage/lockbox/vials,/obj/item/weapon/hand_labeler{pixel_x = -3; pixel_y = -3},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEg" = (/obj/structure/closet/secure_closet/personal/patient,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cEh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/asmaint) @@ -7210,7 +7210,7 @@ "cIH" = (/obj/machinery/alarm{pixel_y = 25; target_temperature = 283.15},/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cII" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/item/device/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/turf/simulated/floor{dir = 10; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTHEAST)"},/area/medical/virology) "cIJ" = (/obj/structure/flora/kirbyplants,/obj/item/device/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) -"cIK" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/space) +"cIK" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/toxins/test_chamber) "cIL" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/binary/valve/digital{color = ""; dir = 4; name = "Gas Mix Outlet Valve"},/turf/simulated/floor,/area/atmos/distribution) "cIM" = (/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/machinery/atmospherics/pipe/manifold/visible/yellow,/turf/simulated/floor{dir = 5; icon_state = "green"},/area/atmos/distribution) "cIN" = (/obj/machinery/iv_drip,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) @@ -8004,7 +8004,7 @@ "cXV" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor,/area/aisat/maintenance) "cXW" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/obj/machinery/light_switch{pixel_x = 27},/turf/simulated/floor,/area/aisat/maintenance) "cXX" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/aisat/maintenance) -"cXY" = (/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/unary/outlet_injector{dir = 8; frequency = 1443; icon_state = "on"; id = "air_in"; on = 1},/turf/simulated/floor/plating,/area/space) +"cXY" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 8},/turf/simulated/floor/plating/airless,/area/toxins/xenobiology) "cXZ" = (/obj/structure/lattice,/obj/structure/window/reinforced{dir = 1},/turf/space,/area/space) "cYa" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 1},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor{dir = 10; icon_state = "yellow"},/area/aisat/maintenance) "cYb" = (/obj/structure/table,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/glass{amount = 50; pixel_x = 3; pixel_y = 3},/turf/simulated/floor{dir = 2; icon_state = "yellow"},/area/aisat/maintenance) @@ -8217,6 +8217,7 @@ "dca" = (/obj/structure/table/glass,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1},/obj/machinery/door_control{id = "medprivacyc"; name = "Privacy Shutters"; pixel_y = -30},/turf/simulated/floor{dir = 6; icon_state = "whitered"},/area/medical/patient_c) "dcb" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor{dir = 8; icon_state = "bluecorner"},/area/medical/patients_rooms) "dcc" = (/obj/machinery/light,/obj/structure/flora/kirbyplants,/turf/simulated/floor{dir = 10; icon_state = "blue"},/area/medical/patients_rooms) +"dcd" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/maintenance/turbine) "dce" = (/obj/machinery/light_switch{pixel_x = -24; pixel_y = 4},/turf/simulated/floor{icon_state = "blue"; dir = 8},/area/medical/patients_rooms) "dcf" = (/obj/machinery/power/apc{dir = 4; cell_type = 15000; name = "east bump"; pixel_x = 24},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor{dir = 4; icon_state = "blue"},/area/medical/patients_rooms) "dcg" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor,/area/medical/patients_rooms) @@ -8232,6 +8233,8 @@ "dcq" = (/obj/effect/decal/warning_stripes/south,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor{dir = 0; icon_state = "blue"},/area/medical/patients_rooms) "dcr" = (/obj/structure/closet/l3closet,/obj/machinery/light{dir = 4},/obj/item/clothing/mask/gas,/turf/simulated/floor{dir = 4; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTH)"},/area/medical/virology) "dcs" = (/obj/structure/closet/l3closet,/obj/item/clothing/mask/gas,/turf/simulated/floor{dir = 6; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTHEAST)"},/area/medical/virology) +"dct" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/maintenance/asmaint) +"dcu" = (/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/unary/outlet_injector{dir = 8; frequency = 1443; icon_state = "on"; id = "air_in"; on = 1},/turf/simulated/floor/plating,/area/aisat/maintenance) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8298,9 +8301,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacgacNacOacPacQacRacSacCaalacEacEacTacUacVacEacEacEaaaaaaaaaaaaabKacGactacWacXacYacXacXacZactadaadaadaadaadaadaabLadbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajaajaajaajaajaaaaajaajaajaajaajaaaaajaajaajaajaajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacgacgacgacgacgacgadcaddacEacEadeadfadgadhadiacEacEaaaaaaaaaaaaaaaabKactadjadkadladmadnadoactadpadqadradsadtaduadvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajaajaajaajaajaaaaajaajaajaajaajaaaaajaajaajaajaajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadwadxadyadzadAadwadBadCacEadDadEadFadGadHadIadJacEaaaaaaaaaaaaaaaaaaactadKadLadMadNacXadOactadPadtadtadtadtaduadvaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajaajaajaajaajaaaaaaaaaaaaaaaaaaaaaaajaajaajaajaajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadQadQadQadQadQadRadSadTadUadwachacdacEadVadWadXadGadYadZaeaacEaaaaaaaaaaaaaaaaebactaecaedaeeaefaegaehactaeiadtaejadtadtaduadvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAaaaaaaabAabAabAabAabAabAabAaaaaaaabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadQaekaelaemadQaenaeoaepaepaeqaeracCacEaesadWadXaetadYadZaeuacEaaaaaaaaaaaaaaaaaaactaevadLaewadNacXaexactaeyadtadtadtadtaezadvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeAaeAaeAaeAaeAaeAaeAaeAaeAaaaadQaeBaeCaeDaeEaeFaeGaeFaeHaeqacSacCacEacEaeIaeJaeKaeLaeMacEacEaaaaaaaaaaaaaaaaaaactaeNaeOaePacXaeQaeRactaeSaeTaeUaeUaeVadaabLabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadQadQadQadQadQadRadSadTadUadwachacdacEadVadWadXaetadYadZaeaacEaaaaaaaaaaaaaaaaebactaecaedaeeaefaegaehactaeiadtaejadtadtaduadvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAaaaaaaabAabAabAabAabAabAabAaaaaaaabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadQaekaelaemadQaenaeoaepaepaeqaeracCacEaesadWadXaeKadYadZaeuacEaaaaaaaaaaaaaaaaaaactaevadLaewadNacXaexactaeyadtadtadtadtaezadvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJaaJaaJaaJaaJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeAaeAaeAaeAaeAaeAaeAaeAaeAaaaadQaeBaeCaeDaeEaeFaeGaeFaeHaeqacSacCacEacEaeIaeJbPfaeLaeMacEacEaaaaaaaaaaaaaaaaaaactaeNaeOaePacXaeQaeRactaeSaeTaeUaeUaeVadaabLabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeAaeWaeXaeYaeAaeZaeXafaaeAaaaadQafbafcafdadQadwafeadwadwadwaffafgaalacEafhafiafjafkaflacEafmafmafmafmafmafmafmactafnafoafpafqafractactafsaftafuafuafwadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafxafxafxacGacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeAafyafzafAaeAafyafzafAaeAaaaadQafBafCafDafEafFafGafHafIafJafKafLafMacEacEafNafOafPacEacEafmafQafRafSafTafUafVafWafXafYafZagaagaagbagcagdageagfaggaghadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaafxaaaaabaaaagiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeAagjafAagkaeAaglafAagmaeAaaaadQadQadQadQadQagnagoagpagqagragsagtaguagvagwagxagyagzagAagBagCagDagEagFagFagFagGagHagIagJagFagFagFagFagKafuagLagMagNagOagPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagQaabagRaabagQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAabAabAabAabAabAabAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8375,12 +8378,12 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbF aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQbFnbBRbBRbKnbAebFqbAebAebAebAebAebyvbAfbICbKobngbKpbpIbKqbKrbpIbKsbpHbpIbpIbKtbtLbDXbvvbIIbHlbHmbCpbKubKvbKwbKxbKybKzbKAbKBbKCbKDbwXbKEbKFbwXbwYbwYbKGbHybKHbKIbKJbKKbKLbKLbKMbKNbKObvvbKPbucbEybKQbEubKRbKSbEybJkbKTbKUbKVbKWbKXbKYbKUbJkbKZbLabLbbLbbLbbLcbLbbLdbLdbLebLfbLgbLhbLhbLibLgbLgbLhbLhbLjbLkbLjbLjbxGbxGbxGbxGbxGbLlbLmbBobxGbLnbLobLpbLqbLqbLrbLsbLtbLubLvbLwbLxbLybLzbLAbLAbLBbJVbLCbEXbLDbLDbLDbLEbEXbLFaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabmObmObmObmObmObmObmObmObmOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQbIzbIAbIzbFobLGbLHbAebAebAebLGbAebyvbAfbICbLIbngbLJbpIbAibFvbpIbnmbLKbpIbpIbLLbtLbDXbvvbLMbHlbLNbCpbLObLPbLQbLRbLSbKzbLTbLUbLVbLWbLXbLYbLZbMaaaaaaaaaabHybMbbMcbMdbMdbMebMfbMgbHybMhbMibFXbMjbMkbMlbMmbMnbMobMpbMqbJlbMrbMsbMtbMubMvbMrbJkbKZbMwbMxbMybMzbMAbMBbLdbMCbMDbMEbLgbMFbMGbMHbMIbMJbMKbMLbKabMMbLqbLqbMNbMObLqbMPbMQbMRbMSbMTbLqbMUbMVbMWbMXbMYbMZbNabNbbNabNabNabIwbEXbEXbIxbIxbEXbNcbNdbNebNfbNgbNhbNibLDaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQbNjbNkbNjbNlbNmbNnbNnbNnbNnbNnbNobNpbNqbICbNrbngbNsbNtbNubNvbNwbNxbNybNybNybNzbNzbNAbvvbNBbNCbHmbCpbNDbNEbNFbKvbNGbKzbNHbNIbNJbNKbNLbFNbNMbMaaaaaaaaaabHybNNbNObNPbNQbMebMfbMgbHybNRbNSbNTbNUbNVbNWbNXbNYbNZbOabObbOcbKUbKUbOdbOebKUbKUbJkbKZbOfbOgbOhbOibOjbOkbLdbOlbOmbOnbOobOpbOqbOrbOrbOsbOtbOubOvbOwbJVbJVbOxbJVbOybJVbOzbJVbOAbOBbOBbOCbODbOEbOFbOGbOHbOIbOJbOKbOLbNabOMbONaaaaaaaaabEXbOObOPbOQbORbOSbOTbOUbEXaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQbFnbBRbBRbngbngbBRbBRbBRbBRbBRbngbngbBRbBRbBRbngbOVbOVbOVbOWbOVbNzbOXbOYbOZbPabNzbDXbvvbPbbPcbPcbCpbCpbCpbCpbCpbPdbKzbISbIRbPebPfbPgbPhbMabMabvjbvjbvjbHybHzbHybHybHybHybHybHybHybPibvvbPjbPkbPlbPmbPnbPlbPlbPobPpbPqbPrbPsbPtbPubPvbPwbMqbPxbPybPzbPAbPBbPCbPDbPEbPFbPGbPHbPIbPJbPKbPLbMHbPMbLhbLhbPNbPObPNbPPbPQbPPbPPbPPbPRbPSbPTbPTbPUbPVbPWbPXbOFbPYbPZbQabQbbQcbQdbNabOMbONaaaaaaaaabEXbQebQfbEXbKjbEXbEXbKjbEXaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQbFnbBRbBRbngbngbBRbBRbBRbBRbBRbngbngbBRbBRbBRbngbOVbOVbOVbOWbOVbNzbOXbOYbOZbPabNzbDXbvvbPbbPcbPcbCpbCpbCpbCpbCpbPdbKzbISbIRbPebNKbPgbPhbMabMabvjbvjbvjbHybHzbHybHybHybHybHybHybHybPibvvbPjbPkbPlbPmbPnbPlbPlbPobPpbPqbPrbPsbPtbPubPvbPwbMqbPxbPybPzbPAbPBbPCbPDbPEbPFbPGbPHbPIbPJbPKbPLbMHbPMbLhbLhbPNbPObPNbPPbPQbPPbPPbPPbPRbPSbPTbPTbPUbPVbPWbPXbOFbPYbPZbQabQbbQcbQdbNabOMbONaaaaaaaaabEXbQebQfbEXbKjbEXbEXbKjbEXaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabQgaabaaaaaaaaaaaabOVbQhbQibQjbQkbNzbQlbQmbQnbQobNzbDXbvvbQpbQqbQrbQsbQtbQubQvbQwbQxbQybQzbQAbQBbQCbQDbQEbQFbQGbQHbQIbQJbQKbQLbQMbQNbubbQObvvbQPbQQbQRbvvbQSbPlbQTbQUbQVbQWbQXbJkbQYbQZbRabRbbRcbRdbRebRfbRgbRhbRibLbbRjbOibRkbRlbRmbRnbRobRpbLgbRqbMHbMHbMHbRrbLhbPNbRsbRtbRubRvbRwbRxbRybPPbRzbRAbRBbPTbPTbRCbPWbRDbREbRFbRGbRHbRIbRJbRKbNabRLbwoaaaaaaaaabEXbEXbEXbEXaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQbBQbBQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOVbRMbRNbRObRPbNybRQbRRbRSbRTbNzbDXbRUbRVbvvbvvbFXbRWbubbQNbQMbRXbRYbRXbRZbSabSabSbbScbSdbSabSabSebSabSfbSabQMbQNbubbSgbShbSibSjbSkbSlbvvbPlbSmbQUbSnbSobSpbJkbSqbSrbSsbStbSubSvbSwbSxbJkbSybSzbLbbSAbSBbSBbSCbSDbSEbSFbSGbLgbSHbSIbMHbSJbSKbLhbPNbSLbSMbSNbSObSPbSQbSRbPPbSSbRAbSTbSTbPTbSUbSVbSWbSXbSYbSZbTabTbbTcbTdbNabOMbwobTeaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabBQbBQbBQbBQbBQaaaaaaaaaaaaaaaaaaaaaaaabTfbTgbThbTgbTiaaaaaaaaabOVbOVbTjbTkbRObTlbNybTmbQnbTnbTobNzbDXbTpbTqbTrbTsbTtbTubTvbTwbTxbTybTzbTAbTBbTCbTCbTDbTEbTEbTEbTEbTEbTEbTFbTGbTHbTIbTJbTKbTsbTLbTMbTNbTObTPbPlbTQbQUbQVbTRbSpbJkbSqbSrbTSbTTbTUbTVbTWbTXbJsbTYbTZbLbbLbbUabUabLbbSDbLdbUbbUcbLgbUdbUebUfbUgbUhbLhbPNbUibUjbUkbUlbUmbUnbUobPPbUpbRAbSTbSTbPTbUqbUrbUsbUtbUubUvbUwbUxbUybUzbNabOMbUAbUBbUAbUCbUDbUCbUCbUCaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUEbUFbUGbUHbUEbUIbUIbUIbOVbUJbUKbULbUMbUNbUObUPbUQbUQbURbNzbUSbUTbUUbUVbUVbUWbUXbUYbUVbUZbUZbVabVbbVcbUZbUZbVdbQMbQMbVebVfbVfbVfbVgbVhbVfbVfbVibVjbVkbVkbVlbVkbVmbVnbVkbVobVpbVqbPlbVrbVsbSqbVtbVubVvbVwbVxbVybVubJkbSybVzbVAbVBbVCbVDbVEbVFbVGbVHbVIbVJbVKbVLbVMbVNbVObLhbPNbPNbVPbVQbVRbVSbVRbVTbPPbVUbVVbVWbVWbPTbVXbVYbVZbNabNabNabNabNabNabNabNabOMbUAbWabWbbWcbWdbWdbWebUCaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbWfbWfbWfbWfbWgbWgbWhbWhbWhbWhbWiaabaabaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabThbWjbWkbWjbThbUIbWlbWmbWnbWobWpbWqbWrbWsbNzbWtbWubWvbWwbNzbUTbUTbWxbUVbWybWzbWAbWBbWCbUZbWDbWEbWFbWGbWHbUZbWIbWJbWKbVfbWLbWMbWNbWObWPbWQbWRbWSbWTbWUbWVbWWbWXbWYbWZbXabXbbXcbXdbXebXfbXgbXhbSrbXibXjbXkbXlbXmbXnbJsbXobXpbXqbXrbVDbXsbXsbXtbXubLgbXvbXwbXxbXybXzbXAbXBbLhbXCbXDbXEbXFbXEbXEbXGbXHbXIbXJbXKbXLbXMbPTbXNbXObPXbEXbxXbXPbXQbXRbXRbXQbXRbXSbUAbXTbXUbWcbWdbXVbXWbUCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWfbXXbXYbXXbWgbWhbWhbXZbYabXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabThbWjbWkbWjbThbUIbWlbWmbWnbWobWpbWqbWrbWsbNzbWtbWubWvbWwbNzbUTbUTbWxbUVbWybWzbWAbWBbWCbUZbWDbWEbWFbWGbWHbUZbWIbWJbWKbVfbWLbWMbWObWNbWPbWQbWRbWSbWTbWUbWVbWWbWXbWYbWZbXabXbbXcbXdbXebXfbXgbXhbSrbXibXjbXkbXlbXmbXnbJsbXobXpbXqbXrbVDbXsbXsbXtbXubLgbXvbXwbXxbXybXzbXAbXBbLhbXCbXDbXEbXFbXEbXEbXGbXHbXIbXJbXKbXLbXMbPTbXNbXObPXbEXbxXbXPbXQbXRbXRbXQbXRbXSbUAbXTbXUbWcbWdbXVbXWbUCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWfbXXbXYbXXbWgbWhbWhbXZbYabXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUEbYbbWjbWjbYcbYdbTkbYebYfbYgbTkbWqbYhbYibNzbNzbNzbNzbNzbNzbYjbUTbYkbYlbYmbYnbYnbYnbYobUZbYpbYqbYqbYqbYrbYsbYtbYubYvbYwbYxbYybYzbYAbYBbYCbVfbVibYDbVkbYEbYFbYGbYHbYIbVkbSmbQVbSnbSobYJbYKbYLbYMbYNbYObYPbYQbYRbVubYSbYTbYUbYVbYWbYXbYYbYZbZabZbbLgbLgbLgbLgbLgbZcbZdbZebLhbZfbXEbXEbZgbZhbXEbZibZjbZkbZlbRAbZmbZmbPTbPVbZnbPXbEXbUAbZobUAbUAbUAbUAbUAbUAbUAbZpbZqbUCbZrbZsbZtbUCaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacaacbZubXXbXXbZvbWhbWhbXZbXZbZwbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabThbWkbWkbWkbThbUIbZxbZybZzbZAbTkbZBbZCbZDbZEbZFbZFbZFbZGbUTbUTbUTbWxbUVbZHbYnbZIbYnbZJbUZbYpbYqbZKbYqbZLbUZbZMbZNbZObVfbZPbZQbZRbZSbZTbZUbZVbZWbZXbZYbZZcaacabcaccadbVkbTQbQVbQVcaebYJbYKcafcagcahbXjcaicajcakcalcamcancaocapcaqcarcascasbXscatbVAcaucavcawcaxcaycazcaAbZjbZfcaBbXEbXEbXEcaCcaDbZjbZkcaEbRAbZmbZmbPTcaFcaGbPXbEXcaHcaIcaJbUAcaKcaLcaMcaNcaOcaPcaQbUCcaRcaScaTbUCbUAbUAbUAbUAbUAbUAbUAbUAaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacaUbWhbZubWhbWhbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbFlaaaaaaaaaaaaaaaaaaaaaaaaaaabFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmbFmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaabUEcaVcaWcaXbUEbUIbUIbUIbOVcaYcaZcaZcaZbOVbOVbUTcbacbacbbcbcbUTcbdcbebUVbZHbYnbYnbYncbfbUZbYpbYqbYqcbgcbhcbicbjcbkcblbVfbVfbVfbVfbVfcbmbVfbVfcbncbobVkbVkcbpbVkbVnbVkbVkbPlcbqcbqbPlbPlcbrcbscbtcbucbvcbwcbxcbycbzcbAcbBcaocapcbCcbDcbEcbFcbGcbHbVAcbIcbJcbKcbLcbMcbNcbOcbPcbQcbPcbRcbRcbRcbPcbScbPcbPcbTcbUbZmbZmbPTcbVbZnbPXcbWcbXcbYcbZccaccbccccccccdcceccfccgcchcciccjcckcclccmccnccoccpccqccrccscctaabaabaabaabaabaabaabaabaaaaaaaaaaaaaaabWgbWhccuccvccvbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8389,7 +8392,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFlbFlbFlbFlbFlbFlbFlbFlbF aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacejcfPcfQcfRbUTcfSbUVcfTcfUcfVbZHcfWcfXcfYbYpcfZcgacgbcfXcgccgdcgecgfcgfcggcghcgicgjcgkcglcgmbGycgnbVicgobGybGycgpcgqcgrcgscgtceQcgucgvcgwcgxcgycgzcgAcgBcgCcgzcgzcgDcgEcgEcgEcgEcgEcgGcgFcgHcgJcgJcgKcgLcgMcgNcgOcgPcbPcgQcgRcgScgTcgScgUcgVcfrcgWcgXcgYbBxcgZbBxcfybZnbBxbEXchachbchcbUAbUAbUAbUAbUAchdcdUchechfcfIcdUchgcdUbZpcdUchhbUAchichjchkbUAaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabWhchlchlchlchlchlchlchmbXZchnchlcfObXZbXZbXZbXZbWhaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacejchochpchqbUTcfSchrchrchrchrchrchrbUZbUZbUZbUZbUZbUZbUZchschtchuchvchwchxchychychzchAcglbGybGychBchCchDbGybGybGychEchFchGceOchHchIchJcgEchKchLchMbSqchLchNcfdcfdcfdcfdcfdcfdcfdcfdcfdcgIbSqchOchPchQchRchSchTchUchVcbPchWchXcfrchYcfrchZciacibciccidciecifbBxcigcfybZncihbEXbFeciicijcikbwobxXbxXbUAcilcimcinciocipciqcirciscitciucivbUAciwcixciycizaacaacaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaciAbXXbXXbXXbXXbXXbXXbXXciBciCbXZbXZbXZbXZciDbYabWhaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacejcejcejcejbUTcfScejaaaaaaaaaaaaciEciFciGciHciIciJciKciLciMciNciOciPciQciRciSciSciTciUciVciWciWciWciWciXciWbGybGybPlciYciZcjacjbcjccjdchScjecjfcjgcjhcjicjjcjkcfdcfdcjlcjpcjpcjpcjpckNclSckUcjqcjqcjrcjscjtcbAcjucjvcbPcjwcjxcjycjzcjAcfrcjBcbPcbPbEXcjCbEXbEXbEXcjDcjEcjFbEXbxXciicjGcjHbwobwobwobUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAbUAaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabWhccvccvccvccvccvccvcjIbXZccuccvcjJbXZbXZbXZbXZbWhaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabTeaaaaabaabcjKcjKcjKcjKcjKcjKcjLcjKbUTcelcjMaaacjNcjOcjPcjQcjRcjScjTcjUcjVcjWcjXcjYcjZckackbckcckdckeckfckgckhciVckickjckjckjckkciWbGybGycklcklcklcklckmcklckncknckocklcklckpcklckqckrckscktcksclZaPKcmacmmcmlcmocmnckzckAckBckCckDckEckFcdccbPcbPckGcbPckHcbPckIckJckKcgnckLckMckvckOckPckQckRckSckPbxXciickTbxXbxXckVckWckXchabxXbxXbxXbxXbxXbxXbxXckYckZbONaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWhbXZbXZbXZbXZbXZbXZcfNbXZcjJbXZbXZbXZbXZbXZbWhbWhaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacAjaaaaabaabcjKcjKcjKcjKcjKcjKcjLcjKbUTcelcjMaaacjNcjOcjPcjQcjRcjScjTcjUcjVcjWcjXcjYcjZckackbckcckdckeckfckgckhciVckickjckjckjckkciWbGybGycklcklcklcklckmcklckncknckocklcklckpcklckqckrckscktcksclZaPKcmacmmcmlcmocmnckzckAckBckCckDckEckFcdccbPcbPckGcbPckHcbPckIckJckKcgnckLckMckvckOckPckQckRckSckPbxXciickTbxXbxXckVckWckXchabxXbxXbxXbxXbxXbxXbxXckYckZbONaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWhbXZbXZbXZbXZbXZbXZcfNbXZcjJbXZbXZbXZbXZbXZbWhbWhaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaclaclbclbclbclccldcleclfclgclhclicjLcljcelcjMaaaclkcllclmclnclocjSclpclqclrclsciLcltcgdcbkciPcluchyclvchyclwclxclyclzclAclAclAclBciWbGybGycklclCclDclEclFclGclHclHclIclJclKclLclMclNclOclPcfhcfhcmpcmrcmqctbcsZcuoctcckDclVclWclXckzclYcmtcmscmbcmbcmccmdcmecmfcmgcmhcmfcmfcmfcmicmfcmfcmjcmucnpcnlcqRcoXcrGcqScrHcrHcrIcrHcrHcrHcrHcrJcrKcrHcrHcrHcrMcmvbxXbONaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWhbWhceibXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmwcmxcmxcmxcmxcmycmzcmAcmBcmCcmCcmDcjKcmEcfScjMaaaclkcmFcmGcmHcmIcmJcmKcmLcmIcmIcmMcmNcmOcmPcmQcmQcmRcmSchycmTcmUclyclAclAclAclAcmVciWbGybGycklcmWcmXcmYcmZcnacnbcnbcnccndcnecnfcngcnhcklcnicfdcnjcjpcwscvxcwEcwCcxNcxIckDcnmcnncnockDbJGcumctecnqcnqcnqcnqcnqcnrcnscntcnucnvcnvcnwcnwcnvcnxcnycnzcnAcnBcnCcnDcnEcnCcnCcnCcnCcnCcnCcnCcnCcnCcnCcnCcnCcuncnFcnGbONaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaUbWhbWhchlchlbXZbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacnHcnIcnJcnKcnJcnLcnMcnNcnOcnPcnQcjKcnRcelcjMaaaclkcnScnTcnUcnVcjScnWcnXcnYcnZciLcltcgdcoacobcgfcoccodciPciPciPcoecofclAclAcogcohciWbGycoicklcojcokcolcomcomcomconcoocomcomcopcolcoqcorcoscfdcotcjpcxVcxUcxVcxVcxNcEickDcowcoxcoyckDcozcuscoicoAcoAcoAcoAcoAcoBcoCcoDcoAcoAaaaaaaaaaaaackPcoEcoFcoGcnCcoHcoIcoJcoKcoLcoMcoNcoOcoPcoQcoRcoScoTcoUcnCcuncoWcvtcoYcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcoZcpacpbbWhbZubWhbXZbXZbXZbXZbXZbXZbXZbWhbWhaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8406,7 +8409,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaaaaaaaaaaacGaaaczocAkczqaaaczocAkczqaaaczocAkczqaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabczscwWcwXcztcAlcxjcAmcAncAocAocyjcxjcztcApcxjcxjcxjcxjcAqcArcAscAtbZNcAucAvcAwcAxcAycxsczBcAzcAAcxscABctWcsOcACcsLcADcAEcAFcAGcAHcAIcAJcAGcAKcAGcAGcAGcoAcoAcoAcoAcoAcoAcoAcoAcEhcoAaaaaaaaaaaaadcidcodcqdcpdbycgmcFdbVicFmcFlcFlcFnbGycoAaaaaaackPcwtcwucwvcAQcARczbcAScATcAUcFrcIScAXcGscIScGtckPaaaaaacwGcwGcBbcCrcBdcwGcwGbwobxXcGycyJcyJcyJbwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaahaaaaaaaaaafxaabczocAkczqaaaczocAkczqaabczocAkczqaabaaaaaaaabaabaabaabaabaaaaaaaaaaaaaaaaabaaaaaaczscwWcvKcBecxjcBfcBgcBhcBicBjcBicBkcBicBlcBmcxfcBncztcztczxcBocBpcBqcBrcBscBtcBucBvcBwcBxcBycBzcBAcBBcBCcBDcBDcBEcBFcBGcBHcBIcBJcBKcBLcBMcHscBOcHucHtcDPcDPcDPcDPcDPcDPcHvcoAcEhclUclUclUclUclUclUcjmbEJcjmcFfclUclUcoAcoAcoAcoAcusbGycoAaaaaaackPcxOcBZcxOcCacxRcqUcCbcCccCdcCecqUcqUcCgcqUcChckPaaaaabaabcwGcwGcCscwGcwGaaabwobxXcvzcyJcHycHxbwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaaaaaaaaaaaabaaaczocAkczqaabczocAkczqaaaczocAkczqaaaaaaaaaaaaaaaaaaaabaabaabaaaaabaaaaabaabaaaaaacybcCicvKcCjcCkcCkcClcvKcvKcvKcvKcvKcvKcvKcvKcvKcvKcvKcvKcvKcCmcCncCmcCocCmcrmcCpcCqcFbcCtcCtcCtcCucCvcBCcCwcCxcCycCzcCAcCBcBIcCCcCDcCEcCFcHzcCHcHAcCJaabcCKcCKcCKcCKcCKcHBcoAcHDcHCcIGcHHcIHctackycjocjnckuckycCScGucupcHwcCScoAcusbGycoAaaaaaackPcxOcxOcxOcAQcCTczbcCUcCVcCWcCXcCZcCZcDacqUcDbckPaabaabaaaaaaaaacIKaaaaaaaaabwobxXcvzcyJbxXbxXbwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaacGacGafxaabaaaczocAkczqaabczocAkczqaaaczocAkczqaabaaaaaaaaaaaaaaaaaaaaaaaaaabcDccDdcDdcDdcDdcybcDecwWcDfcDgcDhcDhcDicDjcDkcDlcDlcDlcDlcDmcDncDocDncDncDpcDpcDncDqcDrcDscDtcDtcDucDvcDwcDxcDycDzcDzcDAcDBcDCcDDcDEcDFcCAcDGcBIcDHcDIcDJcDKcILcDMcIMcDOcDPcDQcDRcDScDTcCKcHBcoDcEhclUcvscvqcIOcINcxLckxckwdcrclUcuqczVcuqczVcuqcoAcusbGycoAcoAaaackPcwAcwAcwAcwAcEkcqUcCbcElcEmcCecqUcEncEocEocEpcEqcAjaabaaaaaaaaaaaaaaaaaaaaabwobxXcGybxXbxXcIPbwoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaacGacGafxaabaaaczocAkczqaabczocAkczqaaaczocAkczqaabaaaaaaaaaaaaaaaaaaaaaaaaaabcDccDdcDdcDdcDdcybcDecwWcDfcDgcDhcDhcDicDjcDkcDlcDlcDlcDlcDmcDncDocDncDncDpcDpcDncDqcDrcDscDtcDtcDucDvcDwcDxcDycDzcDzcDAcDBcDCcDDcDEcDFcCAcDGcBIcDHcDIcDJcDKcILcDMcIMcDOcDPcDQcDRcDScDTcCKcHBcoDcEhclUcvscvqcIOcINcxLckxckwdcrclUcuqczVcuqczVcuqcoAcusbGycoAcoAaaackPcwAcwAcwAcwAcEkcqUcCbcElcEmcCecqUcEncEocEocEpcEqcXYaabaaaaaaaaaaaaaaaaaaaaabwobxXcGybxXbxXcIPbwoaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaacGaaaaabaaaaabaabcEraabaabaabcEraabaaaaabcEraabaaaaaaaaaaaaaaaaaaaaaaaacDccDccDccEscEtcEucEvcEwcExcEycDfcDfcEzcEAcvKcvKcEBcECcECcECcECcEDcEEcEFcEEcEEcEEcDtcDtcEGcEHcEIcEJcEKcDzcELcDwcDzcDzcDzcDzcEMcBCcENcEOcCycDFcCAcDFcBIcDHcDIcEPcEQcERcEScETcEUaabcEVcEWcDTcEXcCKcHBcoDcHDcHCcxKcxJczVcxMclUcIIclQdcsclUcIQcIRczVcuqcyWclUcusbGycITcoAaaackPcwtcwucwvcFjcARczbcFkcJJcJIcJKcJKcFocFpcFqcJLckPaabaabaabaaaaaaaaaaaaaaaaaabwocJMcvzbwobwobwobwobwoaabaabaabcJNcJNcJNcJNcJNcJNaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaafxaabcFscFtcFtcFucFvcFwcFwcFwcFvcFwcFwcFwcFvcFwcFwcFxcFtcFtcFtcFtcFtcFycFzcFAcFBcFCcFDcFEcFFcFGcfRcwWcFHcDfcvKcvKcvKcFIcEBcECcFJcFKcFLcFMcFNcFOcFPcFQcFRcFScFTcFUcFVcFWcFXcFScFYcFZcDwcGacDzcDzcDzcGbcBCcGccGccDFcGdcGecGfcGgcGhcGicGjcGkcGlcGmcGncDOcGocDQcGpcDTcDTcCKcHBcoDcEhclUcyMcyLcyNcFfclUcnkclTcFfclUcyQcyScyRcyTcyTclUcusbGycJOcoAaaackPcxOcxPcxOcGAcxRcqUcGBcJPcGCcqUcqUcGDcwAcwAcwAckPaaaaaaaabaabaaaaaaaaaaaaaaabwocyKcvzbwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyacyacyacyacyacyacyacyacyaaaaaaaaaaacGaaaaabaaaaabaabcGFaabaaaaabcGFaabaaaaabcGFaabaaaaaaaaaaaaaaaaaaaaaaaacDccDccDccGGcGHcGIcDdcGJcfRcGKcExcExcExcExcGLcExcFGcECcGMcGNcGOcGPcGQcGRcGScGTcGUcGVcGWcGXcGYcGZcHacHbcFYcELcDwcHccHdcDzcDzcHecBCcHfcHgcDFcHhcCAcHicHjcHkcHlcHmcHncHocHpcHocHqaabcCKcCKcCKcCKcCKcHBcoAcEhclUcIJcyVcyYcyXczNcJQczPczOcJhczQcyLczVczVczSclUcusbGycJRcoAaaackPcxOcxOcxOcFjcHEcHFcHGcJScHIcCZcCZcCZcHJcHKcHLcHMaaaaaaaaaaabaabaaaaaaaaaaaabwobwocvzbwoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8434,7 +8437,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabcECcTncTocSEaaaaaaaabaaaaaaaabaabaabaabaabaaaaaaaabaaaaaacSEcTlcTmcECcTpcECcECcECcECcECaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaGcYhdaidaHdaicYhcoAdaIcFicFidaJdaLdaKcoAcoAcoAaaaaaaaaaaaaaaaaabaaacxHdaodaMcyJcNRbxXbxXdaNcyJdaObxXbxXbxXbxXbxXbxXbxXbwoaabaaaaaaaaaaabaaacuzcvEcuzaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaacQScQScQScQSaaaaaacQScQScQScQScQScQScQSaaaaaacQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaabcECcTdcSEcTPaaaaaacTQaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaacSEcSEcTdcECcMHcTRcTScTTcTUcTVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaGcYhdaPdaRdaQdaSaabcoAcoAcoDdaTcoDcoAcoAaaaaabaaaaaaaaaaaaaaaaabaabcxHcxHcxHbwobwobwobxXcyJbwodaUbwobwocNRbFeczfbzNczMbwoaabaaaaaaaaaaabaaacuzcwMcuzaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcECcTXcTYcSEaabaabaabcSQaaaaaacSQaaaaaaaaaaaacSQaabcTZaabcSEcUacUbcECcMHcUccUdcGOcUecTVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaadaGcYhcYhdaVcYhcYhaaaaabaaaaaadaWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaabwodaFdaXbwocGxaabbwobwocxHcxHczMbwoaaaaabaaaaaaaaaaabaaaaaacxZaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacECcUfcUgcUhaaaaaaaabaabaabaabaabaabaabaabaabaabaabaaaaaacUicUgcUjcECcMHcECcUkcUlcUmcReaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacIKazycYhdaYcYhdaZaabaabaaaaaacIKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaahaaaaaabwodbbdbabwodbcaabaaaaabaaaaaaaabaaaaaaaabaaaaaaaaaaabaaaaaacznaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacECcUfcUgcUhaaaaaaaabaabaabaabaabaabaabaabaabaabaabaaaaaacUicUgcUjcECcMHcECcUkcUlcUmcReaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadcdazycYhdaYcYhdaZaabaabaaaaaadctaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaahaaaaaabwodbbdbabwodbcaabaaaaabaaaaaaaabaaaaaaaabaaaaaaaaaaabaaaaaacznaaaaaaaabaaaaabaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacNycECcKDcSkcUhaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabaaaaaacUicSjcKDcECcECcMHcECcECcECcUncECaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabaabazydbddbedbdazyaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaaaaaaaaacxHdbfcxHcxHaabczraaaaabaaaaaaaabaaaagQagQacGaqZaabaabaabaabcGEaabaabaabaabczragiagQagQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacECcECcSkcRScRScRScRScRScRScRScRScRScRScRScRScRScSjcECcECcECcECcTpcECaaaaabcUocUpaabaaaaaaaaaaabaaaaaaaaaaabaaaaaaaaaaabaaaaaaaaaaabaaaaabazyaaaaaaaaaazyaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaacxHdbgcxHaaaaaaaaaaaaaabaaaaaaaabaaaagQaaaaaaaabaaaaabaaaaaacHNaaaaaaaabaaaaabaaaaaaagQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTOcTOcTOcTOcTOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacQScQScQScQScQScQScQSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaacECcECcECcECcECcECcECcECcECcECcECcECcECcECcECcECcECaaacECcECcUqcECaabaabcUrcUscUtcUucUvcUucUtcUucUvcUucUtcUucUvcUucUtcUucUvcUwcUxaaaaabazyazyazyazyazyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaacxHdbhcxHaaaaaaaaaaaaaabaaaaaaaabaaaagQaaacIYcIYcIYcIYcIYaabcIZaabcIYcIYcIYcIYcIYaaaagQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -8470,7 +8473,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGcVucWdcVFaaaaabaaacXvcXwcXxcXycXzcXAcXvaaaaaaaaacVucWlcVFacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGcVucWdcXBcVIcXCcXCcXvcXDcXEcXFcXGcXHcXvcVIcVIcVIcXdcWlcVFacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGcVucXIcVRcVRcVRcVRcXJcXKcXLcXMcXNcXOcXPcXQcWacWacWacXRcVFacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGaaacWfcWfcWfcWfcWfcXvcXScXTcXUcXVcXWcXXcXYcWfcWfcXZcXZaaaacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGaaacWfcWfcWfcWfcWfcXvcXScXTcXUcXVcXWcXXdcucWfcWfcXZcXZaaaacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaacVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacGacGacGacGacGacGacGcXvcYacYbcYccYdcYecXvacGacGacGacGacGacGacGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaacVGcVGcVGcVGcVGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabcXvcXvcYfcYfcYfcXvcXvaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacSKcSKcSKcSKcSKcSKcSKcSKcSKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWcTWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/_maps/map_files/cyberiad/z5.dmm b/_maps/map_files/cyberiad/z5.dmm index 958a023b33d..c00a7f8fe50 100644 --- a/_maps/map_files/cyberiad/z5.dmm +++ b/_maps/map_files/cyberiad/z5.dmm @@ -246,7 +246,7 @@ "eL" = (/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/wall/r_wall,/area/research_outpost/power) "eM" = (/obj/structure/transit_tube{icon_state = "N-S"},/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/floor/plating/airless/asteroid,/area/mine/explored) "eN" = (/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 4},/turf/simulated/mineral,/area/mine/explored) -"eO" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 8},/turf/simulated/floor/plating,/area/mine/explored) +"eO" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 8},/turf/simulated/floor/plating,/area/research_outpost/atmos) "eP" = (/obj/item/stack/rods,/obj/structure/window/reinforced{dir = 4},/obj/item/weapon/shard,/turf/simulated/floor/plating,/area/mine/abandoned) "eQ" = (/obj/item/stack/rods,/obj/structure/alien/weeds{icon_state = "weeds2"},/turf/simulated/floor/airless{icon_state = "floorscorched1"},/area/mine/abandoned) "eR" = (/turf/simulated/floor/airless{icon_state = "damaged2"},/area/mine/abandoned) @@ -411,9 +411,9 @@ "hU" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/regular,/obj/item/weapon/storage/firstaid/toxin,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor{icon_state = "white"},/area/research_outpost/med) "hV" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/o2{pixel_x = 2; pixel_y = 2},/obj/item/weapon/storage/firstaid/fire,/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/light/small{dir = 1},/turf/simulated/floor{icon_state = "white"},/area/research_outpost/med) "hW" = (/turf/simulated/wall/r_wall,/area/research_outpost/tempstorage) -"hX" = (/obj/machinery/mineral/input,/obj/machinery/camera{c_tag = "Research Outpost Temporary Storage"; dir = 2; network = list("Research Outpost")},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/research_outpost/tempstorage) +"hX" = (/obj/machinery/camera{c_tag = "Research Outpost Temporary Storage"; dir = 2; network = list("Research Outpost")},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/research_outpost/tempstorage) "hY" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 2; on = 1},/obj/machinery/mineral/unloading_machine,/turf/simulated/floor{dir = 1; icon_state = "vault"; name = "Mainframe floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/research_outpost/tempstorage) -"hZ" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/obj/machinery/mineral/output,/obj/machinery/light_switch{pixel_x = 0; pixel_y = 23},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/research_outpost/tempstorage) +"hZ" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/obj/machinery/light_switch{pixel_x = 0; pixel_y = 23},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/research_outpost/tempstorage) "ia" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/turf/simulated/wall/r_wall,/area/research_outpost/tempstorage) "ib" = (/obj/machinery/camera{c_tag = "Research Outpost Hallway Central"; dir = 4; network = list("Research Outpost")},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor{dir = 5; icon_state = "whitehall"},/area/research_outpost/hallway) "ic" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor{icon_state = "white"},/area/research_outpost/hallway) @@ -668,7 +668,7 @@ "mR" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/turf/simulated/floor,/area/research_outpost/gearstore) "mS" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{dir = 4; name = "Expedition Area APC"; pixel_x = 26; pixel_y = 0},/obj/machinery/camera{c_tag = "Research Outpost Expedition Preparation"; dir = 8; network = list("Research Outpost")},/turf/simulated/floor,/area/research_outpost/gearstore) "mT" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor,/area/research_outpost/tempstorage) -"mU" = (/obj/machinery/mineral/input,/obj/machinery/conveyor_switch/oneway{id = "anominerals"; pixel_y = 16},/obj/machinery/light_switch{pixel_x = 27},/turf/simulated/floor{dir = 2; icon_state = "loadingarea"},/area/research_outpost/tempstorage) +"mU" = (/obj/machinery/conveyor_switch/oneway{id = "anominerals"; pixel_y = 16},/obj/machinery/light_switch{pixel_x = 27},/turf/simulated/floor{dir = 2; icon_state = "loadingarea"},/area/research_outpost/tempstorage) "mV" = (/obj/machinery/conveyor{dir = 1; id = "anosample"},/obj/structure/plasticflaps/mining,/turf/simulated/floor/plating,/area/research_outpost/maint) "mW" = (/obj/machinery/portable_atmospherics/canister/sleeping_agent,/turf/simulated/floor/plating,/area/research_outpost/maint) "mX" = (/obj/machinery/computer/security/telescreen{desc = "Used for watching the isolation room cameras."; layer = 4; name = "Isolation Room Telescreen"; network = list("Anomaly Isolation"); pixel_x = 32; pixel_y = 0},/turf/simulated/floor/plating,/area/research_outpost/maint) @@ -703,7 +703,7 @@ "nA" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/machinery/door/firedoor{dir = 4; name = "Firelock"},/obj/machinery/door/airlock/glass_mining{name = "Equipment storage"; req_access_txt = "47"},/turf/simulated/floor,/area/research_outpost/gearstore) "nB" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor,/area/research_outpost/gearstore) "nC" = (/turf/simulated/floor,/area/research_outpost/gearstore) -"nD" = (/obj/machinery/mineral/unloading_machine,/turf/simulated/floor{icon_state = "floorgrime"},/area/research_outpost/tempstorage) +"nD" = (/obj/machinery/mineral/unloading_machine{input_dir = 1; output_dir = 2},/turf/simulated/floor{icon_state = "floorgrime"},/area/research_outpost/tempstorage) "nE" = (/obj/machinery/conveyor_switch{id = "anotempload"},/turf/simulated/floor/airless{tag = "icon-asteroidwarning (NORTH)"; icon_state = "asteroidwarning"; dir = 1},/area/research_outpost/maint) "nF" = (/obj/machinery/conveyor{dir = 2; id = "anotempload"},/turf/simulated/floor/airless{tag = "icon-asteroidwarning (NORTH)"; icon_state = "asteroidwarning"; dir = 1},/area/research_outpost/maint) "nG" = (/obj/machinery/conveyor_switch{id = "anosample"},/obj/machinery/light/small{dir = 1},/turf/simulated/floor/airless{tag = "icon-asteroidwarning (NORTH)"; icon_state = "asteroidwarning"; dir = 1},/area/research_outpost/maint) @@ -738,7 +738,7 @@ "oj" = (/obj/structure/dispenser/oxygen,/turf/simulated/floor,/area/research_outpost/gearstore) "ok" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor,/area/research_outpost/gearstore) "ol" = (/obj/structure/table,/obj/item/weapon/pickaxe,/obj/machinery/status_display{layer = 4; pixel_x = 32; pixel_y = 0},/obj/item/weapon/wrench,/obj/item/device/measuring_tape,/obj/item/weapon/storage/box/excavation,/obj/item/device/ano_scanner,/obj/item/weapon/storage/bag/fossils,/turf/simulated/floor,/area/research_outpost/gearstore) -"om" = (/obj/machinery/conveyor{dir = 2; id = "anominerals"},/obj/machinery/mineral/output,/turf/simulated/floor{icon_state = "floorgrime"},/area/research_outpost/tempstorage) +"om" = (/obj/machinery/conveyor{dir = 2; id = "anominerals"},/turf/simulated/floor{icon_state = "floorgrime"},/area/research_outpost/tempstorage) "on" = (/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"; tag = ""},/area/mine/explored) "oo" = (/obj/machinery/light/small{dir = 8},/obj/machinery/alarm{dir = 4; pixel_x = -23; pixel_y = 0},/turf/simulated/floor/plating,/area/research_outpost/maint) "op" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/visible{dir = 6; level = 1},/turf/simulated/floor/plating,/area/research_outpost/iso1) @@ -945,9 +945,9 @@ "si" = (/obj/machinery/conveyor{dir = 2; id = "gulag"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sj" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/obj/structure/plasticflaps/mining,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sk" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) -"sl" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/obj/machinery/mineral/output,/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) -"sm" = (/obj/machinery/mineral/unloading_machine{dir = 1},/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) -"sn" = (/obj/structure/ore_box,/obj/machinery/mineral/input,/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) +"sl" = (/obj/structure/ore_box,/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) +"sm" = (/obj/machinery/mineral/unloading_machine{dir = 1; input_dir = 4; output_dir = 8},/turf/simulated/floor/plating{icon_plating = "asteroidplating"; icon_state = "asteroidplating"},/area/mine/laborcamp) +"sn" = (/obj/structure/plasticflaps,/obj/machinery/conveyor{dir = 2; id = "gulag"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "so" = (/obj/structure/closet/crate{icon_state = "crateopen"; opened = 1},/turf/simulated/floor{icon_plating = "asteroid"; icon_state = "asteroid"; name = "Asteroid"},/area/mine/explored) "sp" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "labor_camp_north_outer"; locked = 1; name = "Labor Camp Airlock"; opacity = 1; req_access_txt = "2"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sq" = (/obj/machinery/light/small{dir = 1},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "labor_camp_north_sensor"; pixel_x = -8; pixel_y = 30},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1379; id_tag = "labor_camp_north_pump"},/obj/machinery/door_control{id = "Labor"; name = "Labor Camp Lockdown"; pixel_x = 0; pixel_y = -28; req_access_txt = "2"},/obj/machinery/embedded_controller/radio/airlock/docking_port_multi{id_tag = "labor_camp_north_airlock"; master_tag = "labor_camp_dock"; pixel_y = 30; req_access_txt = "2"; req_one_access_txt = "0"; tag_airpump = "labor_camp_north_pump"; tag_chamber_sensor = "labor_camp_north_sensor"; tag_exterior_door = "labor_camp_north_outer"; tag_interior_door = "labor_camp_north_inner"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) @@ -955,7 +955,7 @@ "ss" = (/obj/machinery/door/poddoor/preopen{id_tag = "Labor"; name = "labor camp blast door"},/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; master_tag = "labor_camp_north_airlock"; name = "interior access button"; pixel_x = -25; pixel_y = 25; req_access_txt = "2"},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; initialize_directions = 10},/obj/machinery/door/airlock/glass_security{name = "Labor Camp Shuttle Cockpit"; req_access_txt = "2"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "st" = (/turf/simulated/floor,/area/mine/laborcamp) "su" = (/obj/machinery/mineral/processing_unit_console{machinedir = 6},/turf/simulated/wall,/area/mine/laborcamp) -"sv" = (/obj/structure/plasticflaps,/obj/machinery/conveyor{dir = 2; id = "gulag"},/obj/machinery/mineral/input,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) +"sv" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sw" = (/obj/machinery/camera{c_tag = "Labor Camp External"; dir = 4; network = list("Labor")},/turf/simulated/floor{dir = 1; icon_state = "asteroidwarning"; tag = "icon-asteroidwarning (NORTH)"},/area/mine/laborcamp) "sx" = (/turf/simulated/floor{dir = 1; icon_state = "asteroidwarning"; tag = "icon-asteroidwarning (NORTH)"},/area/mine/laborcamp) "sy" = (/obj/machinery/conveyor_switch/oneway{id = "gulag"},/turf/simulated/floor{dir = 1; icon_state = "asteroidwarning"; tag = "icon-asteroidwarning (NORTH)"},/area/mine/laborcamp) @@ -970,10 +970,10 @@ "sH" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/mine/laborcamp) "sI" = (/obj/machinery/computer/shuttle_control/labor_camp/one_way,/obj/machinery/atmospherics/pipe/simple/hidden,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sJ" = (/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/navbeacon{codes_txt = "patrol;next_patrol=6-Vending"; location = "5-Central"},/obj/structure/sign/poster/legit{pixel_x = 0; pixel_y = -32},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) -"sK" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/obj/machinery/mineral/output,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) +"sK" = (/obj/machinery/conveyor{dir = 10; icon_state = "conveyor0"; id = "gulag"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) "sL" = (/obj/machinery/mineral/stacking_machine{dir = 1},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) -"sM" = (/obj/machinery/conveyor{dir = 8; id = "gulag"},/obj/machinery/mineral/input,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) -"sN" = (/obj/machinery/conveyor{dir = 10; icon_state = "conveyor0"; id = "gulag"},/obj/machinery/mineral/output,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/laborcamp) +"sM" = (/obj/machinery/mineral/unloading_machine{input_dir = 4; output_dir = 8},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/west_outpost) +"sN" = (/turf/simulated/floor{dir = 4; icon_state = "loadingarea"; tag = "loading"},/area/mine/west_outpost) "sO" = (/obj/structure/closet/crate,/turf/simulated/floor{icon_state = "asteroidfloor"},/area/mine/laborcamp) "sP" = (/obj/item/stack/sheet/metal{amount = 5},/obj/structure/closet/crate,/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor{icon_state = "asteroidfloor"},/area/mine/laborcamp) "sQ" = (/turf/simulated/wall/r_wall,/area/mine/laborcamp/security) @@ -1257,6 +1257,7 @@ "yi" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/obj/item/device/gps/mining{gpstag = "MINE2"},/obj/item/device/gps/mining{gpstag = "MINE1"},/obj/item/device/gps/mining,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -3},/turf/simulated/floor,/area/mine/eva) "yj" = (/turf/simulated/floor,/area/mine/eva) "yk" = (/obj/structure/dispenser/oxygen,/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor,/area/mine/eva) +"yl" = (/obj/machinery/conveyor{dir = 4; id = "mining_west"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/west_outpost) "ym" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 2; frequency = 1379; id_tag = "mining_east_pump"},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/eva) "yn" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 2; frequency = 1379; id_tag = "mining_east_pump"},/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/mine/eva) "yo" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/mine/eva) @@ -1268,9 +1269,6 @@ "yu" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor,/area/mine/west_outpost) "yv" = (/obj/machinery/light_switch{pixel_x = 6; pixel_y = -23},/turf/simulated/floor,/area/mine/west_outpost) "yw" = (/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/turf/simulated/floor,/area/mine/west_outpost) -"yx" = (/obj/machinery/mineral/input,/turf/simulated/floor{dir = 4; icon_state = "loadingarea"; tag = "loading"},/area/mine/west_outpost) -"yy" = (/obj/machinery/mineral/unloading_machine,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/west_outpost) -"yz" = (/obj/machinery/conveyor{dir = 4; id = "mining_west"},/obj/machinery/mineral/output,/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/west_outpost) "yA" = (/obj/structure/disposalpipe/trunk{dir = 4},/obj/machinery/disposal/deliveryChute{dir = 8},/turf/simulated/floor{icon_state = "floorgrime"},/area/mine/west_outpost) "yB" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/firedoor{dir = 2},/turf/simulated/floor/plating,/area/mine/west_outpost) "yC" = (/obj/structure/toilet{dir = 4},/obj/machinery/light_switch{pixel_y = -25},/turf/simulated/floor{icon_state = "showroomfloor"},/area/mine/living_quarters) @@ -1600,10 +1598,10 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaqUrBrCrdrDrfrerErFrfrGrdrHrIrIrqrJrqrtrtqQqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacaaaaaabkbkbkaaaaaaafafafpepepepepeafafaeaeaeaeqKaerKntafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaarLrLagagagagagqUrMrNrOrPrQrRrfrDrfrfrSrIrIrqrqrqrqrTrtqQqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacaaaaaaaaaaaaaaaaaaafafafpepepepepeafafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbkacaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUqUrVrWrXrYrQrZrfrDsarfrdsbscscrqrqrrrrrtrtqQqQqQbkqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacaaaaaaaaaaaaaaaaaaaaafafpepepepepeafafafaeaesdqBqCaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbkacaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUseqUrdrdrdsfrfsgrQshrusisjskslsmsnrqrrrrsortqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacaaaaaaaaaaaaaaaaaaafafpepepepepeafafafaeaeqxqGqzaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafaaafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUspsqsrssstrfrDrfrfsusvrdswsxsyrqrqrrrrrrrtszqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaaaaaaaaaaaaafafafpepepepepeafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbkacaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUseqUrdrdrdsfrfsgrQshrusisjsksksmslrqrrrrsortqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacaaaaaaaaaaaaaaaaaaafafpepepepepeafafafaeaeqxqGqzaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafaaafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUspsqsrssstrfrDrfrfsusnrdswsxsyrqrqrrrrrrrtszqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaaaaaaaaaaaaafafafpepepepepeafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacbkacaaaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUqUqUqUsAsBrfrDrusCrdsDrdrIsErIrrrrrrrrsFrdqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkctbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaaaactaaaaafafafpepepepepeafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacctacacaaaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUsGsHsHsIrfrfsJsKsLsMsNrdsOsPrrrrrrrrrTrtrtqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaabkctctaaaaafafpepepepepeafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacctacacaaaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUsGsHsHsIrfrfsJsvsLsvsKrdsOsPrrrrrrrrrTrtrtqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaabkctctaaaaafafpepepepepeafafaeaeaeqKaeaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUsQsQsQsRsSsTsUsVsVsVrdsVsVsWrrrrrrrrrTrtqQqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaabkbkctaaaaaaafafafafafpeafafafaeaeqKaeafafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagrUrUrUrUrUsXsYsZtatbtctdtetftgthtitjtkrIrrrrrrrtrtqQqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkctbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacaaaaaaaaaaaaaaaaaaaaafafafpeafafafaeaeqKaeafafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaagrUrUrUrUtlsQsVsVsUtmsUsVsVtntotpsVsVtqrIrrrrrtrtqQqQqQqQqQqQqQbkbkbkbkbkbkbkbkbkbkbkbkbkbkctbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkbkacacacacaaaaaaaaaaaaaaaaaaaaaaafafpeafafafaeaeqKaeaeafafpepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepepeafafafafafafafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1689,7 +1687,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacacacacaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaacacacaaaaacafaeaeaewtxbxcxdwHxcxexcxcxfxgxhwPxixjaeaeaeaeaeafafafacacacacacacacbkbkbkbkbkbkbkbkbkbkbkbkacacafafntaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeafafacacacacacacvNxkwRxlxmxnxovNvNvNvNvTvNwVxpxpxpxqweaeaeaeaeaeaeaeaaaaaaaaaaaaaaaaaaaeaeaeaeaeaeaeaeaeaeaewYxrxsxsxtwZaexuaeaeaeofntafafafpepepepepepepepepepeafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacaaaaaaaaaaaaaaaaaaaaaaaaaaacafaeaeaewtxvxcxcxwxcxexxxcxcwHxyxzwHqzaeaeaeaeaeaeaeafafafafacacacacacacbkbkbkbkbkbkbkbkbkacacafafaewfaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeafafafafacacacvNxAxBxCwRxDxExFxqxGxHxIvNxJxpxKxLxMweaeaeaeaeaeaeaaaaaaaaaaaaaaaaaaaaaaaaaeaeaeaeaexNxNxOxOwYxPxQxRxSwZwZwZwZaeaeaeaeafafafafpepepepepepepepepeafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacafafaeaewtxTxcxUwNxVxWxXxcwtwtwtwtwtwvsdqCaeaeaeaeaeaeaeaeafafafacacacacacbkbkbkbkbkbkbkacacacafaeaeaeaeaeaeaeaeaeaeaesdqCaeaeaeaeaeaeaeaeaeafafacacxYvNvNvNxZvNvNyaybycyaybvNvNvNvNvNydvNvNweweaeaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaexOxOyeyfygyhyiyjyjykyoymynyoqCaeaeaenuafafafpepepepepepepeafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacafaeaewtypyqyrwHysytyuyvywyxyyyzyAyBujukrArArArArAqTaeaeaeaeafafafacacacacacbkbkbkacacacacafafaeaeuhrArArArArArArArAujukrArArArAqTaeaeaeaeaeafacacacacacxZyCyDyExpxMyFxqxMxFyGyHyIxqxMxpyJyKweweweyLyMyMyMyMyMyMyMyNyNyNyNyNyNyNxOxOxOyOyfyPyQyRySyjyjyTyUyVyWyXyYaeaeaenuafafafpepepepepepeafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacafaeaewtypyqyrwHysytyuyvywsNsMylyAyBujukrArArArArAqTaeaeaeaeafafafacacacacacbkbkbkacacacacafafaeaeuhrArArArArArArArAujukrArArArAqTaeaeaeaeaeafacacacacacxZyCyDyExpxMyFxqxMxFyGyHyIxqxMxpyJyKweweweyLyMyMyMyMyMyMyMyNyNyNyNyNyNyNxOxOxOyOyfyPyQyRySyjyjyTyUyVyWyXyYaeaeaenuafafafpepepepepepeafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacafaeaewtwtwtwtwtyZzazbwtwtzcwtwtwtwtqxqzaeaeaeaeaeqKaeaeaeaeafaeafafacacacacacacacacacacafafaeaeaeqKaeaeaeaeaeaeaeaeqxqzaeaeaeaeqKaeaeaeaeaeafafntafafacvNvNvNvNxpxMzdzezfxHzgzhzhzizizjzhzkzlzhzlzmzmzmzmzmzmzmzmznznznznznznznzozpzozqzpzrzsztzuzvzwzxyozyzzyoqzaeaeaeaeafafafafpepepepepeafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacafafaeaeaeaeaewtzAzBzCzDwtzEzFonaeaeaeaeaeqMaeaeaeqSrArAqTaeaeaeaeafacacacacacacacacacacafaeaeuhrAuiaeaeaeaeafaeaeqMaeaeaeaeaeaeqKaeaeaeaeaeaeaewfaeafafafafafvNxpzGzHzIzIzHzJzKzLzIzIzMzHzNzOzOzOzPzPzPzPzPzPzPzPzQzQzQzQzQzQzRzSzSzSzTzUzVzWzXzYzZzYzYzYzYzYzYAaaeaeaeaenuafafafpepepepeafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacacafafaeaeaeaewtAbAcAdAewtaeaeaeaeaeaeafafntafaeaeaeaeaeqKaeaeaeaeaeafacacacacacafafafafafaeuhuiaeaeaeafafafafafafntaeaeaeaeaeaeqKaeaeaeaeaeaeaeaeaeaeaeafafvNvNyaAfyavNvNAgAhAivNvNvNAjyavNweaeaeaeaaaaaaaaagaaaaaaagaaaaaaaaaaagaaxOxOyfAkAlAmAnAoApAqArAszYwkAtaeaeaeaeaeafafafpepepepeafafafpeafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 4dfe8d70812..a7fe9ddd537 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -41,11 +41,14 @@ Pipelines + Other Objects -> Pipe network if(!pipe_color_check(pipe_color)) pipe_color = null + ..() + +/obj/machinery/atmospherics/initialize() + ..() + if(can_unwrench) stored = new(src, make_from = src) - ..() - /obj/machinery/atmospherics/Destroy() for(var/mob/living/M in src) //ventcrawling is serious business M.remove_ventcrawl() @@ -210,7 +213,7 @@ Pipelines + Other Objects -> Pipe network dir = D initialize_directions = P var/turf/T = loc - level = T.intact ? 2 : 1 + level = T.intact ? 2 : 1 initialize() var/list/nodes = pipeline_expansion() for(var/obj/machinery/atmospherics/A in nodes) diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm index b546268b4e0..343501dfd28 100644 --- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm +++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm @@ -42,6 +42,7 @@ return ..() /obj/machinery/atmospherics/binary/initialize() + ..() var/node2_connect = dir var/node1_connect = turn(dir, 180) diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm index 55216a5a5c2..f1241079ad3 100644 --- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm +++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm @@ -57,6 +57,7 @@ return ..() /obj/machinery/atmospherics/omni/initialize() + ..() for(var/datum/omni_port/P in ports) if(P.node || P.mode == 0) continue diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index cd219cd6f4e..5d33e3cb605 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -37,10 +37,7 @@ if(!istype(T)) return - if(flipped) - add_underlay(T, node1, turn(dir, -90)) - else - add_underlay(T, node1, turn(dir, -180)) + add_underlay(T, node1, turn(dir, -180)) if(flipped) add_underlay(T, node2, turn(dir, 90)) diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm index a008b8886d5..9824715c1f4 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm @@ -67,7 +67,7 @@ return ..() /obj/machinery/atmospherics/trinary/initialize() - + ..() //Mixer: //1 and 2 is input //Node 3 is output @@ -78,10 +78,6 @@ //Node 2 is filtered output //Node 3 is rest output //If we flip the filter, 1 and 3 shall exchange positions - - if(can_unwrench) // Overridden here to avoid having to snowflake the flipped/icon_state on the construction - qdel(stored) - stored = new(src, make_from = src) var/node1_connect = turn(dir, -180) var/node2_connect = turn(dir, -90) diff --git a/code/ATMOSPHERICS/components/trinary_devices/tvalve.dm b/code/ATMOSPHERICS/components/trinary_devices/tvalve.dm index 7e91c931f16..16df97b6ea6 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/tvalve.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/tvalve.dm @@ -40,6 +40,7 @@ var/turf/T = get_turf(src) if(!istype(T)) return + add_underlay(T, node1, turn(dir, -180)) if(flipped) @@ -65,7 +66,7 @@ parent1.update = 0 parent2.update = 0 parent3.update = 0 - parent3.reconcile_air() + parent1.reconcile_air() investigate_log("was set to side by [usr ? key_name(usr) : "a remote signal"]", "atmos") return 1 diff --git a/code/ATMOSPHERICS/components/unary_devices/passive_vent.dm b/code/ATMOSPHERICS/components/unary_devices/passive_vent.dm new file mode 100644 index 00000000000..632b75c0dc8 --- /dev/null +++ b/code/ATMOSPHERICS/components/unary_devices/passive_vent.dm @@ -0,0 +1,36 @@ +/obj/machinery/atmospherics/unary/passive_vent + icon = 'icons/atmos/vent_pump.dmi' + icon_state = "map_vent" + + name = "passive vent" + desc = "A large air vent" + + can_unwrench = 1 + + var/volume = 250 + +/obj/machinery/atmospherics/unary/passive_vent/high_volume + name = "large passive vent" + volume = 1000 + +/obj/machinery/atmospherics/unary/passive_vent/New() + ..() + air_contents.volume = volume + +/obj/machinery/atmospherics/unary/passive_vent/process() + ..() + + if(!node) + return + + var/datum/gas_mixture/removed = air_contents.remove(volume) + loc.assume_air(removed) + air_update_turf() + +/obj/machinery/atmospherics/unary/passive_vent/update_underlays() + if(..()) + underlays.Cut() + var/turf/T = get_turf(src) + if(!istype(T)) + return + add_underlay(T, node, dir) diff --git a/code/ATMOSPHERICS/components/unary_devices/tank.dm b/code/ATMOSPHERICS/components/unary_devices/tank.dm index 88f32eba44a..7c7298c511d 100644 --- a/code/ATMOSPHERICS/components/unary_devices/tank.dm +++ b/code/ATMOSPHERICS/components/unary_devices/tank.dm @@ -16,6 +16,13 @@ if(!istype(T)) return add_underlay(T, node, dir) + +/obj/machinery/atmospherics/unary/tank/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/device/analyzer)) + atmosanalyzer_scan(air_contents, user) + return + + return ..() /obj/machinery/atmospherics/unary/tank/air name = "Pressure Tank (Air)" diff --git a/code/ATMOSPHERICS/components/unary_devices/unary_base.dm b/code/ATMOSPHERICS/components/unary_devices/unary_base.dm index 76bd3ddc8c7..15b254093f9 100644 --- a/code/ATMOSPHERICS/components/unary_devices/unary_base.dm +++ b/code/ATMOSPHERICS/components/unary_devices/unary_base.dm @@ -23,6 +23,7 @@ return ..() /obj/machinery/atmospherics/unary/initialize() + ..() for(var/obj/machinery/atmospherics/target in get_step(src, dir)) if(target.initialize_directions & get_dir(target,src)) var/c = check_connect_types(target,src) diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 0a95353fff3..30908f68900 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -30,17 +30,6 @@ var/global/list/datum/pipeline/pipe_networks = list() update = 0 reconcile_air() return - /* - //Check to see if pressure is within acceptable limits - var/pressure = air.return_pressure() - if(pressure > alert_pressure) - for(var/obj/machinery/atmospherics/pipe/member in members) - if(!member.check_pressure(pressure)) - break //Only delete 1 pipe per process - //Allow for reactions - //air.react() //Should be handled by pipe_network now - */ - var/pipenetwarnings = 10 @@ -231,10 +220,10 @@ var/pipenetwarnings = 10 PL |= V.parent2 for(var/obj/machinery/atmospherics/trinary/tvalve/T in P.other_atmosmch) if(!T.state) - PL |= T.parent3 PL |= T.parent1 - else PL |= T.parent3 + else + PL |= T.parent1 PL |= T.parent2 for(var/obj/machinery/atmospherics/unary/portables_connector/C in P.other_atmosmch) if(C.connected_device) diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm index 6f70cf52465..35916a5b575 100644 --- a/code/ATMOSPHERICS/pipes/cap.dm +++ b/code/ATMOSPHERICS/pipes/cap.dm @@ -62,6 +62,7 @@ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap" + icon_connect_type) /obj/machinery/atmospherics/pipe/cap/initialize() + ..() for(var/obj/machinery/atmospherics/target in get_step(src, dir)) if(target.initialize_directions & get_dir(target,src)) var/c = check_connect_types(target,src) diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm index 555ee66dbfd..6e6a8569ad9 100644 --- a/code/ATMOSPHERICS/pipes/manifold.dm +++ b/code/ATMOSPHERICS/pipes/manifold.dm @@ -33,6 +33,7 @@ icon = null /obj/machinery/atmospherics/pipe/manifold/initialize() + ..() for(var/D in cardinal) if(D == dir) continue diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm index 8f8b8460486..be0019a43a2 100644 --- a/code/ATMOSPHERICS/pipes/manifold4w.dm +++ b/code/ATMOSPHERICS/pipes/manifold4w.dm @@ -152,6 +152,7 @@ update_icon() /obj/machinery/atmospherics/pipe/manifold4w/initialize() + ..() for(var/D in cardinal) for(var/obj/machinery/atmospherics/target in get_step(src, D)) if(target.initialize_directions & get_dir(target,src)) diff --git a/code/ATMOSPHERICS/pipes/pipe.dm b/code/ATMOSPHERICS/pipes/pipe.dm index 3f3a21e7789..7041d13993d 100644 --- a/code/ATMOSPHERICS/pipes/pipe.dm +++ b/code/ATMOSPHERICS/pipes/pipe.dm @@ -36,6 +36,16 @@ if(parent && isnull(parent.gcDestroyed)) qdel(parent) parent = null + +/obj/machinery/atmospherics/pipe/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/device/analyzer)) + atmosanalyzer_scan(parent.air, user) + return + + if(istype(W,/obj/item/device/pipe_painter)) + return + + return ..() /obj/machinery/atmospherics/proc/pipeline_expansion() return null diff --git a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm index 7908acc5321..c3d1762b993 100644 --- a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm +++ b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm @@ -44,6 +44,7 @@ initialize_directions = SOUTH|WEST /obj/machinery/atmospherics/pipe/simple/initialize() + ..() normalize_dir() var/N = 2 for(var/D in cardinal) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 5d63e777087..49ef7a72855 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -19,6 +19,8 @@ #define BANTYPE_JOB_TEMP 4 #define BANTYPE_ANY_FULLBAN 5 //used to locate stuff to unban. #define BANTYPE_APPEARANCE 6 +#define BANTYPE_ADMIN_PERMA 7 +#define BANTYPE_ADMIN_TEMP 8 //Please don't edit these values without speaking to Errorage first ~Carn //Admin Permissions diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 21de59e0216..0458944e956 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -334,7 +334,7 @@ Turf and target are seperate in case you want to teleport some distance from a t /obj/proc/atmosanalyzer_scan(var/datum/gas_mixture/air_contents, mob/user, var/obj/target = src) var/obj/icon = target - user.visible_message("[user] has used the analyzer on \icon[icon] [target].", "You use the analyzer on \icon[icon] [target].") + user.visible_message("[user] has used the analyzer on [target].", "You use the analyzer on [target].") var/pressure = air_contents.return_pressure() var/total_moles = air_contents.total_moles() diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index ac66623c72a..27da3c1fd4b 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -50,7 +50,8 @@ var/global/list/blocked_mobs = list(/mob/living/simple_animal/hostile, /mob/living/simple_animal/hostile/spaceWorm/wormHead, /mob/living/simple_animal/ascendant_shadowling, /mob/living/simple_animal/slaughter, - /mob/living/simple_animal/hostile/retaliate/araneus + /mob/living/simple_animal/hostile/retaliate/araneus, + /mob/living/simple_animal/hostile/syndicate/ranged/orion ) var/global/list/med_hud_users = list() diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index c832bcc03d4..a001c55082f 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -11,6 +11,7 @@ var/global/list/joblist = list() //list of all jobstypes, minus borg and AI var/global/list/flag_list = list() //list of flags during Nations gamemode var/global/list/airlocks = list() //list of all airlocks var/global/list/singularities = list() //list of all singularities +var/global/list/janitorial_equipment = list() //list of janitorial equipment var/global/list/aibots = list() // AI controlled bots var/global/list/table_recipes = list() //list of all table craft recipes diff --git a/code/datums/vision_override.dm b/code/datums/vision_override.dm new file mode 100644 index 00000000000..140ceb8d5fa --- /dev/null +++ b/code/datums/vision_override.dm @@ -0,0 +1,16 @@ +/datum/vision_override + var/name = "vision override" + var/see_in_dark = 0 + var/see_invisible = 0 + var/light_sensitive = 0 + var/sight_flags = 0 + +/datum/vision_override/nightvision + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + +/datum/vision_override/nightvision/thermals + sight_flags = SEE_MOBS + +/datum/vision_override/nightvision/thermals/ling_augmented_eyesight + light_sensitive = 1 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a38d22e6ff6..eb28028cac4 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -80,10 +80,10 @@ last_move = 0 return + last_move = direct src.move_speed = world.timeofday - src.l_move_time src.l_move_time = world.timeofday - last_move = direct spawn(5) // Causes space drifting. /tg/station has no concept of speed, we just use 5 @@ -154,7 +154,7 @@ if(pulledby) return 1 - if(locate(/obj/structure/lattice) in orange(1, get_turf(src))) //Not realistic but makes pushing things in space easier + if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier return 1 return 0 diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index d74b2672360..cbd7772f535 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -217,10 +217,13 @@ return beaker = item - user.drop_item() - item.loc = src - user.visible_message("[user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!") - return + if(user.drop_item()) + item.forceMove(src) + user.visible_message("[user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!") + return + else + user << "\The [item] is stuck to you!" + return else if (!istype(item, /obj/item/weapon/grab)) return var/obj/item/weapon/grab/G = item diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index 496688835bb..a365a45673c 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -19,6 +19,9 @@ /obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user) return +/obj/effect/proc_holder/changeling/proc/on_refund(mob/user) + return + /obj/effect/proc_holder/changeling/Click() var/mob/user = usr if(!user || !user.mind || !user.mind.changeling) diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index aee7e164845..ee6c6f50645 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -406,8 +406,10 @@ var/list/sting_paths mind.changeling.changeling_speak = 0 mind.changeling.reset() for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers) - if(!(p.dna_cost == 0 && keep_free_powers)) - mind.changeling.purchasedpowers -= p + if(p.dna_cost == 0 && keep_free_powers) + continue + mind.changeling.purchasedpowers -= p + p.on_refund(src) remove_language("Changeling") /datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power) diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index d40da71fff1..d303d022753 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -7,18 +7,15 @@ helptext = "Grants us night vision and thermal vision. It may be toggled on or off." chemical_cost = 0 dna_cost = 2 //Would be 1 without thermal vision - var/active = 0 //Whether or not vision is enhanced /obj/effect/proc_holder/changeling/augmented_eyesight/sting_action(var/mob/user) - active = !active - if(active) + if(!user.vision_type) user << "We feel a minute twitch in our eyes, and darkness creeps away." + user.vision_type = new /datum/vision_override/nightvision/thermals/ling_augmented_eyesight else user << "Our vision dulls. Shadows gather." - user.sight &= ~SEE_MOBS - while(active) - user.see_in_dark = 8 - user.see_invisible = 2 - user.sight |= SEE_MOBS - sleep(1) //BAD THINGS HAPPEN WITHOUT THIS. + user.vision_type = null return 1 + +/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) + user.vision_type = null \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm index 9a4b144cc71..3a0fb785f19 100644 --- a/code/game/gamemodes/changeling/powers/fakedeath.dm +++ b/code/game/gamemodes/changeling/powers/fakedeath.dm @@ -18,7 +18,7 @@ if(user.stat != DEAD) user.emote("deathgasp") - user.tod = worldtime2text() + user.timeofdeath = worldtime2text() spawn(800) if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers) diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 8e4313b92b0..e5cc89aeaed 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -5,12 +5,10 @@ //Revive from regenerative stasis /obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user) - if(user.stat == DEAD) dead_mob_list -= user - living_mob_list += user + living_mob_list |= user user.stat = CONSCIOUS - user.tod = null user.setToxLoss(0) user.setOxyLoss(0) user.setCloneLoss(0) diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 1cc2cd9d469..05d778c8b5a 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -135,6 +135,7 @@ Made by Xhuis var/mob/living/carbon/human/S = shadow_mind.current shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_hatch) shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall) + shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision) spawn(0) shadow_mind.current.add_language("Shadowling Hivemind") update_shadow_icons_added(shadow_mind) @@ -154,7 +155,7 @@ Made by Xhuis new_thrall_mind.current.add_language("Shadowling Hivemind") new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_glare) new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) - //new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/thrall_vision) //Uncomment when vision code is unfucked. + new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall) new_thrall_mind.current << "You see the truth. Reality has been torn away and you realize what a fool you've been." new_thrall_mind.current << "The shadowlings are your masters. Serve them above all else and ensure they complete their goals." new_thrall_mind.current << "You may not harm other thralls or the shadowlings. However, you do not need to obey other thralls." @@ -210,7 +211,7 @@ Made by Xhuis else shadowling_dead = 1 //but shadowling was kill :( return 1 - + /datum/game_mode/proc/remove_shadowling(datum/mind/ling_mind) if(!istype(ling_mind) || !(ling_mind in shadows)) return 0 update_shadow_icons_removed(ling_mind) @@ -304,7 +305,7 @@ Made by Xhuis flesh_color = "#222222" flags = NO_BLOOD | NO_BREATHE | NO_SCAN | NO_INTORGANS - burn_mod = 2 //2x burn damage + burn_mod = 1.5 //1.5x burn damage, 2x is excessive /datum/game_mode/proc/update_shadow_icons_added(datum/mind/shadow_mind) spawn(0) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index fbc3b08e60a..0a626d2ec78 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -85,10 +85,20 @@ else if(istype(I, /obj/item/clothing/head/helmet/space/rig)) var/obj/item/clothing/head/helmet/space/rig/R = I if(R.on) - R.on = 0 - R.icon_state = "rig[R.on]-[R._color]" + R.toggle_light() R.visible_message("[R]'s light fades and turns off.") - R.set_light(0) + else if(istype(I, /obj/item/clothing/head/helmet/space/eva/plasmaman)) + var/obj/item/clothing/head/helmet/space/eva/plasmaman/P = I + if(P.on) + P.toggle_light() + P.visible_message("[P]'s light fades and turns off.") + else if(istype(I, /obj/item/weapon/gun)) + var/obj/item/weapon/gun/G = I + if(G.F) + var/obj/item/device/flashlight/F = G.F + if(F.on) + G.toggle_gunlight() + G.visible_message("[G]'s light fades and turns off.") return I.light_range /obj/effect/proc_holder/spell/aoe_turf/veil/proc/extinguishMob(var/mob/living/H) @@ -170,32 +180,34 @@ user.visible_message("[user] appears from nowhere!", "Your shadowy guise slips away.") user.alpha = initial(user.alpha) -/* -/obj/effect/proc_holder/spell/targeted/thrall_vision //Uncomment this if we ever update our vision code to not be absolute garbage. - name = "Darksight" - desc = "Gives you night vision." - panel = "Thrall Abilities" + +/obj/effect/proc_holder/spell/targeted/shadow_vision + name = "Shadowling Darksight" + desc = "Gives you night and thermal vision." + panel = "Shadowling Abilities" charge_max = 0 range = -1 include_user = 1 clothes_req = 0 - var/active = 0 + var/datum/vision_override/vision_path = /datum/vision_override/nightvision/thermals -/obj/effect/proc_holder/spell/targeted/thrall_vision/cast(list/targets) +/obj/effect/proc_holder/spell/targeted/shadow_vision/cast(list/targets) for(var/mob/living/user in targets) if(!istype(user) || !ishuman(user)) return var/mob/living/carbon/human/H = user - active = !active - if(active) - user << "You shift the nerves in your eyes, allowing you to see in the dark." - H.see_in_dark = 8 - H.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM + if(!H.vision_type) + H << "You shift the nerves in your eyes, allowing you to see in the dark." + H.vision_type = new vision_path else - user << "You return your vision to normal." - H.see_in_dark = 0 - H.dna.species.invis_sight = initial(H.dna.species.invis_sight) -*/ + H << "You return your vision to normal." + H.vision_type = null + +/obj/effect/proc_holder/spell/targeted/shadow_vision/thrall + desc = "Thrall Darksight" + desc = "Gives you night vision." + panel = "Thrall Abilities" + vision_path = /datum/vision_override/nightvision /obj/effect/proc_holder/spell/aoe_turf/flashfreeze name = "Icy Veins" diff --git a/code/game/gamemodes/shadowling/shadowling_items.dm b/code/game/gamemodes/shadowling/shadowling_items.dm index e494c7507f0..863ea9c43a6 100644 --- a/code/game/gamemodes/shadowling/shadowling_items.dm +++ b/code/game/gamemodes/shadowling/shadowling_items.dm @@ -66,17 +66,13 @@ flags = ABSTRACT | NODROP -/obj/item/clothing/glasses/night/shadowling +/obj/item/clothing/glasses/shadowling name = "crimson eyes" desc = "A shadowling's eyes. Very light-sensitive and can detect body heat through walls." icon = null icon_state = null item_state = null origin_tech = null - vision_flags = SEE_MOBS - darkness_view = 8 - see_darkness = 0 - invisa_view = 2 unacidable = 1 flash_protect = -1 flags = ABSTRACT | NODROP diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm index bb4fc80c7d6..8692757ccfc 100644 --- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm @@ -13,6 +13,9 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N /obj/effect/proc_holder/spell/targeted/shadowling_hatch/cast(list/targets) if(usr.stat || !ishuman(usr) || !usr) return + if(!isturf(usr.loc)) + usr << "You can't hatch here!" + return for(var/mob/living/carbon/human/H in targets) var/hatch_or_no = alert(H,"Are you sure you want to hatch? You cannot undo this!",,"Yes","No") switch(hatch_or_no) @@ -79,6 +82,8 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.undershirt = "None" H.socks = "None" H.faction |= "faithless" + if(!H.weakeyes) + H.weakeyes = 1 H.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(usr), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(usr), slot_shoes) @@ -86,7 +91,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.equip_to_slot_or_del(new /obj/item/clothing/head/shadowling(usr), slot_head) H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(usr), slot_glasses) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/shadowling(usr), slot_glasses) H.set_species("Shadowling") sleep(10) diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index b5ad01dd92d..256eb2ca69c 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -294,7 +294,7 @@ title = "Janitor" flag = JANITOR department_flag = SUPPORT - total_positions = 1 + total_positions = 2 spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index e80d9dfe889..2ff04e63f6a 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -493,7 +493,7 @@ var/global/datum/controller/occupations/job_master if(istype(G) && !G.prescription) G.prescription = 1 G.name = "prescription [G.name]" -// H.update_icons() + H.regenerate_icons() H.hud_updateflag |= (1 << ID_HUD) H.hud_updateflag |= (1 << IMPLOYAL_HUD) @@ -541,7 +541,6 @@ var/global/datum/controller/occupations/job_master pda.ownjob = C.assignment pda.ownrank = C.rank pda.name = "PDA-[H.real_name] ([pda.ownjob])" - pda.JFLOG("Created") return 1 diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index eafbb40fa19..582a8466e22 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -299,12 +299,14 @@ /obj/machinery/sleeper/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob, params) if(istype(G, /obj/item/weapon/reagent_containers/glass)) if(!beaker) - beaker = G - user.drop_item() - G.loc = src - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") - src.updateUsrDialog() - return + if (user.drop_item()) + beaker = G + G.forceMove(src) + user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + src.updateUsrDialog() + return + else + user << "\The [G] is stuck to you!" else user << "\red The sleeper has a beaker already." return @@ -611,4 +613,4 @@ qdel(O) src.add_fingerprint(usr) return - return \ No newline at end of file + return diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 5ab92bd3088..a62f87ee098 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -205,8 +205,9 @@ user << "You [anchored ? "wrench" : "unwrench"] \the [src]." return - ..() - + else if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) + atmosanalyzer_scan(air_contents, user) + /obj/machinery/portable_atmospherics/scrubber/huge/stationary name = "Stationary Air Scrubber" stationary = 1 \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 2df598a5001..891be23fdf2 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -66,7 +66,7 @@ /obj/machinery/clonepod/Destroy() if(connected) connected.pods -= src - ..() + return ..() /obj/machinery/clonepod/RefreshParts() speed_coeff = 0 diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index cc192ec8c53..31fa24feb6f 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -22,10 +22,10 @@ /obj/machinery/computer/cloning/initialize() ..() updatemodules() - + /obj/machinery/computer/cloning/Destroy() releasecloner() - ..() + return ..() /obj/machinery/computer/cloning/process() if(!scanner || !pods.len || !autoprocess) @@ -39,8 +39,8 @@ for(var/datum/dna2/record/R in src.records) if(!(pod.occupant || pod.mess)) if(pod.growclone(R)) - records.Remove(R) - + records.Remove(R) + /obj/machinery/computer/cloning/proc/updatemodules() src.scanner = findscanner() releasecloner() @@ -119,23 +119,23 @@ return var/data[0] data["menu"] = src.menu - data["scanner"] = src.scanner - + data["scanner"] = src.scanner + var/canpodautoprocess = 0 if(pods.len) data["numberofpods"] = src.pods.len - + var/list/tempods[0] for (var/obj/machinery/clonepod/pod in pods) if(pod.efficiency > 5) canpodautoprocess = 1 - + tempods.Add(list(list("pod" = "\ref[pod]", "name" = capitalize(pod.name), "biomass" = pod.biomass))) data["pods"] = tempods - + data["loading"] = loading data["autoprocess"] = autoprocess - + if(scanner && pods.len && ((scanner.scan_level > 2) || canpodautoprocess)) data["autoallowed"] = 1 else @@ -257,11 +257,11 @@ src.active_record = src.diskette.buf src.temp = "Load successful." - + if("eject") if (!isnull(src.diskette)) src.diskette.loc = src.loc - src.diskette = null + src.diskette = null else if (href_list["save_disk"]) //Save to disk! if ((isnull(src.diskette)) || (src.diskette.read_only) || (isnull(src.active_record))) @@ -284,7 +284,7 @@ else if (href_list["refresh"]) nanomanager.update_uis(src) - + else if (href_list["selectpod"]) var/obj/machinery/clonepod/selected = locate(href_list["selectpod"]) if(istype(selected) && (selected in pods)) @@ -297,7 +297,7 @@ //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. if(!pods.len) temp = "Error: No cloning pod detected." - else + else var/obj/machinery/clonepod/pod = selected_pod if (!selected_pod) temp = "Error: No cloning pod selected." diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index bb7a54daf4b..38cbb0fb4c6 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -153,7 +153,7 @@ if(istype(P, /obj/item)) var/success for(var/I in req_components) - if(istype(P, I) && (req_components[I] > 0)) + if(istype(P, I) && (req_components[I] > 0) && !(P.flags & NODROP)) success=1 playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) if(istype(P, /obj/item/stack/cable_coil)) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index c35eaacf9f8..53f903121ad 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -279,9 +279,11 @@ return beaker = G - user.drop_item() - G.loc = src - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + if(user.drop_item()) + G.forceMove(src) + user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + else + user << "The [G] is stuck to you!" if (istype(G, /obj/item/weapon/screwdriver)) if(occupant || on) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 680f9317bfd..a9559ea01f6 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -83,14 +83,6 @@ else flick("door_deny", src) return - if(istype(AM, /obj/structure/stool/bed/chair/wheelchair)) - var/obj/structure/stool/bed/chair/wheelchair/wheel = AM - if(density) - if(wheel.pulling && (src.allowed(wheel.pulling))) - open() - else - flick("door_deny", src) - return return diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index e32146ff69f..f22c68bb0f0 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -79,6 +79,9 @@ continue O.Weaken(strength) + if(O.weakeyes) + O.Weaken(strength * 1.5) + O.visible_message("[O] gasps and shields their eyes!") if (istype(O, /mob/living/carbon/human)) var/mob/living/carbon/human/H = O var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"] diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 870018c54b3..e3bb3d32eaa 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -63,12 +63,14 @@ user << "There is already a reagent container loaded!" return - user.drop_item() - W.loc = src - src.beaker = W - user << "You attach \the [W] to \the [src]." - src.update_icon() - return + if(user.drop_item()) + W.forceMove(src) + src.beaker = W + user << "You attach \the [W] to \the [src]." + src.update_icon() + return + else + user << "\The [W] is stuck to you!" else return ..() @@ -167,4 +169,4 @@ else user << "\blue No chemicals are attached." - user << "\blue [attached ? attached : "No one"] is attached." \ No newline at end of file + user << "\blue [attached ? attached : "No one"] is attached." diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 667602686b5..9815035311e 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -143,6 +143,8 @@ src.pipe_type = PIPE_INJECTOR else if(istype(make_from, /obj/machinery/atmospherics/binary/dp_vent_pump)) src.pipe_type = PIPE_DP_VENT + else if(istype(make_from, /obj/machinery/atmospherics/unary/passive_vent)) + src.pipe_type = PIPE_PASV_VENT else if(istype(make_from, /obj/machinery/atmospherics/omni/mixer)) src.pipe_type = PIPE_OMNI_MIXER @@ -164,7 +166,7 @@ src.color = PIPE_COLOR_RED else if (pipe_type == PIPE_UNIVERSAL) connect_types = list(1,2,3) - //src.pipe_dir = get_pipe_dir() + update(make_from) src.pixel_x = rand(-5, 5) src.pixel_y = rand(-5, 5) @@ -275,14 +277,8 @@ src.dir = turn(src.dir, -90) - if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE)) - if(dir==2) - dir = 1 - else if(dir==8) - dir = 4 - else if (pipe_type in list (PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W)) - dir = 2 - //src.pipe_dir = get_pipe_dir() + fixdir() + return /obj/item/pipe/verb/flip() @@ -406,22 +402,6 @@ //Helper to clean up dir /obj/item/pipe/proc/fixdir() - if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE)) - if(dir==2) - dir = 1 - else if(dir==8) - dir = 4 - -/obj/item/pipe/attack_self(mob/user as mob) - return rotate() - -/obj/item/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob, params) - ..() - //* - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!isturf(src.loc)) - return 1 if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE)) if(dir==2) dir = 1 @@ -429,15 +409,27 @@ dir = 4 else if (pipe_type in list(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER)) dir = 2 + +/obj/item/pipe/attack_self(mob/user as mob) + return rotate() + +/obj/item/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob, params) + ..() + + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + + if (!isturf(src.loc)) + return 1 + + fixdir() + var/pipe_dir = get_pipe_dir() for(var/obj/machinery/atmospherics/M in src.loc) if((M.initialize_directions & pipe_dir) && M.check_connect_types_construction(M,src)) // matches at least one direction on either type of pipe - user << "\red There is already a pipe of the same type at this location." + user << "There is already a pipe of the same type at this location." return 1 - // no conflicts found - - var/obj/machinery/atmospherics/machineReference = null //If somebody wants to overhaul that switch statement below, be my guest. Easier to set a reference here and then transfer logs after the switch statement. switch(pipe_type) //What kind of heartless person thought of doing this? if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT) @@ -583,6 +575,12 @@ if (pipename) P.name = pipename P.construction(dir, pipe_dir, color) + + if(PIPE_PASV_VENT) + var/obj/machinery/atmospherics/unary/passive_vent/P = new(src.loc) + if (pipename) + P.name = pipename + P.construction(dir, pipe_dir, color) if(PIPE_OMNI_MIXER) var/obj/machinery/atmospherics/omni/mixer/P = new(loc) @@ -597,17 +595,9 @@ "[user] fastens the [src].", \ "\blue You have fastened the [src].", \ "You hear ratchet.") - if(machineReference) - transfer_fingerprints_to(machineReference) - machineReference.add_fingerprint(user) qdel(src) // remove the pipe item return - //TODO: DEFERRED - -// ensure that setterm() is called for a newly connected pipeline - - /obj/item/pipe_meter name = "meter" diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 133ce3814df..8a52c2653e3 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -79,7 +79,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() req_console_supplies |= department if (departmentType & RC_INFO) req_console_information |= department - + set_light(1) /obj/machinery/requests_console/Destroy() @@ -96,14 +96,14 @@ var/list/obj/machinery/requests_console/allConsoles = list() req_console_supplies -= department if (departmentType & RC_INFO) req_console_information -= department - ..() + return ..() /obj/machinery/requests_console/attack_ghost(user as mob) if(stat & NOPOWER) return - - ui_interact(user) - + + ui_interact(user) + /obj/machinery/requests_console/attack_hand(user as mob) if(..(user)) return @@ -138,7 +138,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() ui.set_auto_update(1) /obj/machinery/requests_console/Topic(href, href_list) - if(..()) + if(..()) return 1 usr.set_machine(src) add_fingerprint(usr) diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index f80fe007d26..bed4da6fe2f 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -287,7 +287,7 @@ Destroy() rcd_list -= src - ..() + return ..() action(atom/target) if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index a3ec474fb08..8588baa80df 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -5,13 +5,13 @@ var/obj/machinery/mech_bay_recharge_port/recharge_port var/obj/machinery/computer/mech_bay_power_console/recharge_console var/obj/mecha/recharging_mecha = null - + /turf/simulated/floor/mech_bay_recharge_floor/airless icon_state = "recharge_floor_asteroid" oxygen = 0.01 nitrogen = 0.01 temperature = TCMB - + /turf/simulated/floor/mech_bay_recharge_floor/Destroy() if(recharge_console && recharge_console.recharge_floor == src) recharge_console.recharge_floor = null @@ -36,7 +36,7 @@ else if(!recharge_port) mecha.occupant_message("Power port not found. Terminating.") return - + /turf/simulated/floor/mech_bay_recharge_floor/Exited(atom) . = ..() if(atom == recharging_mecha) @@ -91,7 +91,7 @@ component_parts += new /obj/item/weapon/stock_parts/capacitor(null) component_parts += new /obj/item/stack/cable_coil(null, 1) RefreshParts() - + pr_recharger = new /datum/global_iterator/mech_bay_recharger(null,0) /obj/machinery/mech_bay_recharge_port/upgraded/New() @@ -114,12 +114,12 @@ pr_recharger.max_charge = MC * 10 if(recharge_console) recharge_console.voltage = MC * 10 - + /obj/machinery/mech_bay_recharge_port/Destroy() recharge_console.recharge_port = null recharge_floor.recharge_port = null - ..() - + return ..() + /obj/machinery/mech_bay_recharge_port/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, "recharge_port-o", "recharge_port", I)) return @@ -131,7 +131,7 @@ return default_deconstruction_crowbar(I) - + /obj/machinery/mech_bay_recharge_port/proc/start_charge(var/obj/mecha/recharging_mecha) if(stat&(NOPOWER|BROKEN)) recharging_mecha.occupant_message("Power port not responding. Terminating.") @@ -149,13 +149,13 @@ update_icon() pr_recharger.stop() return - + /obj/machinery/mech_bay_recharge_port/proc/active() if(pr_recharger.active()) return 1 else return 0 - + /obj/machinery/mech_bay_recharge_port/power_change() if(powered()) @@ -165,7 +165,7 @@ stat |= NOPOWER pr_recharger.stop() return - + /obj/machinery/mech_bay_recharge_port/proc/set_voltage(new_voltage) if(new_voltage && isnum(new_voltage)) pr_recharger.max_charge = new_voltage @@ -177,7 +177,7 @@ delay = 20 var/max_charge = 50 check_for_null = 0 //since port.stop_charge() must be called. The checks are made in process() - + /datum/global_iterator/mech_bay_recharger/process(var/obj/machinery/mech_bay_recharge_port/port, var/obj/mecha/mecha) if(!port) return 0 @@ -208,11 +208,11 @@ var/voltage = 50 var/turf/simulated/floor/mech_bay_recharge_floor/recharge_floor var/obj/machinery/mech_bay_recharge_port/recharge_port - + /obj/machinery/computer/mech_bay_power_console/Destroy() recharge_port.recharge_console = null recharge_floor.recharge_console = null - ..() + return ..() /obj/machinery/computer/mech_bay_power_console/proc/mecha_in(var/obj/mecha/mecha) if(stat&(NOPOWER|BROKEN)) @@ -251,7 +251,7 @@ ..() if(recharge_port) recharge_port.stop_charge() - + /obj/machinery/computer/mech_bay_power_console/update_icon() if(!recharge_floor || !recharge_floor.recharging_mecha || !recharge_floor.recharging_mecha.cell || !(recharge_floor.recharging_mecha.cell.charge < recharge_floor.recharging_mecha.cell.maxcharge)) icon_screen = "recharge_comp" diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 859834960ff..076e85c6de0 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -74,9 +74,6 @@ var/global/list/image/splatter_cache=list() if(!perp.feet_blood_DNA) perp.feet_blood_DNA = list() perp.feet_blood_DNA |= blood_DNA.Copy() - else if (perp.buckled && istype(perp.buckled, /obj/structure/stool/bed/chair/wheelchair)) - var/obj/structure/stool/bed/chair/wheelchair/W = perp.buckled - W.bloodiness = 4 perp.update_inv_shoes(1) amount-- diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 74c1f2f51ff..842501da8a1 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -284,7 +284,6 @@ var/global/list/obj/item/device/pda/PDAs = list() if(usr.stat == 2) usr << "You can't do that because you are dead!" return - JFLOG("AI Showed Message Log") var/HTML = "AI PDA Message Log" for(var/index in tnote) if(index["sent"]) @@ -301,7 +300,6 @@ var/global/list/obj/item/device/pda/PDAs = list() if(usr.stat == 2) usr << "You can't do that because you are dead!" return - JFLOG("AI Toggled Receiver") toff = !toff usr << "PDA sender/receiver toggled [(toff ? "Off" : "On")]!" @@ -314,7 +312,6 @@ var/global/list/obj/item/device/pda/PDAs = list() usr << "You can't do that because you are dead!" return silent=!silent - JFLOG("AI toggled the silent option") usr << "PDA ringer toggled [(silent ? "Off" : "On")]!" /obj/item/device/pda/ai/can_use() @@ -325,7 +322,6 @@ var/global/list/obj/item/device/pda/PDAs = list() if ((honkamt > 0) && (prob(60)))//For clown virus. honkamt-- playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - JFLOG("[user] PDA honked") return @@ -528,15 +524,11 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/attack_self(mob/user as mob) user.set_machine(src) if(active_uplink_check(user)) - JFLOG("[user] activated a syndicate uplink in their PDA") return - JFLOG("[user] activated PDA") ui_interact(user) //NanoUI requires this proc return /obj/item/device/pda/Topic(href, href_list) - if (href_list["choice"]!="Return") // We really don't need to see ten thousand return actions. - JFLOG("UI Action >>> HREF|[href] >>> HREF_LIST|[list2json(href_list)]") if(href_list["cartmenu"] && !isnull(cartridge)) cartridge.Topic(href, href_list) return 1 @@ -964,7 +956,6 @@ var/global/list/obj/item/device/pda/PDAs = list() if ( can_use(usr) ) if(id) - JFLOG("[usr] removed ID:[id]") remove_id() else usr << "This PDA does not have an ID in it." @@ -981,7 +972,6 @@ var/global/list/obj/item/device/pda/PDAs = list() return if ( can_use(usr) ) - JFLOG("[usr] removed pen") var/obj/item/weapon/pen/O = locate() in src if(O) if (istype(loc, /mob)) @@ -1021,7 +1011,6 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob, params) ..() if(istype(C, /obj/item/weapon/cartridge) && !cartridge) - JFLOG("[user] inserted Cartridge[cartridge]") cartridge = C user.drop_item() cartridge.loc = src @@ -1033,7 +1022,6 @@ var/global/list/obj/item/device/pda/PDAs = list() else if(istype(C, /obj/item/weapon/card/id)) var/obj/item/weapon/card/id/idcard = C if(!idcard.registered_name) - JFLOG("[user] tried to insert ID:[idcard] but it was rejected.") user << "\The [src] rejects the ID." return if(!owner) @@ -1042,14 +1030,12 @@ var/global/list/obj/item/device/pda/PDAs = list() ownrank = idcard.rank name = "PDA-[owner] ([ownjob])" user << "Card scanned." - JFLOG("[user] tried to insert ID:[idcard] and it was used to initialize this PDA.") else //Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand. if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) ) if( can_use(user) )//If they can still act. id_check(user, 2) user << "You put the ID into \the [src]'s slot." - JFLOG("[user] inserted ID:[idcard].") updateSelfDialog()//Update self dialog on success. return //Return in case of failed check or when successful. updateSelfDialog()//For the non-input related code. @@ -1058,7 +1044,6 @@ var/global/list/obj/item/device/pda/PDAs = list() C.loc = src pai = C user << "You slot \the [C] into [src]." - JFLOG("[user] inserted PAI:[pai]") nanomanager.update_uis(src) // update all UIs attached to src else if(istype(C, /obj/item/weapon/pen)) var/obj/item/weapon/pen/O = locate() in src @@ -1067,7 +1052,6 @@ var/global/list/obj/item/device/pda/PDAs = list() else user.drop_item() C.loc = src - JFLOG("[user] inserted PEN:[C]") user << "You slide \the [C] into \the [src]." return @@ -1075,7 +1059,6 @@ var/global/list/obj/item/device/pda/PDAs = list() if (istype(C, /mob/living/carbon)) switch(scanmode) if(1) - JFLOG("[user] used the medical scanner on [C]") for (var/mob/O in viewers(C, null)) O.show_message("\red [user] has analyzed [C]'s vitals!", 1) @@ -1084,8 +1067,8 @@ var/global/list/obj/item/device/pda/PDAs = list() user.show_message("\blue \t Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1) user.show_message("\blue \t Key: Suffocation/Toxin/Burns/Brute", 1) user.show_message("\blue \t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) - if(C.tod && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) - user.show_message("\blue \t Time of Death: [C.tod]") + if(C.timeofdeath && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) + user.show_message("\blue \t Time of Death: [C.timeofdeath]") if(istype(C, /mob/living/carbon/human)) var/mob/living/carbon/human/H = C var/list/damaged = H.get_damaged_organs(1,1) @@ -1097,7 +1080,6 @@ var/global/list/obj/item/device/pda/PDAs = list() user.show_message("\blue \t Limbs are OK.",1) if(2) - JFLOG("[user] used the fingerprint scanner on [C]") if (!istype(C:dna, /datum/dna)) user << "\blue No fingerprints found on [C]" else @@ -1113,7 +1095,6 @@ var/global/list/obj/item/device/pda/PDAs = list() user << "\blue Blood type: [C:blood_DNA[blood]]\nDNA: [blood]" if(4) - JFLOG("[user] used the radiation scanner on [C]") for (var/mob/O in viewers(C, null)) O.show_message("\red [user] has analyzed [C]'s radiation levels!", 1) @@ -1128,22 +1109,18 @@ var/global/list/obj/item/device/pda/PDAs = list() switch(scanmode) if(3) - JFLOG("[user] used the reagent scanner on [A]") - if(!isobj(A)) - return if(!isnull(A.reagents)) if(A.reagents.reagent_list.len > 0) var/reagents_length = A.reagents.reagent_list.len - user << "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." + user << "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." for (var/re in A.reagents.reagent_list) - user << "\blue \t [re]" + user << "\t [re]" else - user << "\blue No active chemical agents found in [A]." + user << "No active chemical agents found in [A]." else - user << "\blue No significant chemical agents found in [A]." + user << "No significant chemical agents found in [A]." if(5) - JFLOG("[user] used the air analysis scanner on [A]") if (istype(A, /obj/item/weapon/tank)) var/obj/item/weapon/tank/T = A atmosanalyzer_scan(T.air_contents, user, T) @@ -1159,59 +1136,51 @@ var/global/list/obj/item/device/pda/PDAs = list() else if (istype(A, /obj/item/weapon/flamethrower)) var/obj/item/weapon/flamethrower/T = A if(T.ptank) atmosanalyzer_scan(T.ptank.air_contents, user, T) + else if (istype(A, /obj/machinery/portable_atmospherics/scrubber/huge)) + var/obj/machinery/portable_atmospherics/scrubber/huge/T = A + atmosanalyzer_scan(T.air_contents, user, T) + else if (istype(A, /obj/machinery/atmospherics/unary/tank)) + var/obj/machinery/atmospherics/unary/tank/T = A + atmosanalyzer_scan(T.air_contents, user, T) if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) - JFLOG("[user] used the document scanner on [A]") // JMO 20140705: Makes scanned document show up properly in the notes. Not pretty for formatted documents, // as this will clobber the HTML, but at least it lets you scan a document. You can restore the original // notes by editing the note again. (Was going to allow you to edit, but scanned documents are too long.) var/raw_scan = (A:info) var/formatted_scan = "" // Scrub out the tags (replacing a few formatting ones along the way) - // Find the beginning and end of the first tag. var/tag_start = findtext(raw_scan,"<") var/tag_stop = findtext(raw_scan,">") - // Until we run out of complete tags... while(tag_start&&tag_stop) var/pre = copytext(raw_scan,1,tag_start) // Get the stuff that comes before the tag var/tag = lowertext(copytext(raw_scan,tag_start+1,tag_stop)) // Get the tag so we can do intellegent replacement var/tagend = findtext(tag," ") // Find the first space in the tag if there is one. - // Anything that's before the tag can just be added as is. formatted_scan = formatted_scan+pre - // If we have a space after the tag (and presumably attributes) just crop that off. if (tagend) tag=copytext(tag,1,tagend) - if (tag=="p"||tag=="/p"||tag=="br") // Check if it's I vertical space tag. formatted_scan=formatted_scan+"
" // If so, add some padding in. - raw_scan = copytext(raw_scan,tag_stop+1) // continue on with the stuff after the tag - // Look for the next tag in what's left tag_start = findtext(raw_scan,"<") tag_stop = findtext(raw_scan,">") - // Anything that is left in the page. just tack it on to the end as is formatted_scan=formatted_scan+raw_scan - // If there is something in there already, pad it out. if (length(note)>0) note = note + "

" - // Store the scanned document to the notes note = "Scanned Document. Edit to restore previous notes/delete scan.
----------
" + formatted_scan + "
" // notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents" // feature to the PDA, which would better convey the availability of the feature, but this will work for now. - // Inform the user user << "\blue Paper scanned and OCRed to notekeeper." //concept of scanning paper copyright brainoblivion 2009 - - /obj/item/device/pda/proc/explode() //This needs tuning. if(!src.detonate) return var/turf/T = get_turf(src.loc) @@ -1224,12 +1193,10 @@ var/global/list/obj/item/device/pda/PDAs = list() T.hotspot_expose(700,125) explosion(T, -1, -1, 2, 3) - JFLOG("Exploded") qdel(src) return /obj/item/device/pda/Destroy() - JFLOG("Destroyed") PDAs -= src if (src.id) src.id.loc = get_turf(src.loc) @@ -1249,7 +1216,6 @@ var/global/list/obj/item/device/pda/PDAs = list() M.stop_pulling() M << "\blue You slipped on the PDA!" - JFLOG("Clown PDA Slipped [M]") playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(8) M.Weaken(5) @@ -1310,28 +1276,4 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/emp_act(severity) for(var/atom/A in src) A.emp_act(severity) - -/** -* -* JFLOG -* -* These functions as well as all the log statements are being used to gather user data for how -* people are using the PDA files with the intent of revising them based on this data. -* -* They are being added on 28/03/2015 and the intent is to remove them in two weeks. If you're -* reading this and it's substantially past that point, you should remove anything marked with -* 'JFLOG'. -* -* All changes should be contained to PDA.dm except the creation function which is contained in -* job_controller.dm. -* -* - Jack Fractal -**/ - - -/obj/item/device/pda/proc/JFLOG_DescribeSelf() - return "([src]|[cartridge ? cartridge.name : "None"])" - -/obj/item/device/pda/proc/JFLOG(message as text) - if (config) - log_pda("[JFLOG_DescribeSelf()] >>> [message]") + \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index e44fb712774..670d02af975 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -174,7 +174,7 @@ /obj/item/weapon/cartridge/rd/initialize() radio = new /obj/item/radio/integrated/signal(src) - ..() + ..() /obj/item/weapon/cartridge/captain name = "Value-PAK Cartridge" @@ -191,7 +191,7 @@ /obj/item/weapon/cartridge/captain/initialize() radio = new /obj/item/radio/integrated/beepsky(src) - ..() + ..() /obj/item/weapon/cartridge/supervisor name = "Easy-Record DELUXE" @@ -282,7 +282,7 @@ /* Power Monitor (Mode: 43 / 433) */ - if(mode==43 || mode==433) + if(mode==43 || mode==433) values["powermonitors"] = powermonitor_repository.powermonitor_data() if (powmonitor && !isnull(powmonitor.powernet)) @@ -463,7 +463,7 @@ else JaniData["user_loc"] = list("x" = 0, "y" = 0) var/MopData[0] - for(var/obj/item/weapon/mop/M in world) + for(var/obj/item/weapon/mop/M in janitorial_equipment) var/turf/ml = get_turf(M) if(ml) if(ml.z != cl.z) @@ -476,7 +476,7 @@ var/BucketData[0] - for(var/obj/structure/mopbucket/B in world) + for(var/obj/structure/mopbucket/B in janitorial_equipment) var/turf/bl = get_turf(B) if(bl) if(bl.z != cl.z) @@ -488,7 +488,7 @@ BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) var/CbotData[0] - for(var/obj/machinery/bot/cleanbot/B in world) + for(var/obj/machinery/bot/cleanbot/B in aibots) var/turf/bl = get_turf(B) if(bl) if(bl.z != cl.z) @@ -500,7 +500,7 @@ if(!CbotData.len) CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null) var/CartData[0] - for(var/obj/structure/stool/bed/chair/cart/janicart/B in world) + for(var/obj/structure/janitorialcart/B in janitorial_equipment) var/turf/bl = get_turf(B) if(bl) if(bl.z != cl.z) diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 42653c3ff1b..3d37f120bc6 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -77,6 +77,8 @@ /obj/item/device/flash/proc/flash_carbon(var/mob/living/carbon/M, var/mob/user = null, var/power = 5, convert = 1) add_logs(M, user, "flashed", object="[src.name]") + if(M.weakeyes) + M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash var/safety = M:eyecheck() if(safety <= 0) M.confused += power @@ -85,6 +87,9 @@ terrible_conversion_proc(M, user) M.Stun(1) user.visible_message("[user] blinds [M] with the [src.name]!") + if(M.weakeyes) + M.Stun(2) + M.visible_message("[M] gasps and shields their eyes!") return 1 else if(user) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index ec5f18283a8..ed55d931d8c 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -66,9 +66,9 @@ /obj/item/device/laser_pointer/afterattack(var/atom/target, var/mob/living/user, flag, params) if(flag) //we're placing the object on a table or in backpack return - laser_act(target, user) + laser_act(target, user, params) -/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user) +/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user, var/params) if( !(user in (viewers(7,target))) ) return if (!diode) @@ -96,11 +96,13 @@ //20% chance to actually hit the eyes if(prob(effectchance * diode.rating)) - add_logs(user, C, "shone in the eyes", object="laser pointer") + add_logs(C, user, "shone in the eyes", object="laser pointer") //eye target check outmsg = "You blind [C] by shining [src] in their eyes." + if(C.weakeyes) + C.Stun(1) var/eye_prot = C.eyecheck() if(C.blinded || eye_prot >= 2) eye_prot = 4 @@ -173,12 +175,19 @@ //laser pointer image icon_state = "pointer_[pointer_icon_state]" var/list/showto = list() - for(var/mob/M in range(7,targloc)) + for(var/mob/M in viewers(7,targloc)) if(M.client) showto.Add(M.client) var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10) - I.pixel_x = target.pixel_x + rand(-5,5) - I.pixel_y = target.pixel_y + rand(-5,5) + var/list/click_params = params2list(params) + if(click_params) + if(click_params["icon-x"]) + I.pixel_x = (text2num(click_params["icon-x"]) - 16) + if(click_params["icon-y"]) + I.pixel_y = (text2num(click_params["icon-y"]) - 16) + else + I.pixel_x = target.pixel_x + rand(-5,5) + I.pixel_y = target.pixel_y + rand(-5,5) if(outmsg) user << outmsg @@ -204,4 +213,4 @@ energy = max_energy recharging = 0 recharge_locked = 0 - ..() + ..() \ No newline at end of file diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 19812645eea..976fed562c0 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -161,8 +161,8 @@ REAGENT SCANNER user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1) user.show_message("\t Damage Specifics: [OX] - [TX] - [BU] - [BR]") user.show_message("\blue Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1) - if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) - user.show_message("\blue Time of Death: [M.tod]") + if(M.timeofdeath && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) + user.show_message("\blue Time of Death: [M.timeofdeath]") if(istype(M, /mob/living/carbon/human) && mode == 1) var/mob/living/carbon/human/H = M var/list/damaged = H.get_damaged_organs(1,1) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 3d496ca3b86..0342dec3840 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -1,35 +1,36 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - /********************************************************************** Cyborg Spec Items ***********************************************************************/ //Might want to move this into several files later but for now it works here /obj/item/borg/stun - name = "Electrified Arm" - icon = 'icons/obj/decals.dmi' - icon_state = "shock" + name = "electrified arm" + icon = 'icons/obj/items.dmi' + icon_state = "elecarm" + var/charge_cost = 30 + +/obj/item/borg/stun/attack(mob/M, mob/living/silicon/robot/user) + var/mob/living/silicon/robot/R = user + if(R && R.cell && R.cell.charge > 0) + R.cell.use(charge_cost) + else + return - attack(mob/M as mob, mob/living/silicon/robot/user as mob) - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [key_name(user)]") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [key_name(M)]") - if(M.ckey) - msg_admin_attack("[key_name_admin(user)] used the [src.name] to attack [key_name_admin(M)]") + user.do_attack_animation(M) + M.Weaken(5) + if (M.stuttering < 5) + M.stuttering = 5 + M.Stun(5) - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user + M.visible_message("[user] has prodded [M] with [src]!", \ + "[user] has prodded you with [src].") + playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user - user.cell.charge -= 30 - - M.Weaken(5) - if (M.stuttering < 5) - M.stuttering = 5 - M.Stun(5) - - for(var/mob/O in viewers(M, null)) - if (O.client) - O.show_message("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2) + add_logs(M, user, "stunned", src, "(INTENT: [uppertext(user.a_intent)])") /obj/item/borg/overdrive name = "Overdrive" @@ -44,19 +45,16 @@ icon_state = "securearea" var/sight_mode = null - /obj/item/borg/sight/xray name = "X-ray Vision" sight_mode = BORGXRAY - /obj/item/borg/sight/thermal name = "Thermal Vision" sight_mode = BORGTHERM icon_state = "thermal" icon = 'icons/obj/clothing/glasses.dmi' - /obj/item/borg/sight/meson name = "Meson Vision" sight_mode = BORGMESON @@ -67,24 +65,22 @@ name = "Hud" var/obj/item/clothing/glasses/hud/hud = null - /obj/item/borg/sight/hud/med name = "medical hud" icon_state = "healthhud" icon = 'icons/obj/clothing/glasses.dmi' - New() - ..() - hud = new /obj/item/clothing/glasses/hud/health(src) - return - +/obj/item/borg/sight/hud/med/New() + ..() + hud = new /obj/item/clothing/glasses/hud/health(src) + return /obj/item/borg/sight/hud/sec name = "security hud" icon_state = "securityhud" icon = 'icons/obj/clothing/glasses.dmi' - New() - ..() - hud = new /obj/item/clothing/glasses/hud/security(src) - return +/obj/item/borg/sight/hud/sec/New() + ..() + hud = new /obj/item/clothing/glasses/hud/security(src) + return diff --git a/code/game/objects/items/weapons/cash.dm b/code/game/objects/items/weapons/cash.dm index 4269ddb283d..8aadcc91e92 100644 --- a/code/game/objects/items/weapons/cash.dm +++ b/code/game/objects/items/weapons/cash.dm @@ -77,7 +77,7 @@ var/global/list/moneytypes=list( stack_color = "#663200" /obj/item/weapon/spacecash/c200 - icon_state = "cash100" + icon_state = "cash200" worth = 200 stack_color = "#663200" diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index e148d6bc7ff..40ac8e93bdd 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -66,7 +66,7 @@ var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = getline(user, target_turf) - add_logs(user, target, "flamethrowered", addition="at [target.x],[target.y],[target.z]") + add_logs(target, user, "flamethrowered", addition="at [target.x],[target.y],[target.z]") flame_turf(turflist) /obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob, params) diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 7eca6aa719b..260160a63c3 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -36,11 +36,20 @@ ear_safety++ //Flash + var/eye_damage = rand(1,3) + if(M.weakeyes) + M.visible_message("[M] screams and collapses!") + M << "AAAAGH! IT BURNS!" + M.Weaken(15) //hella stunned + M.Stun(15) + eye_damage += 8 + if(!eye_safety && ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"] flick("e_flash", M.flash) - if (E) E.damage += rand(1, 3) + if (E) + E.damage += eye_damage M.Stun(max(10/distance, 3)) M.Weaken(max(10/distance, 3)) if (istype(E) && E.damage >= E.min_bruised_damage) diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 874f96271fe..05a367fc075 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -1,3 +1,5 @@ +#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) + /obj/item/weapon/mop desc = "The world of janitalia wouldn't be complete without a mop." name = "mop" @@ -12,18 +14,22 @@ var/mopping = 0 var/mopcount = 0 var/mopcap = 5 - var/mopspeed = 40 + var/mopspeed = 30 /obj/item/weapon/mop/New() create_reagents(mopcap) + janitorial_equipment += src +/obj/item/weapon/mop/Destroy() + janitorial_equipment -= src + return ..() /obj/item/weapon/mop/proc/clean(turf/simulated/A) if(reagents.has_reagent("water", 1) || reagents.has_reagent("cleaner", 1) || reagents.has_reagent("holywater", 1)) A.clean_blood() for(var/obj/effect/O in A) - if(istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay) || istype(O,/obj/effect/rune)) + if(is_cleanable(O)) qdel(O) reagents.reaction(A, TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. reagents.remove_any(1) //reaction() doesn't use up the reagents @@ -33,20 +39,20 @@ if(!proximity) return if(reagents.total_volume < 1) - user << "Your mop is dry!" + user << "Your mop is dry!" return var/turf/simulated/turf = A - if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay)) + if(is_cleanable(A)) turf = A.loc A = null if(istype(turf)) - user.visible_message("[user] begins to clean \the [turf] with [src].") + user.visible_message("[user] begins to clean \the [turf] with [src].", "You begin to clean \the [turf] with [src]...") - if(do_after(user, mopspeed, target = src)) + if(do_after(user, src.mopspeed, target = turf)) + user << "You finish mopping." clean(turf) - user << "You have finished mopping!" /obj/effect/attackby(obj/item/I, mob/user, params) diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm index 7f5f6b7861e..4ebf6b257e8 100644 --- a/code/game/objects/items/weapons/soap.dm +++ b/code/game/objects/items/weapons/soap.dm @@ -16,11 +16,9 @@ icon_state = "soapnt" /obj/item/weapon/soap/deluxe - icon_state = "soapdeluxe" - -/obj/item/weapon/soap/deluxe/New() desc = "A deluxe Waffle Co. brand bar of soap. Smells of comdoms." - cleanspeed = 40 //same speed as mop because deluxe -- captain gets one of these + icon_state = "soapdeluxe" + cleanspeed = 40 //slightly better because deluxe -- captain gets one of these /obj/item/weapon/soap/syndie desc = "An untrustworthy bar of soap made of strong chemical agents that dissolve blood faster." diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index e88e37afd6c..5b700bf7181 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -29,8 +29,8 @@ /obj/item/weapon/storage/bag/trash name = "trash bag" desc = "It's the heavy-duty black polymer kind. Time to take out the trash!" - icon = 'icons/obj/trash.dmi' - icon_state = "trashbag0" + icon = 'icons/obj/janitor.dmi' + icon_state = "trashbag" item_state = "trashbag" w_class = 4 @@ -46,12 +46,12 @@ /obj/item/weapon/storage/bag/trash/update_icon() if(contents.len == 0) - icon_state = "trashbag0" + icon_state = "[initial(icon_state)]" else if(contents.len < 12) - icon_state = "trashbag1" + icon_state = "[initial(icon_state)]1" else if(contents.len < 21) - icon_state = "trashbag2" - else icon_state = "trashbag3" + icon_state = "[initial(icon_state)]2" + else icon_state = "[initial(icon_state)]3" /obj/item/weapon/storage/bag/trash/cyborg @@ -63,6 +63,13 @@ /obj/item/weapon/storage/bag/trash/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J) return +/obj/item/weapon/storage/bag/trash/bluespace + name = "trash bag of holding" + desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage." + icon_state = "bluetrashbag" + max_combined_w_class = 60 + storage_slots = 60 + // ----------------------------- // Plastic Bag diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 5d92705d1ed..f409324844b 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -359,8 +359,8 @@ /obj/item/weapon/storage/belt/bluespace name = "Belt of Holding" desc = "The greatest in pants-supporting technology." - icon_state = "medicalbelt" - item_state = "medical" + icon_state = "holdingbelt" + item_state = "holdingbelt" storage_slots = 14 w_class = 4 max_w_class = 2 diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index d22ca34cffa..24e030fbbc0 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -258,8 +258,8 @@ new /obj/item/weapon/implantcase/death_alarm(src) new /obj/item/weapon/implantcase/death_alarm(src) new /obj/item/weapon/implantcase/death_alarm(src) + new /obj/item/weapon/implantcase/death_alarm(src) new /obj/item/weapon/implanter(src) - new /obj/item/weapon/implantpad(src) /obj/item/weapon/storage/box/rxglasses diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 14b51d03498..a23ba5ac92e 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -5,13 +5,13 @@ icon_state = "folded_wall" w_class = 3.0 - attack_self(mob/user) - playsound(loc, 'sound/items/zip.ogg', 75, 1) - user << "\blue You inflate [src]." - var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc) - src.transfer_fingerprints_to(R) - R.add_fingerprint(user) - qdel(src) +/obj/item/inflatable/attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + qdel(src) /obj/structure/inflatable name = "inflatable wall" @@ -25,131 +25,130 @@ var/health = 50.0 +/obj/structure/inflatable/New(location) + ..() + air_update_turf(1) - New(location) - ..() - air_update_turf() +/obj/structure/inflatable/Destroy() + air_update_turf(1) + return ..() - Destroy() - air_update_turf() - return ..() +/obj/structure/inflatable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return 0 + +/obj/structure/inflatable/CanAtmosPass(turf/T) + return !density - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - return 0 +/obj/structure/inflatable/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + deflate(1) + return - bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <= 0) +/obj/structure/inflatable/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) deflate(1) - return - - - ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) + return + if(3.0) + if(prob(50)) deflate(1) return - if(3.0) - if(prob(50)) - deflate(1) - return +/obj/structure/inflatable/blob_act() + deflate(1) - blob_act() +/obj/structure/inflatable/attack_hand(mob/user as mob) + add_fingerprint(user) + return + +/obj/structure/inflatable/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime + health -= damage + if(health <= 0) + user.visible_message("[user] tears open [src]!") + deflate(1) + else //for nicer text~ + user.visible_message("[user] tears at [src]!") + +/obj/structure/inflatable/attack_alien(mob/user as mob) + if(islarva(user)) + return + attack_generic(user, 15) + +/obj/structure/inflatable/attack_animal(mob/user as mob) + if(!isanimal(user)) + return + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + attack_generic(M, M.melee_damage_upper) + +/obj/structure/inflatable/attack_slime(mob/user as mob) + var/mob/living/carbon/slime/S = user + if (!S.is_adult) + return + attack_generic(user, rand(10, 15)) + +/obj/structure/inflatable/attackby(obj/item/weapon/W as obj, mob/user as mob, params) + if(!istype(W)) + return + if (can_puncture(W)) + visible_message("\red [user] pierces [src] with [W]!") + deflate(1) + if(W.damtype == BRUTE || W.damtype == BURN) + hit(W.force) + ..() + return + +/obj/structure/inflatable/proc/hit(var/damage, var/sound_effect = 1) + health = max(0, health - damage) + if(sound_effect) + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + if(health <= 0) deflate(1) - attack_hand(mob/user as mob) - add_fingerprint(user) - return - - - proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime - health -= damage - if(health <= 0) - user.visible_message("[user] tears open [src]!") - deflate(1) - else //for nicer text~ - user.visible_message("[user] tears at [src]!") - - attack_alien(mob/user as mob) - if(islarva(user)) return - attack_generic(user, 15) - - attack_animal(mob/user as mob) - if(!isanimal(user)) return - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) return - attack_generic(M, M.melee_damage_upper) - - - attack_slime(mob/user as mob) - var/mob/living/carbon/slime/S = user - if (!S.is_adult) - return - attack_generic(user, rand(10, 15)) - - - attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(!istype(W)) return - - if (can_puncture(W)) - visible_message("\red [user] pierces [src] with [W]!") - deflate(1) - if(W.damtype == BRUTE || W.damtype == BURN) - hit(W.force) - ..() - return - - proc/hit(var/damage, var/sound_effect = 1) - health = max(0, health - damage) - if(sound_effect) - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - if(health <= 0) - deflate(1) - - - proc/deflate(var/violent=0) - playsound(loc, 'sound/machines/hiss.ogg', 75, 1) - if(violent) - visible_message("[src] rapidly deflates!") - var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) +/obj/structure/inflatable/proc/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) + src.transfer_fingerprints_to(R) + qdel(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/R = new /obj/item/inflatable(loc) src.transfer_fingerprints_to(R) qdel(src) - else - //user << "\blue You slowly deflate the inflatable wall." - visible_message("[src] slowly deflates.") - spawn(50) - var/obj/item/inflatable/R = new /obj/item/inflatable(loc) - src.transfer_fingerprints_to(R) - qdel(src) - verb/hand_deflate() - set name = "Deflate" - set category = "Object" - set src in oview(1) +/obj/structure/inflatable/verb/hand_deflate() + set name = "Deflate" + set category = "Object" + set src in oview(1) - if(isobserver(usr)) //to stop ghosts from deflating - return + if(usr.stat || usr.restrained()) + return - deflate() + deflate() -/obj/item/inflatable/door/ +/obj/item/inflatable/door name = "inflatable door" desc = "A folded membrane which rapidly expands into a simple door on activation." icon = 'icons/obj/inflatable.dmi' icon_state = "folded_door" - attack_self(mob/user) - playsound(loc, 'sound/items/zip.ogg', 75, 1) - user << "\blue You inflate [src]." - var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc) - src.transfer_fingerprints_to(R) - R.add_fingerprint(user) - qdel(src) +/obj/item/inflatable/door/attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + qdel(src) /obj/structure/inflatable/door //Based on mineral door code name = "inflatable door" @@ -163,94 +162,92 @@ var/state = 0 //closed, 1 == open var/isSwitchingStates = 0 - //Bumped(atom/user) - // ..() - // if(!state) - // return TryToSwitchState(user) - // return +/obj/structure/inflatable/door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral + if(isAI(user)) //so the AI can't open it + return + else if(isrobot(user)) //but cyborgs can + if(get_dist(user,src) <= 1) //not remotely though + return TryToSwitchState(user) - attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral - if(isAI(user)) //so the AI can't open it - return - else if(isrobot(user)) //but cyborgs can - if(get_dist(user,src) <= 1) //not remotely though - return TryToSwitchState(user) +/obj/structure/inflatable/door/attack_hand(mob/user as mob) + return TryToSwitchState(user) - attack_hand(mob/user as mob) - return TryToSwitchState(user) +/obj/structure/inflatable/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) + return state + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density + +/obj/structure/inflatable/door/CanAtmosPass(turf/T) + return !density - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group) - return state - if(istype(mover, /obj/effect/beam)) - return !opacity - return !density - - proc/TryToSwitchState(atom/user) - if(isSwitchingStates) return - if(ismob(user)) - var/mob/M = user - if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? - if(M.client) - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(!C.handcuffed) - SwitchState() - else +/obj/structure/inflatable/door/proc/TryToSwitchState(atom/user) + if(isSwitchingStates) + return + if(ismob(user)) + var/mob/M = user + if(world.time - user.last_bumped <= 60) + return //NOTE do we really need that? + if(M.client) + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(!C.handcuffed) SwitchState() - else if(istype(user, /obj/mecha)) - SwitchState() + else + SwitchState() + else if(istype(user, /obj/mecha)) + SwitchState() - proc/SwitchState() - if(state) - Close() - else - Open() - air_update_turf() - - proc/Open() - isSwitchingStates = 1 - //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) - flick("door_opening",src) - sleep(10) - density = 0 - opacity = 0 - state = 1 - update_icon() - isSwitchingStates = 0 - - proc/Close() - isSwitchingStates = 1 - //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) - flick("door_closing",src) - sleep(10) - density = 1 - opacity = 0 - state = 0 - update_icon() - isSwitchingStates = 0 +/obj/structure/inflatable/door/proc/SwitchState() + if(state) + Close() + else + Open() + air_update_turf(1) +/obj/structure/inflatable/door/proc/Open() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_opening",src) + sleep(10) + density = 0 + opacity = 0 + state = 1 update_icon() - if(state) - icon_state = "door_open" - else - icon_state = "door_closed" + isSwitchingStates = 0 - deflate(var/violent=0) - playsound(loc, 'sound/machines/hiss.ogg', 75, 1) - if(violent) - visible_message("[src] rapidly deflates!") - var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) +/obj/structure/inflatable/door/proc/Close() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_closing",src) + sleep(10) + density = 1 + opacity = 0 + state = 0 + update_icon() + isSwitchingStates = 0 + +/obj/structure/inflatable/door/update_icon() + if(state) + icon_state = "door_open" + else + icon_state = "door_closed" + +/obj/structure/inflatable/door/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) + src.transfer_fingerprints_to(R) + else + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) src.transfer_fingerprints_to(R) - qdel(src) - else - //user << "\blue You slowly deflate the inflatable wall." - visible_message("[src] slowly deflates.") - spawn(50) - var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) - src.transfer_fingerprints_to(R) - qdel(src) - + + air_update_turf(1) + qdel(src) /obj/item/inflatable/torn name = "torn inflatable wall" @@ -258,9 +255,9 @@ icon = 'icons/obj/inflatable.dmi' icon_state = "folded_wall_torn" - attack_self(mob/user) - user << "\blue The inflatable wall is too torn to be inflated!" - add_fingerprint(user) +/obj/item/inflatable/torn/attack_self(mob/user) + user << "The inflatable wall is too torn to be inflated!" + add_fingerprint(user) /obj/item/inflatable/door/torn name = "torn inflatable door" @@ -268,9 +265,9 @@ icon = 'icons/obj/inflatable.dmi' icon_state = "folded_door_torn" - attack_self(mob/user) - user << "\blue The inflatable door is too torn to be inflated!" - add_fingerprint(user) +/obj/item/inflatable/door/torn/attack_self(mob/user) + user << "The inflatable door is too torn to be inflated!" + add_fingerprint(user) /obj/item/weapon/storage/briefcase/inflatable name = "inflatable barrier box" @@ -280,12 +277,12 @@ max_combined_w_class = 21 w_class = 3 - New() - ..() - new /obj/item/inflatable/door(src) - new /obj/item/inflatable/door(src) - new /obj/item/inflatable/door(src) - new /obj/item/inflatable(src) - new /obj/item/inflatable(src) - new /obj/item/inflatable(src) - new /obj/item/inflatable(src) \ No newline at end of file +/obj/item/weapon/storage/briefcase/inflatable/New() + ..() + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index c9a624fad8c..9d8ed7ee3dc 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -1,54 +1,98 @@ -/obj/structure/stool/bed/chair/cart/ +//old style PIMP-CART +/obj/structure/stool/bed/chair/janicart + name = "janicart" + desc = "A brave janitor cyborg gave its life to produce such an amazing combination of speed and utility." icon = 'icons/obj/vehicles.dmi' - anchored = 1 + icon_state = "pussywagon" + anchored = 0 density = 1 - var/empstun = 0 - var/health = 100 - var/destroyed = 0 - var/move_delay = 1 - var/keytype = /obj/item/key - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread + var/obj/item/weapon/storage/bag/trash/mybag = null + var/callme = "pimpin' ride" //how do people refer to it? + var/move_delay = 0 + var/floorbuffer = 0 + var/keytype = /obj/item/key/janitor -/obj/structure/stool/bed/chair/cart/process() - if(empstun > 0) - empstun-- - if(empstun < 0) - empstun = 0 - -/obj/structure/stool/bed/chair/cart/New() - processing_objects |= src +/obj/structure/stool/bed/chair/janicart/New() handle_rotation() -/obj/structure/stool/bed/chair/cart/examine(mob/user) - if(..(user, 1)) - switch(health) - if(75 to 99) - usr << "\blue It appears slightly dented." - if(40 to 74) - usr << "\red It appears heavily dented." - if(1 to 39) - usr << "\red It appears severely dented." - if((INFINITY * -1) to 0) - usr << "It appears completely unsalvageable" +/obj/structure/stool/bed/chair/janicart/Move(a, b, flag) + ..() + if(floorbuffer) + var/turf/tile = loc + if(isturf(tile)) + tile.clean_blood() + if (istype(tile, /turf/simulated/floor)) + var/turf/simulated/floor/F = tile + F.dirt = 0 + for(var/A in tile) + if(istype(A, /obj/effect)) + if(is_cleanable(A)) + qdel(A) -/obj/structure/stool/bed/chair/cart/attackby(obj/item/W, mob/user, params) - if (istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0)) - if(destroyed) - user << "\red The [src.name] is destroyed beyond repair." - add_fingerprint(user) - user.visible_message("\blue [user] has fixed some of the dents on [src].", "\blue You fix some of the dents on \the [src]") - health += 20 - HealthCheck() - else - user << "Need more welding fuel!" +/obj/structure/stool/bed/chair/janicart/examine(mob/user) + ..() + if(floorbuffer) + user << "It has been upgraded with a floor buffer." + + +/obj/structure/stool/bed/chair/janicart/attackby(obj/item/I, mob/user, params) + if(istype(I, keytype)) + user << "Hold [I] in one of your hands while you drive this [callme]." + else if(istype(I, /obj/item/weapon/storage/bag/trash)) + if(keytype == /obj/item/key/janitor) + if(!user.drop_item()) + return + user << "You hook the trashbag onto the [callme]." + I.loc = src + mybag = I + else if(istype(I, /obj/item/janiupgrade)) + if(keytype == /obj/item/key/janitor) + floorbuffer = 1 + qdel(I) + user << "You upgrade the [callme] with the floor buffer." + update_icon() + +/obj/structure/stool/bed/chair/janicart/update_icon() + overlays.Cut() + if(mybag) + overlays += "cart_garbage" + if(floorbuffer) + overlays += "cart_buffer" + +/obj/structure/stool/bed/chair/janicart/attack_hand(mob/user) + if(mybag) + mybag.loc = get_turf(user) + user.put_in_hands(mybag) + mybag = null + update_icon() + else + ..() + + +/obj/structure/stool/bed/chair/janicart/relaymove(mob/user, direction) + if(user.stat || user.stunned || user.weakened || user.paralysis) + unbuckle_mob() + if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype)) + if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc)) return - if(istype(W, /obj/item/key)) - user << "Hold [W] in one of your hands while you drive this [name]." + step(src, direction) + update_mob() + handle_rotation() + if(istype(src.loc, /turf/simulated)) + var/turf/simulated/T = src.loc + if(T.wet == 2) //Lube! Fall off! + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) + buckled_mob.Stun(7) + buckled_mob.Weaken(7) + unbuckle_mob() + step(src, dir) + move_delay = 1 + spawn(2) + move_delay = 0 + else + user << "You'll need the keys in one of your hands to drive this [callme]." - -/obj/structure/stool/bed/chair/cart/user_buckle_mob(mob/living/M, mob/user) +/obj/structure/stool/bed/chair/janicart/user_buckle_mob(mob/living/M, mob/user) if(user.incapacitated()) //user can't move the mob on the janicart's turf if incapacitated return for(var/atom/movable/A in get_turf(src)) //we check for obstacles on the turf. @@ -59,19 +103,14 @@ ..() update_mob() -/obj/structure/stool/bed/chair/cart/post_buckle_mob(mob/living/M) - update_mob() - return ..() +/obj/structure/stool/bed/chair/janicart/unbuckle_mob() + if(buckled_mob) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + ..() -/obj/structure/stool/bed/chair/cart/unbuckle_mob() - var/mob/living/M = ..() - if(M) - M.pixel_x = 0 - M.pixel_y = 0 - return M - -/obj/structure/stool/bed/chair/cart/handle_rotation() - if(dir == SOUTH) +/obj/structure/stool/bed/chair/janicart/handle_rotation() + if((dir == SOUTH) || (dir == WEST) || (dir == EAST)) layer = FLY_LAYER else layer = OBJ_LAYER @@ -83,7 +122,8 @@ update_mob() -/obj/structure/stool/bed/chair/cart/proc/update_mob() + +/obj/structure/stool/bed/chair/janicart/proc/update_mob() if(buckled_mob) buckled_mob.dir = dir switch(dir) @@ -91,190 +131,85 @@ buckled_mob.pixel_x = 0 buckled_mob.pixel_y = 7 if(WEST) - buckled_mob.pixel_x = 13 + buckled_mob.pixel_x = 12 buckled_mob.pixel_y = 7 if(NORTH) buckled_mob.pixel_x = 0 buckled_mob.pixel_y = 4 if(EAST) - buckled_mob.pixel_x = -13 + buckled_mob.pixel_x = -12 buckled_mob.pixel_y = 7 -/obj/structure/stool/bed/chair/cart/emp_act(severity) - switch(severity) - if(1) - src.empstun = (rand(5,10)) - if(2) - src.empstun = (rand(1,5)) - src.visible_message("\red The [src.name]'s motor short circuits!") - spark_system.attach(src) - spark_system.set_up(5, 0, src) - spark_system.start() - -/obj/structure/stool/bed/chair/cart/bullet_act(var/obj/item/projectile/Proj) - var/hitrider = 0 - if(istype(Proj, /obj/item/projectile/ion)) - Proj.on_hit(src, 2) - return +/obj/structure/stool/bed/chair/janicart/bullet_act(obj/item/projectile/Proj) if(buckled_mob) - if(prob(75)) - hitrider = 1 - var/act = buckled_mob.bullet_act(Proj) - if(act >= 0) - visible_message("[buckled_mob.name] is hit by [Proj]!") - if(istype(Proj, /obj/item/projectile/energy)) - unbuckle_mob() - return - if(istype(Proj, /obj/item/projectile/energy/electrode)) - if(prob(25)) - unbuckle_mob() - visible_message("The [src.name] absorbs the [Proj]") - if(!istype(buckled_mob, /mob/living/carbon/human)) - return buckled_mob.bullet_act(Proj) - else - var/mob/living/carbon/human/H = buckled_mob - return H.electrocute_act(0, src, 1, 0) - if(!hitrider) - visible_message("[Proj] hits the [name]!") - if(!Proj.nodamage && Proj.damage_type == BRUTE || Proj.damage_type == BURN) - health -= Proj.damage - HealthCheck() - -/obj/structure/stool/bed/chair/cart/proc/HealthCheck() - if(health > 100) health = 100 - if(health <= 0 && !destroyed) - destroyed = 1 - density = 0 - if(buckled_mob) - unbuckle_mob() - visible_message("The [name] explodes!") - explosion(src.loc,-1,0,2,7,10) - icon_state = "pussywagon_destroyed" - -/obj/structure/stool/bed/chair/cart/ex_act(severity) - switch (severity) - if(1.0) - health -= 100 - if(2.0) - health -= 75 - if(3.0) - health -= 45 - HealthCheck() - - -///////////////////////////////////////////////////////////////////////// - -/obj/structure/stool/bed/chair/cart/janicart - name = "janicart" - icon_state = "pussywagon" - flags = OPENCONTAINER - //copypaste sorry - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - var/obj/item/weapon/storage/bag/trash/mybag = null - -/obj/structure/stool/bed/chair/cart/janicart/New() - ..() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - -/obj/structure/stool/bed/chair/cart/janicart/examine(mob/user) - if(!..(user, 1)) - return - - user << "\icon[src] This [name] contains [reagents.total_volume] unit\s of [reagents]!" - if(mybag) - user << "\A [mybag] is hanging on the [name]." - -/obj/structure/stool/bed/chair/cart/janicart/attackby(obj/item/W, mob/user, params) - ..() - if(istype(W, /obj/item/weapon/mop)) - if(reagents.total_volume >= 2) - reagents.trans_to(W, 2) - user << "You wet the mop in the pimpin' ride." - playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1) - if(reagents.total_volume < 1) - user << "This pimpin' ride is out of water!" - else if(istype(W, /obj/item/weapon/storage/bag/trash)) - user << "You hook the trashbag onto the pimpin' ride." - user.drop_item() - W.loc = src - mybag = W - - -/obj/structure/stool/bed/chair/cart/janicart/attack_hand(mob/user) - if(mybag) - mybag.loc = get_turf(user) - user.put_in_hands(mybag) - mybag = null - else - ..() - - -/obj/structure/stool/bed/chair/cart/janicart/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis || destroyed) - unbuckle_mob() - return - if(empstun > 0) - if(user) - user << "\red \the [src] is unresponsive." - return - if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype)) - if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc)) - return - step(src, direction) - update_mob() - handle_rotation() - move_delay = 1 - spawn(2) - move_delay = 0 - else - user << "You'll need the keys in one of your hands to drive this pimpin' ride." - -//////////////////////////////////////////////////////////////////////////////////////////////// - -/obj/structure/stool/bed/chair/cart/ambulance - name = "ambulance" - icon = 'icons/obj/vehicles.dmi' - icon_state = "docwagon" - anchored = 0 - density = 1 -/var/brightness = 4 -/var/strobe = 0 - -/obj/structure/stool/bed/chair/cart/ambulance/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis || destroyed) - unbuckle_mob() - return - if(empstun > 0) - if(user) - user << "\red \the [src] is unresponsive." - return - if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype)) - if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc)) - return - step(src, direction) - update_mob() - handle_rotation() - move_delay = 1 - spawn(2) - move_delay = 0 - else - user << "You'll need the keys in one of your hands to drive this ambulance." - + buckled_mob.bullet_act(Proj) /obj/item/key name = "key" - desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + desc = "A small grey key." icon = 'icons/obj/vehicles.dmi' - icon_state = "keys" + icon_state = "key" w_class = 1 +/obj/item/key/janitor + desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + icon_state = "keyjanitor" + +/obj/item/key/security + desc = "A keyring with a small steel key, and a rubber stun baton accessory." + icon_state = "keysec" + /obj/item/key/ambulance name = "ambulance key" desc = "A keyring with a small steel key, and tag with a red cross on it." icon_state = "keydoc" +/obj/item/key/snowmobile + name = "snowmobile key" + desc = "A keyring with a small steel key, and tag with a red cross on it; clearly it's not implying you're going to the hospital for this..." + icon_state = "keydoc" //get a better icon, sometime. + +/obj/item/janiupgrade + name = "floor buffer upgrade" + desc = "An upgrade for mobile janicarts." + icon = 'icons/obj/vehicles.dmi' + icon_state = "upgrade" + +/obj/structure/stool/bed/chair/janicart/secway + name = "secway" + desc = "A brave security cyborg gave its life to help you look like a complete tool." + icon = 'icons/obj/vehicles.dmi' + icon_state = "secway" + callme = "secway" + keytype = /obj/item/key/security + +/obj/structure/stool/bed/chair/janicart/secway/update_mob() + if(buckled_mob) + buckled_mob.dir = dir + buckled_mob.pixel_y = 4 + + +/obj/structure/stool/bed/chair/janicart/ambulance + name = "ambulance" + desc = "For getting to patients in a hurry--or running them over." + icon = 'icons/obj/vehicles.dmi' + icon_state = "docwagon" + callme = "ambulance" + keytype = /obj/item/key/ambulance + +/obj/structure/stool/bed/chair/janicart/secway/snowmobile + name = "red snowmobile" + desc = "Wheeeeeeeeeeee." + icon = 'icons/obj/vehicles.dmi' + icon_state = "snowmobile" + callme = "snowmobile" + +/obj/structure/stool/bed/chair/janicart/secway/snowmobile/blue + name = "blue snowmobile" + icon_state = "bluesnowmobile" + +//////////////////////////////////////////////////////////////////////////////////////////////// + //TG style Janicart /obj/structure/janitorialcart @@ -297,8 +232,13 @@ /obj/structure/janitorialcart/New() create_reagents(100) + janitorial_equipment += src +/obj/structure/janitorialcart/Destroy() + janitorial_equipment -= src + return ..() + /obj/structure/janitorialcart/proc/wet_mop(obj/item/weapon/mop, mob/user) if(reagents.total_volume < 1) user << "[src] is out of water!" diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index f14e9ec246d..4988e7d465e 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -11,11 +11,16 @@ var/datum/reagents/R = new/datum/reagents(100) reagents = R R.my_atom = src + janitorial_equipment += src /obj/structure/mopbucket/full/New() ..() reagents.add_reagent("water", 100) +/obj/structure/mopbucket/Destroy() + janitorial_equipment -= src + return ..() + /obj/structure/mopbucket/examine(mob/user) if(..(user, 1)) usr << text("\icon[] [] contains [] units of water left!", src, src.name, src.reagents.total_volume) diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 10b8d73a92b..c95f3aa2b09 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -23,11 +23,11 @@ FLOOR SAFES /obj/structure/safe/New() - tumbler_1_pos = rand(0, 72) - tumbler_1_open = rand(0, 72) + tumbler_1_pos = rand(0, 71) + tumbler_1_open = rand(0, 71) - tumbler_2_pos = rand(0, 72) - tumbler_2_open = rand(0, 72) + tumbler_2_pos = rand(0, 71) + tumbler_2_open = rand(0, 71) /obj/structure/safe/initialize() @@ -39,14 +39,14 @@ FLOOR SAFES I.loc = src -/obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear) +/obj/structure/safe/proc/check_unlocked(mob/user, canhear) if(user && canhear) if(tumbler_1_pos == tumbler_1_open) - user << "You hear a [pick("tonk", "krunk", "plunk")] from [src]." + user << "You hear a [pick("tonk", "krunk", "plunk")] from [src]." if(tumbler_2_pos == tumbler_2_open) - user << "You hear a [pick("tink", "krink", "plink")] from [src]." + user << "You hear a [pick("tink", "krink", "plink")] from [src]." if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open) - if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") + if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") return 1 return 0 @@ -72,7 +72,7 @@ FLOOR SAFES icon_state = initial(icon_state) -/obj/structure/safe/attack_hand(mob/user as mob) +/obj/structure/safe/attack_hand(mob/user) user.set_machine(src) var/dat = "
" dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +" @@ -101,7 +101,7 @@ FLOOR SAFES updateUsrDialog() return else - user << "You can't [open ? "close" : "open"] [src], the lock is engaged!" + user << "You can't [open ? "close" : "open"] [src], the lock is engaged!" return if(href_list["decrement"]) @@ -109,11 +109,11 @@ FLOOR SAFES if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71) tumbler_1_pos = decrement(tumbler_1_pos) if(canhear) - user << "You hear a [pick("clack", "scrape", "clank")] from [src]." + user << "You hear a [pick("clack", "scrape", "clank")] from [src]." if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35) tumbler_2_pos = decrement(tumbler_2_pos) if(canhear) - user << "You hear a [pick("click", "chink", "clink")] from [src]." + user << "You hear a [pick("click", "chink", "clink")] from [src]." check_unlocked(user, canhear) updateUsrDialog() return @@ -123,11 +123,11 @@ FLOOR SAFES if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71) tumbler_1_pos = increment(tumbler_1_pos) if(canhear) - user << "You hear a [pick("clack", "scrape", "clank")] from [src]." + user << "You hear a [pick("clack", "scrape", "clank")] from [src]." if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35) tumbler_2_pos = increment(tumbler_2_pos) if(canhear) - user << "You hear a [pick("click", "chink", "clink")] from [src]." + user << "You hear a [pick("click", "chink", "clink")] from [src]." check_unlocked(user, canhear) updateUsrDialog() return @@ -142,11 +142,13 @@ FLOOR SAFES updateUsrDialog() -/obj/structure/safe/attackby(obj/item/I as obj, mob/user as mob, params) +/obj/structure/safe/attackby(obj/item/I, mob/user, params) if(open) if(I.w_class + space <= maxspace) space += I.w_class - user.drop_item() + if(!user.drop_item()) + user << "\The [I] is stuck to your hand, you cannot put it in the safe!" + return I.loc = src user << "You put [I] in [src]." updateUsrDialog() @@ -156,14 +158,13 @@ FLOOR SAFES return else if(istype(I, /obj/item/clothing/accessory/stethoscope)) - user << "Hold [I] in one of your hands while you manipulate the dial." + user << "Hold [I] in one of your hands while you manipulate the dial!" return obj/structure/safe/blob_act() return - obj/structure/safe/ex_act(severity) return diff --git a/code/game/objects/structures/segway.dm b/code/game/objects/structures/segway.dm deleted file mode 100644 index 4e781364af5..00000000000 --- a/code/game/objects/structures/segway.dm +++ /dev/null @@ -1,163 +0,0 @@ -/obj/structure/stool/bed/chair/segway - name = "security segway" - desc = "Gives the illusion of authority." - icon = 'icons/obj/vehicles.dmi' - icon_state = "sec_seg_idle" - anchored = 1 - density = 1 - - var/health = 100 - var/delay = 3 //Move delay to simulate a speed - var/allowMove = 1 - var/datum/global_iterator/space_move //Handling space movement (i.e. drift forever) - -/obj/structure/stool/bed/chair/segway/New() - handle_rotation() - space_move = new /datum/global_iterator/space_movement(null,0) - return - -/obj/structure/stool/bed/chair/segway/user_buckle_mob(mob/living/M, mob/user) - if(user.incapacitated()) //user can't move the mob on the janicart's turf if incapacitated - return - for(var/atom/movable/A in get_turf(src)) //we check for obstacles on the turf. - if(A.density) - if(A != src && A != M) - return - M.loc = loc //we move the mob on the janicart's turf before checking if we can buckle. - ..() - -/obj/structure/stool/bed/chair/segway/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis) - unbuckle_mob() - icon_state = "sec_seg_idle" - if(istype(user.l_hand, /obj/item/sec_seg_key) || istype(user.r_hand, /obj/item/sec_seg_key)) - if(!allowMove) - return - if(src.space_move.active()) - return - allowMove = 0 - icon_state = "sec_seg_move" - step(src, direction) - update_mob() - handle_rotation() - if(istype(src.loc, /turf/space)) - src.space_move.start(list(src,direction)) - if(istype(src.loc, /turf/simulated)) - var/turf/simulated/T = src.loc - if(T.wet == 2) //Lube! Fall off! - playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) - buckled_mob.Stun(8) - buckled_mob.Weaken(5) - unbuckle_mob() - step(src, dir) - sleep(delay) - allowMove = 1 - else - user << "Requires key in hand to drive." - -/obj/structure/stool/bed/chair/segway/Move() - . = ..() - -/obj/structure/stool/bed/chair/segway/Bump(var/atom/obstacle) - if(istype(obstacle, /mob)) - step(obstacle, src.dir) - else - obstacle.Bumped(src) - return - -/obj/structure/stool/bed/chair/segway/post_buckle_mob(mob/living/M) - update_mob() - add_fingerprint(M) - M.pixel_x = 0 - M.pixel_y = 5 - return ..() - -/obj/structure/stool/bed/chair/segway/unbuckle_mob() - var/mob/living/M = ..() - if(M) - M.pixel_x = 0 - M.pixel_y = 0 - return M - -/obj/structure/stool/bed/chair/segway/handle_rotation() - if(dir == NORTH) - layer = OBJ_LAYER - else - layer = FLY_LAYER - - update_mob() - -/obj/structure/stool/bed/chair/segway/proc/update_mob() - if(buckled_mob) - buckled_mob.dir = dir - -/obj/structure/stool/bed/chair/segway/bullet_act(var/obj/item/projectile/Proj) - if(buckled_mob) - return buckled_mob.bullet_act(Proj) - else if(istype(Proj, /obj/item/projectile/beam)) - damage(Proj.damage) - -/obj/structure/stool/bed/chair/segway/proc/damage(amount) - health -= amount - if(health <= 0) - if(buckled_mob) - buckled_mob << "The [src.name] was destroyed!" - qdel(src) - -/obj/item/sec_seg_key - name = "security segway key" - desc = "A key for a security segway. You feel the choice of keyring could be more professional." - icon = 'icons/obj/vehicles.dmi' - icon_state = "keys" //Needs a proper sprite - w_class = 1 - -/datum/global_iterator/space_movement //moon_theme.mp3 - delay = 5 - - process(var/obj/structure/stool/bed/chair/segway/seg as obj,direction) - if(!step(seg, direction)) - src.stop() - - -/obj/structure/stool/bed/chair/segway/snowmobile - name = "red snowmobile" - desc = "Wheeeeeeeeeeee." - icon = 'icons/obj/vehicles.dmi' - icon_state = "snowmobile" - anchored = 1 - density = 1 - -/obj/structure/stool/bed/chair/segway/snowmobile/blue - name = "blue snowmobile" - desc = "Wheeeeeeeeeeee." - icon = 'icons/obj/vehicles.dmi' - icon_state = "bluesnowmobile" - anchored = 1 - density = 1 - -/obj/structure/stool/bed/chair/segway/snowmobile/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis) - unbuckle_mob() - if(!allowMove) - return - if(src.space_move.active()) - return - allowMove = 0 - step(src, direction) - update_mob() - handle_rotation() - if(istype(src.loc, /turf/space)) - src.space_move.start(list(src,direction)) - if(istype(src.loc, /turf/simulated)) - damage(5) - usr << "Your snowmobile takes damage from not being on snow!" - var/turf/simulated/T = src.loc - if(T && T.wet == 2) //Lube! Fall off! - playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) - buckled_mob.Stun(8) - buckled_mob.Weaken(5) - unbuckle_mob() - step(src, dir) - sleep(delay) - allowMove = 1 - diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm index 03d74cee94e..51424aeb26e 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm @@ -5,10 +5,7 @@ anchored = 0 movable = 1 - var/driving = 0 - var/mob/living/pulling = null - var/bloodiness - + var/move_delay = null /obj/structure/stool/bed/chair/wheelchair/handle_rotation() overlays = null @@ -18,139 +15,57 @@ buckled_mob.dir = dir /obj/structure/stool/bed/chair/wheelchair/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained()) - if(user==pulling) - pulling = null - user.pulledby = null - user << "\red You lost your grip!" - return - if(user.pulling && (user == pulling)) - pulling = null - user.pulledby = null - return if(propelled) - return - if(pulling && (get_dist(src, pulling) > 1)) - pulling = null - user.pulledby = null - if(user==pulling) - return - if(pulling && (get_dir(src.loc, pulling.loc) == direction)) - user << "\red You cannot go there." - return - if(pulling && buckled_mob && (buckled_mob == user)) - user << "\red You cannot drive while being pushed." + return 0 + + if(!Process_Spacemove(direction) || !has_gravity(src.loc) || !isturf(loc)) + return 0 + + if(world.time < move_delay) return - if(istype(user.loc, /turf/space)) - return + move_delay = world.time + move_delay += 2 //wheelchairs are not infact sport bikes - if(ishuman(user)) - var/mob/living/carbon/human/driver = user - var/obj/item/organ/external/l_hand = driver.get_organ("l_hand") - var/obj/item/organ/external/r_hand = driver.get_organ("r_hand") - if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED))) - return // No hands to drive your chair? Tough luck! - - // Let's roll - driving = 1 - var/turf/T = null - //--1---Move occupant---1--// if(buckled_mob) - buckled_mob.buckled = null - step(buckled_mob, direction) - buckled_mob.buckled = src - //--2----Move driver----2--// - if(pulling) - T = pulling.loc - if(get_dist(src, pulling) >= 1) - step(pulling, get_dir(pulling.loc, src.loc)) - //--3--Move wheelchair--3--// - step(src, direction) - if(buckled_mob) // Make sure it stays beneath the occupant - Move(buckled_mob.loc) - dir = direction - handle_rotation() - if(pulling) // Driver - if(pulling.loc == src.loc) // We moved onto the wheelchair? Revert! - pulling.forceMove(T) - else - spawn(0) - if(get_dist(src, pulling) > 1) // We are too far away? Losing control. - pulling = null - user.pulledby = null - pulling.dir = get_dir(pulling, src) // When everything is right, face the wheelchair - if(bloodiness) - create_track() - driving = 0 + if(buckled_mob.incapacitated()) + return 0 -/obj/structure/stool/bed/chair/wheelchair/Move() - ..() - if(buckled_mob) - var/mob/living/occupant = buckled_mob - if(!driving) - occupant.buckled = null - occupant.Move(src.loc) - occupant.buckled = src - if (occupant && (src.loc != occupant.loc)) - if (propelled) - for (var/mob/O in src.loc) - if (O != occupant) - Bump(O) - else - unbuckle_mob() - if (pulling && (get_dist(src, pulling) > 1)) - pulling.pulledby = null - pulling << "\red You lost your grip!" - pulling = null - else - if (occupant && (src.loc != occupant.loc)) - forceMove(occupant.loc) // Failsafe to make sure the wheelchair stays beneath the occupant after driving - handle_rotation() + if(ishuman(buckled_mob)) + var/mob/living/carbon/human/driver = user + var/obj/item/organ/external/l_hand = driver.get_organ("l_hand") + var/obj/item/organ/external/r_hand = driver.get_organ("r_hand") + if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED))) + return 0 // No hands to drive your chair? Tough luck! -/obj/structure/stool/bed/chair/wheelchair/attack_hand(mob/user as mob) - if (pulling) - MouseDrop(usr) - else - user_unbuckle_mob(user, user) - return + for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm")) + var/obj/item/organ/external/E = driver.get_organ(organ_name) + if(!E || (E.status & ORGAN_DESTROYED)) + move_delay += 4 + else if(E.status & ORGAN_SPLINTED) + move_delay += 0.5 + else if(E.status & ORGAN_BROKEN) + move_delay += 1.5 + + if(!buckled_mob.Move(get_step(buckled_mob, direction), direction)) + loc = buckled_mob.loc //we gotta go back + last_move = buckled_mob.last_move + inertia_dir = last_move + buckled_mob.inertia_dir = last_move + . = 0 -/obj/structure/stool/bed/chair/wheelchair/MouseDrop(over_object, src_location, over_location) - ..() - if(over_object == usr && in_range(src, usr)) - if(!ishuman(usr)) return - if(usr == buckled_mob) - usr << "\red You realize you are unable to push the wheelchair you sit in." - return - if(!pulling) - pulling = usr - usr.pulledby = src - if(usr.pulling) - usr.stop_pulling() - usr.dir = get_dir(usr, src) - usr << "You grip \the [name]'s handles." else - if(usr != pulling) - for(var/mob/O in viewers(pulling, null)) - O.show_message("\red [usr] breaks [pulling]'s grip on the wheelchair.", 1) - else - usr << "You let go of \the [name]'s handles." - pulling.pulledby = null - pulling = null - return + . = 1 /obj/structure/stool/bed/chair/wheelchair/Bump(atom/A) ..() if(!buckled_mob) return - if(propelled || (pulling && (pulling.a_intent == I_HARM))) + if(propelled) var/mob/living/occupant = buckled_mob unbuckle_mob() - if (pulling && (pulling.a_intent == "hurt")) - occupant.throw_at(A, 3, 3, pulling) - else if (propelled) - occupant.throw_at(A, 3, propelled) + occupant.throw_at(A, 3, propelled) occupant.apply_effect(6, STUN, 0) occupant.apply_effect(6, WEAKEN, 0) @@ -162,31 +77,5 @@ victim.apply_effect(6, WEAKEN, 0) victim.apply_effect(6, STUTTER, 0) victim.take_organ_damage(10) - if(pulling) - occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!") - pulling.attack_log += "\[[time_stamp()]\] Crashed [key_name(occupant)] [name] into \a [A]" - occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [key_name(pulling)] with \the [name]" - msg_admin_attack("[key_name_admin(pulling)] has thrusted [key_name_admin(occupant)] [name] into \a [A]") - else - occupant.visible_message("[occupant] crashed into \the [A]!") - -/obj/structure/stool/bed/chair/wheelchair/proc/create_track() - var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) - var/newdir = get_dir(get_step(loc, dir), loc) - if(newdir == dir) - B.dir = newdir - else - newdir = newdir | dir - if(newdir == 3) - newdir = 1 - else if(newdir == 12) - newdir = 4 - B.dir = newdir - bloodiness-- - -/obj/structure/stool/bed/chair/wheelchair/buckle_mob(mob/M as mob, mob/user as mob) - if(M == pulling) - pulling = null - usr.pulledby = null - ..() \ No newline at end of file + occupant.visible_message("[occupant] crashed into \the [A]!") \ No newline at end of file diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index e3ddc913bb1..48cc9feccf7 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -15,6 +15,7 @@ var/const/OPEN_DURATION = 6 var/const/CLOSE_DURATION = 6 + var/list/disallowed_mobs = list(/mob/living/silicon/ai) /obj/structure/transit_tube/station/New() ..() @@ -32,13 +33,13 @@ return 1 /obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj) - if(!pod_moving && icon_state == "open" && istype(AM, /mob)) + if(!pod_moving && icon_state == "open" && istype(AM, /mob/living) && !is_type_in_list(AM, disallowed_mobs)) for(var/obj/structure/transit_tube_pod/pod in loc) if(pod.contents.len) AM << "" return else if(!pod.moving && pod.dir in directions()) - AM.loc = pod + AM.forceMove(pod) return diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 44ee7ef52db..3262ac5ece2 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -299,7 +299,7 @@ var/turf/tile = loc loc.clean_blood() for(var/obj/effect/E in tile) - if(istype(E,/obj/effect/rune) || istype(E,/obj/effect/decal/cleanable) || istype(E,/obj/effect/overlay)) + if(is_cleanable(E)) qdel(E) /obj/machinery/shower/process() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index ec573e348a2..9cafaf48198 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -9,7 +9,7 @@ thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT heat_capacity = 700000 - var/transition //These is used in transistions as a way to tell where on the "cube" of space you're transitioning from/to + var/destination_z var/destination_x var/destination_y @@ -85,30 +85,15 @@ user << "\red The plating is going to need some support." return - -// Ported from unstable r355 - /turf/space/Entered(atom/movable/A as mob|obj) ..() - if ((!(A) || src != A.loc)) return + if ((!(A) || src != A.loc)) + return - if(transition) - - if(A.z > MAX_Z) return //for away missions - - if(destination_x) - A.x = destination_x - - if(destination_y) - A.y = destination_y - - var/obj/item/flag/nation/fukkenflag = A.GetTypeInAllContents(/obj/item/flag/nation) - if(fukkenflag) - fukkenflag.loc = fukkenflag.startloc - if(isliving(A)) - A << "The flag you were carrying was just returned to it's base. Nice try." - - A.z = text2num(transition) + if(destination_z) + A.x = destination_x + A.y = destination_y + A.z = destination_z if(isliving(A)) var/mob/living/L = A @@ -229,100 +214,5 @@ A.loc.Entered(A) return - -/turf/space/proc/Assign_Destination() - - if(transition) - if(x <= TRANSITIONEDGE) //west - destination_x = world.maxx - TRANSITIONEDGE - 2 - else if (x >= (world.maxx - TRANSITIONEDGE - 1)) //east - destination_x = TRANSITIONEDGE + 1 - else if (y <= TRANSITIONEDGE) //south - destination_y = world.maxy - TRANSITIONEDGE - 2 - else if (y >= (world.maxy - TRANSITIONEDGE - 1)) //north - destination_y = TRANSITIONEDGE + 1 - -/* - Set the space turf transitions for the "space cube" - Connections: - ___ ___ - /_A_/| /_F_/| - | |C| | |E| - |_B_|/ |_D_|/ - Note that all maps except F are oriented with north towards A. A and F are oriented with north towards D. - The characters on the second cube should be upside down in this illustration, but aren't because of a lack of unicode support. -*/ -proc/setup_map_transitions() //listamania - - var/list/unplaced_z_levels = accessable_z_levels - var/list/free_zones = list("A", "B", "C", "D", "E", "F") - var/list/zone_connections = list("D ","C ","B ","E ","A ","C ","F ","E ","A ","D ","F ","B ","A ","E ","F ","C ","A ","B ","F ","D ","D ","C ","B ","E") //This describes the borders of a cube based on free zones, really! - var/text_zone_connections = list2text(zone_connections) - var/list/final_zone_connections = list() - var/list/turfs_needing_transition = list() - var/list/turfs_needing_destinations = list() - var/list/z_level_order = list() - var/z_level - var/placement - var/total_processed = 0 - - for(var/turf/space/S in world) //Define the transistions of the z levels - total_processed++ - if (S.x == TRANSITIONEDGE || S.x == (world.maxx - TRANSITIONEDGE - 1) || S.y == TRANSITIONEDGE || S.y == (world.maxy - TRANSITIONEDGE - 1)) - turfs_needing_transition += S - - //if we've processed lots of turfs, switch to background processing to prevent being mistaken for an infinite loop - if(total_processed > 450000) - set background = 1 - - while(free_zones.len != 0) //Assign the sides of the cube - if(!unplaced_z_levels || !unplaced_z_levels.len) //if we're somehow unable to fill the cube, pad with deep space - z_level = 6 - else - z_level = pick(unplaced_z_levels) - if(z_level > world.maxz) //A safety if one of the unplaced_z_levels doesn't actually exist - z_level = 6 - placement = pick(free_zones) - text_zone_connections = replacetext(text_zone_connections, placement, "[z_level]") - - for(var/turf/space/S in turfs_needing_transition) //pass the identity zone to the relevent turfs - if(S.transition && prob(50)) //In z = 6 (deep space) it's a bit of a crapshoot in terms of navigation - continue - if(S.z == z_level) - S.transition = num2text(z_level) - if(!(S in turfs_needing_destinations)) - turfs_needing_destinations += S - if(S.z != 6) //deep space turfs need to hang around in case they get reassigned a zone - turfs_needing_transition -= S - - z_level_order += num2text(z_level) - unplaced_z_levels -= z_level - free_zones -= placement - - zone_connections = text2list(replacetext(text_zone_connections, " ", "\n")) //Convert the string back into a list - - final_zone_connections.len = z_level_order.len - - var/list/temp = list() - - for(var/j=1, j<= 24, j++) - temp += zone_connections[j] - if(temp.len == 4) //Chunks of cardinal directions - final_zone_connections[z_level_order[j/4]] += temp - temp = list() - - for(var/turf/space/S in turfs_needing_destinations) //replace the identity zone with the destination z-level - var/list/directions = final_zone_connections[S.transition] - if(S.x <= TRANSITIONEDGE) - S.transition = directions[Z_WEST] - else if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) - S.transition = directions[Z_EAST] - else if(S.y <= TRANSITIONEDGE) - S.transition = directions[Z_SOUTH] - else - S.transition = directions[Z_NORTH] - - S.Assign_Destination() - /turf/space/singularity_act() - return \ No newline at end of file + return diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 8cd511a3c9a..72cee4a7b4c 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -1,3 +1,4 @@ +#define MAX_ADMIN_BANS_PER_ADMIN 1 datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null, var/banip = null, var/bancid = null) @@ -10,14 +11,22 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = var/serverip = "[world.internet_address]:[world.port]" var/bantype_pass = 0 var/bantype_str + var/maxadminbancheck //Used to limit the number of active bans of a certein type that each admin can give. Used to protect against abuse or mutiny. + var/announceinirc //When set, it announces the ban in irc. Intended to be a way to raise an alarm, so to speak. + var/blockselfban //Used to prevent the banning of yourself. + var/kickbannedckey //Defines whether this proc should kick the banned person, if they are connected (if banned_mob is defined). + //some ban types kick players after this proc passes (tempban, permaban), but some are specific to db_ban, so + //they should kick within this proc. switch(bantype) if(BANTYPE_PERMA) bantype_str = "PERMABAN" duration = -1 bantype_pass = 1 + blockselfban = 1 if(BANTYPE_TEMP) bantype_str = "TEMPBAN" bantype_pass = 1 + blockselfban = 1 if(BANTYPE_JOB_PERMA) bantype_str = "JOB_PERMABAN" duration = -1 @@ -29,6 +38,21 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = bantype_str = "APPEARANCE_BAN" duration = -1 bantype_pass = 1 + if(BANTYPE_ADMIN_PERMA) + bantype_str = "ADMIN_PERMABAN" + duration = -1 + bantype_pass = 1 + maxadminbancheck = 1 + announceinirc = 1 + blockselfban = 1 + kickbannedckey = 1 + if(BANTYPE_ADMIN_TEMP) + bantype_str = "ADMIN_TEMPBAN" + bantype_pass = 1 + maxadminbancheck = 1 + announceinirc = 1 + blockselfban = 1 + kickbannedckey = 1 if( !bantype_pass ) return if( !istext(reason) ) return @@ -66,6 +90,11 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = a_ckey = src.owner:ckey a_computerid = src.owner:computer_id a_ip = src.owner:address + + if(blockselfban) + if(a_ckey == ckey) + usr << "You cannot apply this ban type on yourself." + return var/who for(var/client/C in clients) @@ -82,6 +111,15 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = adminwho += ", [C]" reason = sql_sanitize_text(reason) + + if(maxadminbancheck) + var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + adm_query.Execute() + if(adm_query.NextRow()) + var/adm_bans = text2num(adm_query.item[1]) + if(adm_bans >= MAX_ADMIN_BANS_PER_ADMIN) + usr << "You already logged [MAX_ADMIN_BANS_PER_ADMIN] admin ban(s) or more. Do not abuse this function!" + return var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)" var/DBQuery/query_insert = dbcon.NewQuery(sql) @@ -89,7 +127,12 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = usr << "\blue Ban saved to database." message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1) + if(announceinirc) + send2irc("BAN ALERT","[a_ckey] applied a [bantype_str] on [ckey]") + if(kickbannedckey) + if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey) + del(banned_mob.client) datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") @@ -114,6 +157,12 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") if(BANTYPE_APPEARANCE) bantype_str = "APPEARANCE_BAN" bantype_pass = 1 + if(BANTYPE_ADMIN_PERMA) + bantype_str = "ADMIN_PERMABAN" + bantype_pass = 1 + if(BANTYPE_ADMIN_TEMP) + bantype_str = "ADMIN_TEMPBAN" + bantype_pass = 1 if(BANTYPE_ANY_FULLBAN) bantype_str = "ANY" bantype_pass = 1 @@ -300,6 +349,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" output += "" output += "" + output += "" + output += "" output += "" output += "Ckey: " output += "IP: " @@ -339,6 +390,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" output += "" output += "" + output += "" + output += "" output += "" output += "

" output += " Match(min. 3 characters to search by key or ip, and 7 to search by cid)
" @@ -406,6 +459,10 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) bantypesearch += "'JOB_TEMPBAN' " if(BANTYPE_APPEARANCE) bantypesearch += "'APPEARANCE_BAN' " + if(BANTYPE_ADMIN_PERMA) + bantypesearch = "'ADMIN_PERMABAN' " + if(BANTYPE_ADMIN_TEMP) + bantypesearch = "'ADMIN_TEMPBAN' " else bantypesearch += "'PERMABAN' " @@ -448,6 +505,10 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) typedesc = "TEMP JOBBAN
([job])
([duration] minutes
Expires [expiration]" if("APPEARANCE_BAN") typedesc = "APPEARANCE/NAME BAN" + if("ADMIN_PERMABAN") + typedesc = "ADMIN PERMABAN" + if("ADMIN_TEMPBAN") + typedesc = "ADMIN TEMPBAN
([duration] minutes [(unbanned) ? "" : "(Edit))"]
Expires [expiration]
" output += "" output += "[typedesc]" diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index e6d258b3386..37c6a60bcdd 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -2,38 +2,42 @@ world/IsBanned(key,address,computer_id) if (!key || !address || !computer_id) log_access("Failed Login (invalid data): [key] [address]-[computer_id]") - return list("reason"="invalid login data", "desc"="Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]' If you continue to get this error, please restart byond or contact byond support.") - if(ckey(key) in admin_datums) - return ..() + return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.") + var/admin = 0 + var/ckey = ckey(key) + if((ckey in admin_datums) || (ckey in deadmins)) + admin = 1 //Guest Checking if(!guests_allowed && IsGuestKey(key)) - log_access("Failed Login: [key] - Guests not allowed") + log_access("Failed Login: [key] [computer_id] [address] - Guests not allowed") // message_admins("\blue Failed Login: [key] - Guests not allowed") - return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") + return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.") - //check if the IP address is a known TOR node - if(config && config.ToRban && ToRban_isbanned(address)) - log_access("Failed Login: [src] - Banned: ToR") - message_admins("\blue Failed Login: [src] - Banned: ToR") + //check if the IP address is a known Tor node + if(config.ToRban && ToRban_isbanned(address)) + log_access("Failed Login: [key] [computer_id] [address] - Banned: Tor") + message_admins("Failed Login: [key] - Banned: Tor") //ban their computer_id and ckey for posterity - AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0) - return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]") + AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0) + var/mistakemessage = "" + if(config.banappeals) + mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]." + return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]") if(config.ban_legacy_system) - //Ban Checking - . = CheckBan( ckey(key), computer_id, address ) + . = CheckBan(ckey(key), computer_id, address) if(.) - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") - message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]") - return . - - return ..() //default pager ban stuff - + if (admin) + log_admin("The admin [key] has been allowed to bypass a matching ban on [.["key"]]") + message_admins("The admin [key] has been allowed to bypass a matching ban on [.["key"]]") + addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]].") + else + log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + return . else - var/ckeytext = ckey(key) if(!establish_db_connection()) @@ -49,7 +53,7 @@ world/IsBanned(key,address,computer_id) if(computer_id) cidquery = " OR computerid = '[computer_id]' " - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") query.Execute() @@ -63,18 +67,47 @@ world/IsBanned(key,address,computer_id) var/duration = query.item[7] var/bantime = query.item[8] var/bantype = query.item[9] - + if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN") + //admin bans MUST match on ckey to prevent cid-spoofing attacks + // as well as dynamic ip abuse + if (pckey != ckey) + continue + if (admin) + if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN") + log_admin("The admin [key] is admin banned, and has been disallowed access") + message_admins("The admin [key] is admin banned, and has been disallowed access") + else + log_admin("The admin [key] has been allowed to bypass a matching ban on [pckey]") + message_admins("The admin [key] has been allowed to bypass a matching ban on [pckey]") + addclientmessage(ckey,"You have been allowed to bypass a matching ban on [pckey].") + continue var/expires = "" if(text2num(duration) > 0) - expires = "The ban is for [duration] minutes and expires on [expiration] (server time)." - if(istext(bantype) && (bantype == "PERMABAN")) - var/appealmsg = "" - if(config && config.banappeals) - appealmsg = " You may appeal it at [config.banappeals]." - expires = "The ban is permanent.[appealmsg]" + expires = " The ban is for [duration] minutes and expires on [expiration] (server time)." + else + var/appealmessage = "" + if(config.banappeals) + appealmessage = " You may appeal it at [config.banappeals]." + expires = " The is a permanent ban.[appealmessage]" - var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime]. [expires]" + var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]" - return list("reason"="[bantype]", "desc"="[desc]") + . = list("reason"="[bantype]", "desc"="[desc]") - return ..() //default pager ban stuff + log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + return . + + . = ..() //default pager ban stuff + if (.) + //byond will not trigger isbanned() for "global" host bans, + //ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked) + //So it's safe to let admins walk thru host/sticky bans here + if (admin) + log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban") + message_admins("The admin [key] has been allowed to bypass a matching host/sticky ban") + addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban.") + return null + else + log_access("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]") + + return . diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm index 03fc3767b8e..355a82aa697 100644 --- a/code/modules/admin/admin_memo.dm +++ b/code/modules/admin/admin_memo.dm @@ -11,7 +11,7 @@ return admin_memo_output(memotask) -/client/proc/admin_memo_output(task, checkrights = 1) +/client/proc/admin_memo_output(task, checkrights = 1, silent = 0) if(checkrights && !check_rights(R_SERVER)) return if(!task) @@ -99,7 +99,7 @@ if(last_editor) output += "
Last edit by [last_editor] (Click here to see edit log)" output += "
[memotext]

" - if(!output) + if(!output && !silent) src << "No memos found in database." return src << output diff --git a/code/modules/admin/admin_report.dm b/code/modules/admin/admin_report.dm index b0f43741d02..89b267cd348 100644 --- a/code/modules/admin/admin_report.dm +++ b/code/modules/admin/admin_report.dm @@ -118,7 +118,7 @@ client/proc/display_admin_reports() usr << browse(output, "window=news;size=600x400") -client/proc/Report(mob/M as mob in world) +client/proc/Report(mob/M as mob in view()) set category = "Admin" if(!src.holder) return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5184f4e7dd2..e2b26e7c491 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -74,7 +74,8 @@ var/list/admin_verbs_admin = list( ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, - /client/proc/jobbans + /client/proc/jobbans, + /client/proc/stickybanpanel ) var/list/admin_verbs_sounds = list( /client/proc/play_local_sound, @@ -225,6 +226,7 @@ var/list/admin_verbs_proccall = list ( admin_verbs_spawn, admin_verbs_mod, admin_verbs_mentor, + admin_verbs_proccall, admin_verbs_show_debug_verbs, /client/proc/readmin, ) @@ -570,7 +572,7 @@ var/list/admin_verbs_proccall = list ( log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].") message_admins("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].") -/client/proc/make_sound(var/obj/O in world) // -- TLE +/client/proc/make_sound(var/obj/O in view()) // -- TLE set category = "Event" set name = "Make Sound" set desc = "Display a message to everyone who can hear the target" @@ -639,7 +641,7 @@ var/list/admin_verbs_proccall = list ( set name = "De-admin self" set category = "Admin" - if(!check_rights(R_ADMIN|R_MOD)) + if(!check_rights(R_ADMIN|R_MOD|R_MENTOR)) return log_admin("[key_name(usr)] deadmined themself.") diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm new file mode 100644 index 00000000000..474b7c76265 --- /dev/null +++ b/code/modules/admin/stickyban.dm @@ -0,0 +1,211 @@ +/datum/admins/proc/stickyban(action,data) + if(!check_rights(R_BAN)) + return + + switch (action) + if ("show") + stickyban_show() + return + if ("add") + var/list/ban = list() + var/ckey + ban["admin"] = usr.key + ban["type"] = list("sticky") + ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only + + if (data["ckey"]) + ckey = ckey(data["ckey"]) + else + ckey = input(usr,"Ckey","Ckey","") as text|null + if (!ckey) + return + ckey = ckey(ckey) + if (get_stickyban_from_ckey(ckey)) + usr << "Error: Can not add a stickyban: User already has a current sticky ban" + + if (data["reason"]) + ban["message"] = data["reason"] + else + var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null + if (!reason) + return + ban["message"] = "[reason]" + + world.SetConfig("ban", ckey, list2stickyban(ban)) + + log_admin("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]") + message_admins("[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]") + + if ("remove") + if (!data["ckey"]) + return + var/ckey = data["ckey"] + + var/ban = get_stickyban_from_ckey(ckey) + if (!ban) + usr << "Error: No sticky ban for [ckey] found!" + return + if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No") + return + if (!get_stickyban_from_ckey(ckey)) + usr << "Error: The ban disappeared." + return + world.SetConfig("ban", ckey, null) + + log_admin("[key_name(usr)] removed [ckey]'s stickyban") + message_admins("[key_name_admin(usr)] removed [ckey]'s stickyban") + + if ("remove_alt") + if (!data["ckey"]) + return + var/ckey = data["ckey"] + if (!data["alt"]) + return + var/alt = ckey(data["alt"]) + var/ban = get_stickyban_from_ckey(ckey) + if (!ban) + usr << "Error: No sticky ban for [ckey] found!" + return + + var/found = 0 + //we have to do it this way because byond keeps the case in its sticky ban matches WHY!!! + for (var/key in ban["keys"]) + if (ckey(key) == alt) + found = 1 + break + + if (!found) + usr << "Error: [alt] is not linked to [ckey]'s sticky ban!" + return + + if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No") + return + + //we have to do this again incase something changes + ban = get_stickyban_from_ckey(ckey) + if (!ban) + usr << "Error: The ban disappeared." + return + + found = 0 + for (var/key in ban["keys"]) + if (ckey(key) == alt) + ban["keys"] -= key + found = 1 + break + + if (!found) + usr << "Error: [alt] link to [ckey]'s sticky ban disappeared." + return + + world.SetConfig("ban",ckey,list2stickyban(ban)) + + log_admin("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban") + message_admins("[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban") + + if ("edit") + if (!data["ckey"]) + return + var/ckey = data["ckey"] + var/ban = get_stickyban_from_ckey(ckey) + if (!ban) + usr << "Error: No sticky ban for [ckey] found!" + return + var/oldreason = ban["message"] + var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null + if (!reason || reason == oldreason) + return + //we have to do this again incase something changed while we waited for input + ban = get_stickyban_from_ckey(ckey) + if (!ban) + usr << "Error: The ban disappeared." + return + ban["message"] = "[reason]" + + world.SetConfig("ban",ckey,list2stickyban(ban)) + + log_admin("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]") + message_admins("[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]") + + spawn(10) + stickyban_show() + +/datum/admins/proc/stickyban_gethtml(ckey, ban) + . = "\[-\][ckey]
" + . += "[ban["message"]] \[Edit\]
" + if (ban["admin"]) + . += "[ban["admin"]]
" + else + . += "LEGACY
" + . += "Caught keys
\n
    " + for (var/key in ban["keys"]) + if (ckey(key) == ckey) + continue + . += "
  1. \[-\][key]
  2. " + . += "
\n" + +/datum/admins/proc/stickyban_show() + if(!check_rights(R_BAN)) + return + + var/list/bans = sortList(world.GetConfig("ban")) + var/banhtml = "" + for(var/key in bans) + var/ckey = ckey(key) + var/ban = stickyban2list(world.GetConfig("ban",key)) + banhtml += "

\n" + banhtml += stickyban_gethtml(ckey,ban) + + var/html = {" + + Sticky Bans + + +

All Sticky Bans:

\[+\]
+ [banhtml] + + "} + usr << browse(html,"window=stickybans;size=700x400") + +/proc/get_stickyban_from_ckey(var/ckey) + if (!ckey) + return null + ckey = ckey(ckey) + . = null + for (var/key in world.GetConfig("ban")) + if (ckey(key) == ckey) + . = stickyban2list(world.GetConfig("ban",key)) + break + +/proc/stickyban2list(var/ban) + if (!ban) + return null + . = params2list(ban) + .["keys"] = text2list(.["keys"], ",") + .["type"] = text2list(.["type"], ",") + .["IP"] = text2list(.["IP"], ",") + .["computer_id"] = text2list(.["computer_id"], ",") + +/proc/list2stickyban(var/list/ban) + if (!ban || !islist(ban)) + return null + . = ban.Copy() + if (.["keys"]) + .["keys"] = list2text(.["keys"], ",") + if (.["type"]) + .["type"] = list2text(.["type"], ",") + if (.["IP"]) + .["IP"] = list2text(.["IP"], ",") + if (.["computer_id"]) + .["computer_id"] = list2text(.["computer_id"], ",") + . = list2params(.) + +/client/proc/stickybanpanel() + set name = "Sticky Ban Panel" + set category = "Admin" + + if(!check_rights(R_BAN)) + return + + holder.stickyban_show() + \ No newline at end of file diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index cff4e611d65..b922b4979c8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -25,6 +25,9 @@ message_admins("[key_name_admin(usr)] rejected [key_name_admin(C.mob)]'s admin help") log_admin("[key_name(usr)] rejected [key_name(C.mob)]'s admin help") + + if(href_list["stickyban"]) + stickyban(href_list["stickyban"],href_list) if(href_list["makeAntag"]) switch(href_list["makeAntag"]) @@ -123,6 +126,17 @@ return banduration = null banjob = null + if(BANTYPE_ADMIN_PERMA) + if(!banckey || !banreason) + usr << "Not enough parameters (Requires ckey and reason)" + return + banduration = null + banjob = null + if(BANTYPE_ADMIN_TEMP) + if(!banckey || !banreason || !banduration) + usr << "Not enough parameters (Requires ckey, reason and duration)" + return + banjob = null var/mob/playermob diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 69999e89940..198e5c8a042 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -92,7 +92,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," //send this msg to all admins var/admin_number_afk = 0 var/list/modholders = list() - var/list/banholders = list() var/list/adminholders = list() for(var/client/X in admins) if(check_rights(R_MOD|R_MENTOR, 0, X.mob)) @@ -103,8 +102,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(X.is_afk()) admin_number_afk++ adminholders += X - if(check_rights(R_BAN, 0, X.mob)) - banholders += X switch(selected_type) if("Question") @@ -113,15 +110,14 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(X.prefs.sound & SOUND_ADMINHELP) X << 'sound/effects/adminhelp.ogg' X << msg - else - if(adminholders.len) - for(var/client/X in adminholders) - if(X.prefs.sound & SOUND_ADMINHELP) - X << 'sound/effects/adminhelp.ogg' - X << msg - else if("Player Complaint") - if(banholders.len) - for(var/client/X in banholders) + if(adminholders.len) + for(var/client/X in adminholders) + if(X.prefs.sound & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' + X << msg + if("Player Complaint") + if(adminholders.len) + for(var/client/X in adminholders) if(X.prefs.sound & SOUND_ADMINHELP) X << 'sound/effects/adminhelp.ogg' X << msg diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 542a02ee231..8fc24a175cd 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -83,11 +83,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(!target) usr << "Error: callproc(): owner of proc no longer exists." return + message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc else //this currently has no hascall protection. wasn't able to get it working. - log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]") + log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]") returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc usr << "[procname] returned: [returnval ? returnval : "null"]" @@ -115,7 +117,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(!A || !IsValidSrc(A)) usr << "Error: callproc_datum(): owner of proc no longer exists." return - log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + message_admins("[key_name_admin(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]") + log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]") spawn() var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 177f5f49f34..6c5db7cd1e6 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -1,6 +1,9 @@ /client/proc/air_status(turf/target as turf) set category = "Debug" set name = "Display Air Status" + + if(!check_rights(R_DEBUG)) + return if(!isturf(target)) return @@ -15,11 +18,22 @@ usr << "\blue @[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("\red BURNING"):(null)]" for(var/datum/gas/trace_gas in GM.trace_gases) usr << "[trace_gas.type]: [trace_gas.moles]" + + message_admins("[key_name_admin(usr)] has checked the air status of [T]") + log_admin("[key_name(usr)] has checked the air status of [T]") + feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/fix_next_move() set category = "Debug" set name = "Unfreeze Everyone" + + if(!check_rights(R_DEBUG)) + return + + message_admins("[key_name_admin(usr)] has unfrozen everyone") + log_admin("[key_name(usr)] has unfrozen everyone") + var/largest_move_time = 0 var/largest_click_time = 0 var/mob/largest_move_mob = null @@ -42,15 +56,20 @@ log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]") M.next_move = 1 M.next_click = 0 + message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1) message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1) message_admins("world.time = [world.time]", 1) + feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return /client/proc/radio_report() set category = "Debug" set name = "Radio report" + + if(!check_rights(R_DEBUG)) + return var/filters = list( "1" = "RADIO_TO_AIRALARM", @@ -83,15 +102,22 @@ output += "    [device]
" usr << browse(output,"window=radioreport") + + message_admins("[key_name_admin(usr)] has generated a radio report") + log_admin("[key_name(usr)] has generated a radio report") + feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/reload_admins() set name = "Reload Admins" set category = "Debug" - if(!check_rights(R_SERVER)) return + if(!check_rights(R_SERVER)) + return - message_admins("[usr] manually reloaded admins") + message_admins("[key_name_admin(usr)] has manually reloaded admins") + log_admin("[key_name(usr)] has manually reloaded admins") + load_admins() feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -100,15 +126,24 @@ set name = "Print Jobban Log" set desc = "This spams all the active jobban entries for the current round to standard output." set category = "Debug" + + if(!check_rights(R_DEBUG)) + return usr << "Jobbans active in this round." for(var/t in jobban_keylist) usr << "[t]" + + message_admins("[key_name_admin(usr)] has printed the jobban log") + log_admin("[key_name(usr)] has printed the jobban log") /client/proc/print_jobban_old_filter() set name = "Search Jobban Log" set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output." set category = "Debug" + + if(!check_rights(R_DEBUG)) + return var/filter = input("Contains what?","Filter") as text|null if(!filter) @@ -118,3 +153,6 @@ for(var/t in jobban_keylist) if(findtext(t, filter)) usr << "[t]" + + message_admins("[key_name_admin(usr)] has searched the jobban log for [filter]") + log_admin("[key_name(usr)] has searched the jobban log for [filter]") diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index f0532fbd254..134cc9ff3f5 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -323,8 +323,12 @@ var/list/forbidden_varedit_object_types = list( for(var/p in forbidden_varedit_object_types) if( istype(O,p) ) - usr << "\red It is forbidden to edit this object's variables." + usr << "It is forbidden to edit this object's variables." return + + if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key")) + usr << "You cannot edit ckeys on client objects." + return var/class var/variable diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index a49cd02c06b..e047a9c6497 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -567,7 +567,7 @@ Traitors and the like can also be revived with the previous role mostly intact. message_admins("[key_name_admin(src)] has created a command report", 1) feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world) +/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in view()) set category = "Admin" set name = "Delete" @@ -596,7 +596,7 @@ Traitors and the like can also be revived with the previous role mostly intact. src << "[job.title]: [job.total_positions]" feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world) +/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in view()) set category = "Event" set name = "Explosion" @@ -627,7 +627,7 @@ Traitors and the like can also be revived with the previous role mostly intact. else return -/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world) +/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in view()) set category = "Special Verbs" set name = "EM Pulse" diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 3e2910fa556..ce914b6c407 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -207,7 +207,7 @@ dead_mob_list -= C living_mob_list += C C.stat = CONSCIOUS - C.tod = null + C.timeofdeath = 0 C.setToxLoss(0) C.setOxyLoss(0) C.setCloneLoss(0) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 5212d6e84e8..cc3b54b6bde 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -272,7 +272,7 @@ if(holder) add_admin_verbs() - admin_memo_output("Show", 0) + admin_memo_output("Show", 0, 1) // Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays. // (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise) @@ -282,15 +282,20 @@ winset(src, null, "command=\".configure graphics-hwmode on\"") log_client_to_db() + + if (ckey in clientmessages) + for (var/message in clientmessages[ckey]) + src << message + clientmessages.Remove(ckey) if (config && config.autoconvert_notes) convert_notes_sql(ckey) send_resources() - ////////////// - //DISCONNECT// - ////////////// +////////////// +//DISCONNECT// +////////////// /client/Del() if(holder) holder.owner = null diff --git a/code/modules/client/message.dm b/code/modules/client/message.dm new file mode 100644 index 00000000000..6406a7d051a --- /dev/null +++ b/code/modules/client/message.dm @@ -0,0 +1,9 @@ +var/list/clientmessages = list() + +proc/addclientmessage(var/ckey, var/message) + ckey = ckey(ckey) + if (!ckey || !message) + return + if (!(ckey in clientmessages)) + clientmessages[ckey] = list() + clientmessages[ckey] += message diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 06ac7184749..210b1ddea65 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -367,7 +367,7 @@ datum/preferences dat += "
Eyes
" dat += "Change Color
__

" - if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins + if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins dat += "
Body Color
" dat += "Change Color
__
" @@ -1028,7 +1028,7 @@ datum/preferences if(species == "Human") s_tone = random_skin_tone() if("s_color") - if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Wryn" || species == "Vulpkanin") + if(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Wyrn", "Vulpkanin", "Machine")) r_skin = rand(0,255) g_skin = rand(0,255) b_skin = rand(0,255) @@ -1115,6 +1115,8 @@ datum/preferences b_hair = 0//hex2num(copytext(new_hair, 6, 8)) s_tone = 0 + + body_accessory = null //no vulpatail on humans damnit if("speciesprefs")//oldvox code speciesprefs = !speciesprefs @@ -1268,7 +1270,7 @@ datum/preferences s_tone = 35 - max(min( round(new_s_tone), 220),1) if("skin") - if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People"|| species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user)) + if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null if(new_skin) r_skin = hex2num(copytext(new_skin, 2, 4)) diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm index 38006797487..98c26df8ec8 100644 --- a/code/modules/client/preferences_mysql.dm +++ b/code/modules/client/preferences_mysql.dm @@ -264,10 +264,10 @@ job_karma_high='[job_karma_high]', job_karma_med='[job_karma_med]', job_karma_low='[job_karma_low]', - flavor_text='[sql_sanitize_text(flavor_text)]', - med_record='[sql_sanitize_text(med_record)]', - sec_record='[sql_sanitize_text(sec_record)]', - gen_record='[sql_sanitize_text(gen_record)]', + flavor_text='[sql_sanitize_text(html_decode(flavor_text))]', + med_record='[sql_sanitize_text(html_decode(med_record))]', + sec_record='[sql_sanitize_text(html_decode(sec_record))]', + gen_record='[sql_sanitize_text(html_decode(gen_record))]', player_alt_titles='[playertitlelist]', be_special='[be_special]', disabilities='[disabilities]', @@ -321,7 +321,7 @@ '[job_medsci_high]', '[job_medsci_med]', '[job_medsci_low]', '[job_engsec_high]', '[job_engsec_med]', '[job_engsec_low]', '[job_karma_high]', '[job_karma_med]', '[job_karma_low]', - '[sql_sanitize_text(flavor_text)]', '[sql_sanitize_text(med_record)]', '[sql_sanitize_text(sec_record)]', '[sql_sanitize_text(gen_record)]', + '[sql_sanitize_text(html_encode(flavor_text))]', '[sql_sanitize_text(html_encode(med_record))]', '[sql_sanitize_text(html_encode(sec_record))]', '[sql_sanitize_text(html_encode(gen_record))]', '[playertitlelist]', '[be_special]', '[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]', '[socks]', '[body_accessory]') diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 32b99189599..7bfa16b8ba8 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -5,7 +5,7 @@ desc = "A special containment suit designed to protect a plasmaman's volatile body from outside exposure and quickly extinguish it in emergencies." allowed = list(/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank) slowdown = 0 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) + armor = list(melee = 0, bullet = 0, laser = 0 ,energy = 0, bomb = 0, bio = 100, rad = 20) heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT @@ -16,9 +16,9 @@ icon_state = "plasmaman_suit" item_state = "plasmaman_suit" - var/next_extinguish=0 - var/extinguish_cooldown=10 SECONDS - var/extinguishes_left=10 // Yeah yeah, reagents, blah blah blah. This should be simple. + var/next_extinguish = 0 + var/extinguish_cooldown = 10 SECONDS + var/extinguishes_left = 10 // Yeah yeah, reagents, blah blah blah. This should be simple. /obj/item/clothing/suit/space/eva/plasmaman/examine(mob/user) ..(user) @@ -46,35 +46,26 @@ var/base_state = "plasmaman_helmet" var/brightness_on = 4 //luminosity when on var/on = 0 - var/no_light=0 // Disable the light on the atmos suit action_button_name = "Toggle Helmet Light" /obj/item/clothing/head/helmet/space/eva/plasmaman/attack_self(mob/user) if(!isturf(user.loc)) - user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities. - return - if(no_light) + user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities. return + toggle_light(user) + +/obj/item/clothing/head/helmet/space/eva/plasmaman/proc/toggle_light(mob/user) on = !on icon_state = "[base_state][on]" - if(on) user.set_light(user.luminosity + brightness_on) - else user.set_light(user.luminosity - brightness_on) - user.update_inv_head() - -/obj/item/clothing/head/helmet/space/eva/plasmaman/pickup(mob/user) - if(on) - user.set_light(user.luminosity + brightness_on) -// user.UpdateLuminosity() + if(on) + set_light(brightness_on) + else set_light(0) -/obj/item/clothing/head/helmet/space/eva/plasmaman/dropped(mob/user) - if(on) - user.set_light(user.luminosity - brightness_on) -// user.UpdateLuminosity() - set_light(brightness_on) - - + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_head() // ENGINEERING /obj/item/clothing/suit/space/eva/plasmaman/assistant @@ -305,7 +296,7 @@ /obj/item/clothing/suit/space/eva/plasmaman/nuclear name = "blood red plasmaman suit" icon_state = "plasmaman_Nukeops" - armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60) + armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs) siemens_coefficient = 0.6 @@ -313,20 +304,5 @@ name = "blood red plasmaman helmet" icon_state = "plasmaman_Nukeops_helmet0" base_state = "plasmaman_Nukeops_helmet" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) + armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50) siemens_coefficient = 0.6 - var/obj/machinery/camera/camera - -/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/attack_self(mob/user) - if(camera) - ..(user) - else - camera = new /obj/machinery/camera(src) - camera.network = list("NUKE") - cameranet.removeCamera(camera) - camera.c_tag = user.name - user << "User scanned as [camera.c_tag]. Camera activated." - -/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/examine(mob/user) - if(..(user, 1)) - user << "This helmet has a built-in camera. It's [camera ? "" : "in"]active." \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index b3c5d19b6d7..8f1703a3325 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -27,20 +27,24 @@ "Vox" = 'icons/obj/clothing/species/vox/hats.dmi', ) - attack_self(mob/user) - if(!isturf(user.loc)) - user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities. - return - on = !on - icon_state = "rig[on]-[_color]" -// item_state = "rig[on]-[color]" +/obj/item/clothing/head/helmet/space/rig/attack_self(mob/user) + if(!isturf(user.loc)) + user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities. + return + toggle_light(user) - if(on) set_light(brightness_on) - else set_light(0) +/obj/item/clothing/head/helmet/space/rig/proc/toggle_light(mob/user) + on = !on + icon_state = "rig[on]-[_color]" - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_head() + if(on) + set_light(brightness_on) + else + set_light(0) + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_head() /obj/item/clothing/suit/space/rig name = "hardsuit" @@ -98,7 +102,7 @@ else M << "Your suit's helmet deploys with a hiss." //TODO: Species check, skull damage for forcing an unfitting helmet on? - helmet.loc = H + helmet.forceMove(H) H.equip_to_slot(helmet, slot_head) helmet.flags |= NODROP @@ -107,7 +111,7 @@ M << "You are unable to deploy your suit's magboots as \the [H.shoes] are in the way." else M << "Your suit's boots deploy with a hiss." - boots.loc = H + boots.forceMove(H) H.equip_to_slot(boots, slot_shoes) boots.flags |= NODROP @@ -122,7 +126,7 @@ if(helmet && H.head == helmet) helmet.flags &= ~NODROP H.unEquip(helmet) - helmet.loc = src + helmet.forceMove(src) if(boots) H = boots.loc @@ -130,58 +134,15 @@ if(boots && H.shoes == boots) boots.flags &= ~NODROP H.unEquip(boots) - boots.loc = src - -/* -/obj/item/clothing/suit/space/rig/verb/get_mounted_device() - - set name = "Deploy Mounted Device" - set category = "Object" - set src in usr - - if(!can_mount) - verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device - verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device - return - - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - if(active_device) - usr << "You already have \the [active_device] deployed." - return - - if(!mounted_devices.len) - usr << "You do not have any devices mounted on \the [src]." - return - -/obj/item/clothing/suit/space/rig/verb/stow_mounted_device() - - set name = "Stow Mounted Device" - set category = "Object" - set src in usr - - if(!can_mount) - verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device - verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device - return - - if(!istype(usr, /mob/living)) return - - if(usr.stat) return - - if(!active_device) - usr << "You have no device currently deployed." - return -*/ - + boots.forceMove(src) + /obj/item/clothing/suit/space/rig/verb/toggle_helmet() - set name = "Toggle Helmet" set category = "Object" set src in usr - if(!istype(src.loc,/mob/living)) return + if(!isliving(usr)) + return if(!helmet) usr << "There is no helmet installed." @@ -197,23 +158,22 @@ helmet.flags &= ~NODROP H.unEquip(helmet) helmet.loc = src - H << "\blue You retract your hardsuit helmet." + H << "You retract your hardsuit helmet." else if(H.head) - H << "\red You cannot deploy your helmet while wearing another helmet." + H << "You cannot deploy your helmet while wearing another helmet." return //TODO: Species check, skull damage for forcing an unfitting helmet on? helmet.loc = H helmet.pickup(H) H.equip_to_slot(helmet, slot_head) helmet.flags |= NODROP - H << "\blue You deploy your hardsuit helmet, sealing you off from the world." + H << "You deploy your hardsuit helmet, sealing you off from the world." H.update_inv_head() /obj/item/clothing/suit/space/rig/attackby(obj/item/W as obj, mob/user as mob, params) - - if(!istype(user,/mob/living)) return - + if(!isliving(user)) + return if(istype(src.loc,/mob/living)) user << "How do you propose to modify a hardsuit while it is being worn?" @@ -230,7 +190,7 @@ if(!boots) user << "\The [src] does not have any boots installed." else - user << "You detatch \the [boots] from \the [src]'s boot mounts." + user << "You detach \the [boots] from \the [src]'s boot mounts." boots.loc = get_turf(src) boots = null return @@ -338,8 +298,9 @@ /obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) if(!isturf(user.loc)) - user << "You cannot toggle your helmet while in this [user.loc]" //To prevent some lighting anomalities. + user << "You cannot toggle your helmet while in this [user.loc]." //To prevent some lighting anomalities. return + on = !on if(on) user << "You switch your helmet to travel mode. It will allow you to stand in zero pressure environments, at the cost of speed and armor." @@ -484,7 +445,6 @@ heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT - /obj/item/clothing/suit/space/rig/atmos desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." icon_state = "rig-atmos" diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index e7e1e299f27..93c9733eae0 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -62,6 +62,7 @@ Item.loc = get_turf(M.loc) HackProperties(Item,propadjust) + M.regenerate_icons() // This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X /proc/HackProperties(var/mob/living/carbon/human/M,var/obj/item/I,var/script) diff --git a/code/modules/DetectiveWork/detective_work.dm b/code/modules/detective_work/detective_work.dm similarity index 100% rename from code/modules/DetectiveWork/detective_work.dm rename to code/modules/detective_work/detective_work.dm diff --git a/code/modules/DetectiveWork/evidence.dm b/code/modules/detective_work/evidence.dm similarity index 100% rename from code/modules/DetectiveWork/evidence.dm rename to code/modules/detective_work/evidence.dm diff --git a/code/modules/DetectiveWork/footprints_and_rag.dm b/code/modules/detective_work/footprints_and_rag.dm similarity index 100% rename from code/modules/DetectiveWork/footprints_and_rag.dm rename to code/modules/detective_work/footprints_and_rag.dm diff --git a/code/modules/DetectiveWork/scanner.dm b/code/modules/detective_work/scanner.dm similarity index 100% rename from code/modules/DetectiveWork/scanner.dm rename to code/modules/detective_work/scanner.dm diff --git a/code/modules/garbage collection/__gc_info.dm b/code/modules/garbage_collection/__gc_info.dm similarity index 100% rename from code/modules/garbage collection/__gc_info.dm rename to code/modules/garbage_collection/__gc_info.dm diff --git a/code/modules/garbage collection/garbage_collector.dm b/code/modules/garbage_collection/garbage_collector.dm similarity index 100% rename from code/modules/garbage collection/garbage_collector.dm rename to code/modules/garbage_collection/garbage_collector.dm diff --git a/code/modules/garbage collection/gc_testing.dm b/code/modules/garbage_collection/gc_testing.dm similarity index 100% rename from code/modules/garbage collection/gc_testing.dm rename to code/modules/garbage_collection/gc_testing.dm diff --git a/code/modules/genetics2/computer.dm b/code/modules/genetics2/computer.dm deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/code/modules/genetics2/genetree.dm b/code/modules/genetics2/genetree.dm deleted file mode 100644 index aa8d1ba7571..00000000000 --- a/code/modules/genetics2/genetree.dm +++ /dev/null @@ -1,63 +0,0 @@ -// Management of available genes. - -/datum/genetree - var/list/sectors=list() - var/list/dependencies=list() - var/list/dependants=list() - var/obj/machinery/networked/biomass_controller/biomass = null - -/datum/genetree/New(var/obj/machinery/networked/biomass_controller/holder) - biomass = holder - // Build list of all sectors - for(var/typepath in subtypesof(/datum/genetic_sector)) - var/datum/genetic_sector/sector = new typepath - sectors[sector.id]=sector - - if(sector.prerequisites.len > 0) - sector.locked=1 - - // Make list of things that depend on this sector. - dependencies[sector.id]=sector.prerequisites - - // Generate reverse dependencies - for(var/dependee in sector.prerequisites) - if(!(dependee in dependants)) - dependants[dependee]=list(sector.id) - else - var/list/D = dependants[dependee] - D.Add(sector.name) - -/datum/genetree/proc/IsActive(var/sname) - var/datum/genetic_sector/sector = sectors[sname] - return sector.active - -/datum/genetree/proc/CanActivateSector(var/sname) - var/datum/genetic_sector/sector = sectors[sname] - for(var/dep in sector.prerequisites) - if(!IsActive(sector.id)) - return 0 - return biomass.available >= sector.required_biomass - -// Does NOT check for biomass -/datum/genetree/proc/ActivateSector(var/sname) - var/datum/genetic_sector/sector = sectors[sname] - sector.active = 1 - sector.OnActivate() - for(var/subsect in dependants[sname]) - var/datum/genetic_sector/subsector = sectors[subsect] - subsector.locked=0 - -/datum/genetree/proc/CheckSectors() - var/sectors_changed=0 - for(var/sname in sectors) - var/datum/genetic_sector/sector = sectors[sname] - var/pstate=sector.active - sector.active=1 - for(var/prereq in sector.prerequisites) - if(!IsActive(prereq)) - sector.active=0 - break - if(pstate != sector.active) - sectors_changed = 1 - if(sectors_changed) - CheckSectors() \ No newline at end of file diff --git a/code/modules/genetics2/sectors.dm b/code/modules/genetics2/sectors.dm deleted file mode 100644 index aec12619180..00000000000 --- a/code/modules/genetics2/sectors.dm +++ /dev/null @@ -1,110 +0,0 @@ -var/global/current_sector_id=0 -/datum/genetic_sector - var/name = "UNKNOWN SECTOR" - var/desc = "LOLIDK" - - var/id = "" - var/uniqid = "" // 3-char ID, shown when locked. - var/list/prerequisites = list() - var/list/blocks_txt = list() - var/list/blocks = list() // DO NOT FUCKING USE THIS - var/required_biomass = 0 // In hominids (/mob/living/carbon) - var/time_required = 300 // Decaseconds required to unlock - var/time_researched = 0 - var/active=0 // Accessible - var/locked=0 // Cannot be purchased (yet) - -/datum/genetic_sector/New() - uniqid = add_zero2("[current_sector_id++]",3) - - // Set blocks - for(var/blockname in blocks_txt) - var/block = assigned_blocks[blockname] - if(block) - blocks += block - -/////////////////////////////////////// -// SECTORS -/////////////////////////////////////// - -/datum/genetic_sector/metabolism - id = "metabolism" - name = "Metabolism" - desc = "Grants access to areas of DNA that affect how the body controls its temperature." - required_biomass = 1 - time_required = 30 SECONDS - blocks_txt=list( - "COLD", - "FIRE", - "IMMOLATE", - "SOBER", - "MELT", - "FAT" - ) - -/datum/genetic_sector/mind - id = "mind" - name = "Mental Aptitude" - desc = "Reveals parts of DNA that affect mental capabilities" - required_biomass = 2 - time_required = 30 SECONDS - blocks_txt=list( - "PSYRESIST", - "HALLUCINATION", - "TWITCH", - "EPILEPSY", - ) - -/datum/genetic_sector/teleability - id = "teleability" - name = "Teleability" - desc = "Activates unused portions of the brain that can affect people a great distance away." - prerequisites = list("mind") - required_biomass = 4 - time_required = 1 MINUTES - blocks_txt = list( - "REMOTEVIEW", - "REMOTETALK", - "CRYO", - "EMPATH" - ) - -/datum/genetic_sector/telekinesis - id = "telekinesis" - name = "Telekinesis" - desc = "Activates unused portions of the brain that can affect objects a great distance away." - prerequisites = list("teleability") - required_biomass = 5 - time_required = 2 MINUTES - blocks_txt = list( - "TELE", - "FAKE" - ) - -/datum/genetic_sector/senses - id = "senses" - name = "Senses" - desc = "Accesses genes that affect vision and hearing." - prerequisites = list("mind") - required_biomass = 4 - time_required = 30 SECONDS - blocks_txt = list( - "XRAY", - "BLIND", - "GLASSES", - "EMPATH", - "DEAF" - ) - -/datum/genetic_sector/respiration - id = "respiration" - name = "Respiration" - desc = "Mess around with genes that affect breathing and lungs." - prerequisites = list("metabolism") - time_required = 1 MINUTES - required_biomass = 4 - blocks_txt = list( - "NOBREATH", - "COUGH", - "INCREASERUN", - ) \ No newline at end of file diff --git a/code/modules/icon generation/Bluespaced.dm b/code/modules/icon generation/Bluespaced.dm deleted file mode 100644 index 697b9e97196..00000000000 --- a/code/modules/icon generation/Bluespaced.dm +++ /dev/null @@ -1,243 +0,0 @@ -/proc/bsi_cast_ray(icon/I, list/start, list/end) - - if(abs(start[1] - end[1]) > abs(start[2] - end[2])) - var/dist = abs(start[1] - end[1]) * 2 - - for(var/i = 1, i <= dist, i++) - var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist))) - var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist))) - - if(I.GetPixel(x, y) != null) - return list(x, y) - - else - var/dist = abs(start[2] - end[2]) * 2 - - for(var/i = 1, i <= dist, i++) - var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist))) - var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist))) - - if(I.GetPixel(x, y) != null) - return list(x, y) - - return null - -/proc/bsi_split_colors(color) - if(color == null) - return list(0, 0, 0, 0) - - var/list/colors = list(0, 0, 0, 0) - colors[1] = hex2num(copytext(color, 2, 4)) - colors[2] = hex2num(copytext(color, 4, 6)) - colors[3] = hex2num(copytext(color, 6, 8)) - colors[4] = (length(color) > 7)? hex2num(copytext(color, 8, 10)) : 255 - - return colors - -/proc/bsi_spread(icon/I, list/start_point) - var/list/queue = list() - queue[++queue.len] = start_point - - var/i = 0 - - while(i++ < length(queue)) - var/x = queue[i][1] - var/y = queue[i][2] - - var/list/pixel = bsi_split_colors(I.GetPixel(x, y)) - if(pixel[4] == 0) - continue - - var/list/n = (y < I.Height())? bsi_split_colors(I.GetPixel(x, y + 1)) : list(0, 0, 0, 0) - var/list/s = (y > 1)? bsi_split_colors(I.GetPixel(x, y - 1)) : list(0, 0, 0, 0) - var/list/e = (x < I.Width())? bsi_split_colors(I.GetPixel(x + 1, y)) : list(0, 0, 0, 0) - var/list/w = (x > 1)? bsi_split_colors(I.GetPixel(x - 1, y)) : list(0, 0, 0, 0) - - var/value = (i == 1)? 16 : max(n[1] - 1, e[1] - 1, s[1] - 1, w[1] - 1) - - if(prob(50)) - value = max(0, value - 1) - - if(prob(50)) - value = max(0, value - 1) - - if(prob(50)) - value = max(0, value - 1) - - if(value <= pixel[1]) - continue - - var/v2 = 256 - ((16 - value) * (16 - value)) - - I.DrawBox(rgb(value, v2, pixel[4] - v2, pixel[4]), x, y) - - if(n[4] != 0 && n[1] < value - 1) - queue[++queue.len] = list(x, y + 1) - - if(s[4] != 0 && s[1] < value - 1) - queue[++queue.len] = list(x, y - 1) - - if(e[4] != 0 && e[1] < value - 1) - queue[++queue.len] = list(x + 1, y) - - if(w[4] != 0 && w[1] < value - 1) - queue[++queue.len] = list(x - 1, y) - - - - - -/proc/bsi_generate_mask(icon/source, state) - var/icon/mask = icon(source, state) - - mask.MapColors( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 1, - 0, 0, 0, 0) - - var/hits = 0 - - for(var/i = 1, i <= 10, i++) - var/point1 - var/point2 - - if(prob(50)) - if(prob(50)) - point1 = list(rand(1, mask.Width()), mask.Height()) - point2 = list(rand(1, mask.Width()), 1) - - else - point2 = list(rand(1, mask.Width()), mask.Height()) - point1 = list(rand(1, mask.Width()), 1) - - else - if(prob(50)) - point1 = list(mask.Width(), rand(1, mask.Height())) - point2 = list(1, rand(1, mask.Height())) - - else - point2 = list(mask.Width(), rand(1, mask.Height())) - point1 = list(1, rand(1, mask.Height())) - - var/hit = bsi_cast_ray(mask, point1, point2) - - if(hit == null) - continue - - hits++ - - bsi_spread(mask, hit) - - if(prob(20 + hits * 20)) - break - - if(hits == 0) - return null - - else - return mask - -/proc/generate_bluespace_icon(icon/source, state) - - var/icon/mask = bsi_generate_mask(source, state) - - if(mask == null) - return source - - var/icon/unaffected = icon(mask) - unaffected.MapColors( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 255, 255, 255, 0) - - var/icon/temp = icon(source, state) //Mask already contains the original alpha values, avoid squaring them - temp.MapColors( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 0, 255) - - unaffected.Blend(temp, ICON_MULTIPLY) - - var/icon/bluespaced = icon(mask) - bluespaced.MapColors( - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 0, 0, 0, - 1, 1, 1, 0) - - bluespaced.Blend(icon(source, state), ICON_MULTIPLY) - - var/list/frames = list( - list(0.000,20), - list(0.020, 5), - list(0.050, 4), - list(0.080, 5), - list(0.100,10), - list(0.080, 5), - list(0.050, 4), - list(0.020, 5), - - list(0.000,20), - list(0.020, 5), - list(0.050, 4), - list(0.080, 5), - list(0.100,10), - list(0.080, 5), - list(0.050, 4), - list(0.020, 5), - - list(0.000,20), - list(0.020, 5), - list(0.050, 4), - list(0.080, 5), - list(0.100,10), - list(0.080, 5), - list(0.050, 4), - list(0.020, 5), - ) - - var/list/colors = list( - list( 75, 75, 75, 0), - list( 25, 25, 25, 0), - list( 75, 75, 75, 0), - list( 25, 25, 75, 0), - list( 75, 75, 300, 0), - list( 25, 25, 300, 0), - list(255, 255, 255, 0), - list( 0, 0, 0, 255), - list( 0, 0, 0, 0), - list( 0, 0, 0, 0), - ) - - for(var/i = 1, i <= rand(1, 5), i++) - var/f = rand(1, length(frames)) - - if(frames[f][2] > 1) - frames[f][2]-- - frames.Insert(f, 0) - - frames[f] = list(0.8, 1) - - var/icon/result = generate_color_animation(bluespaced, colors, frames) - result.Blend(unaffected, ICON_UNDERLAY) - - return result - - - -/atom/verb/test() - set src in view() - src.icon = generate_bluespace_icon(src.icon, src.icon_state) - -/mob/verb/bluespam() - for(var/turf/t in view(5)) - var/obj/s = new /obj/square(t) - s.icon = generate_bluespace_icon(s.icon, s.icon_state) - diff --git a/code/modules/icon generation/Icon_color_animation.dm b/code/modules/icon generation/Icon_color_animation.dm deleted file mode 100644 index 1be1bfa28a9..00000000000 --- a/code/modules/icon generation/Icon_color_animation.dm +++ /dev/null @@ -1,96 +0,0 @@ -//---------------------------------------- -// -// Return a copy of the provided icon, -// after calling MapColors on it. The -// color values are linearily interpolated -// between the pairs provided, based on -// the ratio argument. -// -//---------------------------------------- - -/proc/MapColors_interpolate(icon/input, ratio, - rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, - gr1, gg1, gb1, ga1, gr2, gg2, gb2, ga2, - br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, - ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2, - zr1, zg1, zb1, za1, zr2, zg2, zb2, za2) - var/r = ratio - var/i = 1 - ratio - var/icon/I = icon(input) - - I.MapColors( - (rr1 * r + rr2 * i) / 255.0, (rg1 * r + rg2 * i) / 255.0, (rb1 * r + rb2 * i) / 255.0, (ra1 * r + ra2 * i) / 255.0, - (gr1 * r + gr2 * i) / 255.0, (gg1 * r + gg2 * i) / 255.0, (gb1 * r + gb2 * i) / 255.0, (ga1 * r + ga2 * i) / 255.0, - (br1 * r + br2 * i) / 255.0, (bg1 * r + bg2 * i) / 255.0, (bb1 * r + bb2 * i) / 255.0, (ba1 * r + ba2 * i) / 255.0, - (ar1 * r + ar2 * i) / 255.0, (ag1 * r + ag2 * i) / 255.0, (ab1 * r + ab2 * i) / 255.0, (aa1 * r + aa2 * i) / 255.0, - (zr1 * r + zr2 * i) / 255.0, (zg1 * r + zg2 * i) / 255.0, (zb1 * r + zb2 * i) / 255.0, (za1 * r + za2 * i) / 255.0) - - return I - - - - -//---------------------------------------- -// -// Extension of the above that takes a -// list of lists of color values, rather -// than a large number of arguments. -// -//---------------------------------------- - -/proc/MapColors_interpolate_list(icon/I, ratio, list/colors) - var/list/c[10] - - //Provide default values for any missing colors (without altering the original list - for(var/i = 1, i <= 10, i++) - c[i] = list(0, 0, 0, (i == 7 || i == 8)? 255 : 0) - - if(istype(colors[i], /list)) - for(var/j = 1, j <= 4, j++) - if(j <= length(colors[i]) && isnum(colors[i][j])) - c[i][j] = colors[i][j] - - return MapColors_interpolate(I, ratio, - colors[ 1][1], colors[ 1][2], colors[ 1][3], colors[ 1][4], // Red 1 - colors[ 2][1], colors[ 2][2], colors[ 2][3], colors[ 2][4], // Red 2 - colors[ 3][1], colors[ 3][2], colors[ 3][3], colors[ 3][4], // Green 1 - colors[ 4][1], colors[ 4][2], colors[ 4][3], colors[ 4][4], // Green 2 - colors[ 5][1], colors[ 5][2], colors[ 5][3], colors[ 5][4], // Blue 1 - colors[ 6][1], colors[ 6][2], colors[ 6][3], colors[ 6][4], // Blue 2 - colors[ 7][1], colors[ 7][2], colors[ 7][3], colors[ 7][4], // Alpha 1 - colors[ 8][1], colors[ 8][2], colors[ 8][3], colors[ 8][4], // Alpha 2 - colors[ 9][1], colors[ 9][2], colors[ 9][3], colors[ 9][4], // Added 1 - colors[10][1], colors[10][2], colors[10][3], colors[10][4]) // Added 2 - - - - - -//---------------------------------------- -// -// Take the source image, and return an animated -// version, that transitions between the provided -// color mappings, according to the provided -// pattern. -// -// Colors should be in a format suitable for -// MapColors_interpolate_list, and frames should -// be a list of 'frames', where each frame is itself -// a list, element 1 being the ratio of the first -// color to the second, and element 2 being how -// long the frame lasts, in tenths of a second. -// -//---------------------------------------- - -/proc/generate_color_animation(icon/icon, list/colors, list/frames) - var/icon/out = icon('icons/effects/uristrunes.dmi', "") - var/frame_num = 1 - - for(var/frame in frames) - var/icon/I = MapColors_interpolate_list(icon, frame[1], colors) - out.Insert(I, "", 2, frame_num++, 0, frame[2]) - - return out - - - diff --git a/code/modules/icon generation/Uristrunes.dm b/code/modules/icon generation/Uristrunes.dm deleted file mode 100644 index d9c129df8ed..00000000000 --- a/code/modules/icon generation/Uristrunes.dm +++ /dev/null @@ -1,268 +0,0 @@ -//---------------------------------------- -// -// Take a source icon, convert into a mask, -// then create a border around it. -// -// The output then uses the colors and -// alpha values provided. -// -//---------------------------------------- - -/proc/create_border_image(icon/input, border_color = "#000000", fill_color = "#000000", border_alpha = 255, fill_alpha = 255) - var/icon/I = icon('icons/effects/uristrunes.dmi', "blank") - I.Blend(input, ICON_OVERLAY) - - //Discard the image - I.MapColors(0, 0, 0, 0, //-\ Ignore - 0, 0, 0, 0, //--> The - 0, 0, 0, 0, //-/ Colors - 0,255, 0, 1, //Keep alpha channel, any pixel with non-zero alpha gets max green channel - 0, 0, 0, 0) - - //Loop over the image, calculating the border value, and storing it in the red channel - //Store border's alpha in the blue channel - for(var/x = 1, x <= 32, x++) - for(var/y = 1, y <= 32, y++) - var/p = I.GetPixel(x, y) - - if(p == null) - var/n = I.GetPixel(x, y + 1) - var/s = I.GetPixel(x, y - 1) - var/e = I.GetPixel(x + 1, y) - var/w = I.GetPixel(x - 1, y) - var/ne = I.GetPixel(x + 1, y + 1) - var/se = I.GetPixel(x + 1, y - 1) - var/nw = I.GetPixel(x - 1, y + 1) - var/sw = I.GetPixel(x - 1, y - 1) - - var/sum_adj = ((n == "#00ff00"? 1 : 0) \ - + (s == "#00ff00"? 1 : 0) \ - + (e == "#00ff00"? 1 : 0) \ - + (w == "#00ff00"? 1 : 0)) - - var/sum_diag = ((ne == "#00ff00"? 1 : 0) \ - + (se == "#00ff00"? 1 : 0) \ - + (nw == "#00ff00"? 1 : 0) \ - + (sw == "#00ff00"? 1 : 0)) - - - if(sum_adj) - I.DrawBox(rgb(255, 0, 200, 0), x, y) - - else if(sum_diag) - I.DrawBox(rgb(255, 0, 100, 0), x, y) - - else - I.DrawBox(rgb(0, 0, 0, 0), x, y) - - else if(p != "#00ff00") - var/a = 255 - - if(length(p) == 9) // "#rrggbbaa", we want the aa - a = hex2num(copytext(p, 8)) - - I.DrawBox(rgb(255 - a, a, 255 - a, a), x, y) - - //Map the red and green channels to the desired output colors - I.MapColors(border_color, fill_color, rgb(0, 0, 0, border_alpha), rgb(0, 0, 0, fill_alpha), "#00000000") - - return I - - - - -//---------------------------------------- -// -// Take a source icon, convert into a mask, -// and border. Color them according to args, -// and animate. -// -//---------------------------------------- - -/proc/animate_rune_full(icon/input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2, or1, og1, ob1, oa1, or2, og2, ob2, oa2, frames) - - var/list/colors[10] - colors[ 1] = list(rr1, rg1, rb1, ra1) //Rune color 1 - colors[ 2] = list(rr2, rg2, rb2, ra2) //Rune color 2 - colors[ 3] = list(br1, bg1, bb1, ba1) //Border color 1 - colors[ 4] = list(br2, bg2, bb2, ba2) //Border color 2 - colors[ 5] = list( 0, 0, 0, 0) //Unused - colors[ 6] = list( 0, 0, 0, 0) //Unused - colors[ 7] = list(ar1, ag1, ab1, aa1) //Alpha color 1 - colors[ 8] = list(ar2, ag2, ab2, aa2) //Alpha color 2 - colors[ 9] = list(or1, og1, ob1, oa1) //Added color 1 - colors[10] = list(or2, og2, ob2, oa2) //Added color 2 - - var/icon/base = create_border_image(input, "#00ff0000", "#ff000000") - - return generate_color_animation(base, colors, frames) - - - - -//---------------------------------------- -// -// Calls the above, but accepts colors in -// the form of "#RRGGBBAA", and provides -// default values. -// -// Main limit is that it doesn't accept -// negative values, which you probably -// don't need anyway. Also missing a few -// color inputs, which would also be rarely -// used. -// -//---------------------------------------- - - -/proc/animate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000", rune_color2 = "#00000000", border_color2 = "#d8380000", alpha = 255, alpha2 = 255, frames = rune_animation) - var/rr1 = hex2num(copytext(rune_color, 2, 4)) - var/rg1 = hex2num(copytext(rune_color, 4, 6)) - var/rb1 = hex2num(copytext(rune_color, 6, 8)) - var/ra1 = hex2num(copytext(rune_color, 8, 10)) - var/rr2 = hex2num(copytext(rune_color2, 2, 4)) - var/rg2 = hex2num(copytext(rune_color2, 4, 6)) - var/rb2 = hex2num(copytext(rune_color2, 6, 8)) - var/ra2 = hex2num(copytext(rune_color2, 8, 10)) - var/br1 = hex2num(copytext(border_color, 2, 4)) - var/bg1 = hex2num(copytext(border_color, 4, 6)) - var/bb1 = hex2num(copytext(border_color, 6, 8)) - var/ba1 = hex2num(copytext(border_color, 8, 10)) - var/br2 = hex2num(copytext(border_color2, 2, 4)) - var/bg2 = hex2num(copytext(border_color2, 4, 6)) - var/bb2 = hex2num(copytext(border_color2, 6, 8)) - var/ba2 = hex2num(copytext(border_color2, 8, 10)) - - return animate_rune_full(input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, 0, 0, 0, alpha, 0, 0, 0, alpha2, 0, 0, 0, 0, 0, 0, 0, 0, frames) - - -/proc/inanimate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000") - var/icon/base = create_border_image(input, "#00ff0000", "#ff000000") - - base.MapColors(rune_color, border_color, "#00000000", "#000000ff", "#00000000") - - return base - -var/list/rune_animation = list( - list(0.000, 5), - list(0.020, 1), - list(0.050, 1), - list(0.090, 1), - list(0.140, 1), - list(0.200, 1), - list(0.270, 1), - list(0.340, 1), - list(0.420, 1), - list(0.500, 1), - list(0.590, 1), - list(0.675, 1), - list(0.750, 1), - list(0.900, 1), - list(1.000, 6), - list(0.875, 1), - list(0.750, 1), - list(0.625, 1), - list(0.500, 1), - list(0.375, 1), - list(0.250, 1), - list(0.125, 1), - ) - -/var/list/rune_cache = list() - -/proc/get_rune(rune_bits, animated = 0) - var/lookup = "[rune_bits]-[animated]" - - if(lookup in rune_cache) - return rune_cache[lookup] - - var/icon/base = icon('icons/effects/uristrunes.dmi', "") - - for(var/i = 0, i < 10, i++) - if(rune_bits & (1 << i)) - base.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY) - - var/icon/result - - if(animated == 1) - result = animate_rune(base) - - else - result = inanimate_rune(base) - - rune_cache[lookup] = result - return result - - - - - -// Testing procs and Fun procs - - - - -/mob/verb/create_rune() - var/obj/o = new(locate(x, y, z)) - o.icon = get_rune(rand(1, 1023), 1) - -/mob/verb/runes_15x15() - for(var/turf/t in range(7)) - var/obj/o = new /obj(t) - o.icon = get_rune(rand(1, 1023), 1) - - -/* -/mob/verb/create_rune_custom(rune as num, color1 as color, border1 as color, color2 as color, border2 as color, alpha1 as num, alpha2 as num) - var/icon/I = icon('icons/effects/uristrunes.dmi', "blank") - - for(var/i = 0, i < 10, i++) - if(rune & (1 << i)) - I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY) - - var/obj/o = new(locate(x, y, z)) - o.icon = animate_rune(I, color1, border1, color2, border2, alpha1, alpha2) - -/mob/verb/spam() - for(var/turf/t in range(4)) - var/icon/I = icon('icons/effects/uristrunes.dmi', "blank") - - var/rune = rand(1, 1023) - for(var/i = 0, i < 10, i++) - if(rune & (1 << i)) - I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY) - - var/obj/o = new(t) - o.icon = animate_rune_full(I, rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255), - rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255), - rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255), - rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255), - 0, 0, 0, rand(0, 255), - 0, 0, 0, rand(0, 255), - 0, 0, 0, 0, - 0, 0, 0, 0, - list( - list(0.000, 5), - list(0.020, 1), - list(0.050, 1), - list(0.090, 1), - list(0.140, 1), - list(0.200, 1), - list(0.270, 1), - list(0.340, 1), - list(0.420, 1), - list(0.500, 1), - list(0.590, 1), - list(0.675, 1), - list(0.750, 1), - list(0.900, 1), - list(1.000, 6), - list(0.875, 1), - list(0.750, 1), - list(0.625, 1), - list(0.500, 1), - list(0.375, 1), - list(0.250, 1), - list(0.125, 1), - )) -*/ \ No newline at end of file diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index e355194ddfc..e81ade4287a 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -571,7 +571,7 @@ playsound(src,'sound/weapons/resonator_blast.ogg',50,1) if(creator) for(var/mob/living/L in src.loc) - add_logs(creator, L, "used a resonator field on", object="resonator") + add_logs(L, creator, "used a resonator field on", object="resonator") L << "The [src.name] ruptured with you in it!" L.adjustBruteLoss(resonance_damage) else @@ -656,7 +656,7 @@ return ..() -/mob/living/simple_animal/hostile/mining_drone/death() +/mob/living/simple_animal/hostile/mining_drone/Die() ..() visible_message("[src] is destroyed!") new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) @@ -707,11 +707,11 @@ /mob/living/simple_animal/hostile/mining_drone/proc/CollectOre() var/obj/item/weapon/ore/O for(O in src.loc) - O.loc = src + O.forceMove(src) for(var/dir in alldirs) var/turf/T = get_step(src,dir) for(O in T) - O.loc = src + O.forceMove(src) return /mob/living/simple_animal/hostile/mining_drone/proc/DropOre() @@ -719,7 +719,7 @@ return for(var/obj/item/weapon/ore/O in contents) contents -= O - O.loc = src.loc + O.forceMove(loc) return /mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss() diff --git a/code/modules/mob/living/carbon/alien/alien_defenses.dm b/code/modules/mob/living/carbon/alien/alien_defenses.dm index 8d0c36bc05d..ed98e221993 100644 --- a/code/modules/mob/living/carbon/alien/alien_defenses.dm +++ b/code/modules/mob/living/carbon/alien/alien_defenses.dm @@ -35,7 +35,7 @@ In all, this is a lot like the monkey code. /N visible_message("[M.name] bites [src]!", \ "[M.name] bites [src]!") adjustBruteLoss(damage) - add_logs(M, src, "attacked", admin=0) + add_logs(src, M, "attacked", admin=0) updatehealth() else M << "[name] is too injured for that." @@ -67,4 +67,4 @@ In all, this is a lot like the monkey code. /N if(..()) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) - updatehealth() + updatehealth() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm index 40303b03543..693763e4960 100644 --- a/code/modules/mob/living/carbon/alien/death.dm +++ b/code/modules/mob/living/carbon/alien/death.dm @@ -53,7 +53,7 @@ if(client) blind.layer = 0 update_icons() - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index a80a0d5892c..69d1eb600dc 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -1,4 +1,7 @@ /mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) + if(stat) + return + var/param = null if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 67edcfd04ca..574b617ca58 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -9,8 +9,8 @@ update_canmove() if(client) blind.layer = 0 - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) living_mob_list -= src return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index 12ad431f3c3..134350e2517 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -1,5 +1,7 @@ /mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) - + if(stat) + return + var/param = null if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 17bf26de838..efcfac98624 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -11,8 +11,8 @@ see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) //mind. ? + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) //mind. ? return ..(gibbed) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index 0441eb00ac4..054a9b6e71c 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -1,4 +1,7 @@ /mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null) + if(stat) + return + if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes return diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index ff2b98d430f..bc0226f4597 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -110,7 +110,7 @@ return 1 /mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue) - if(red == r_skin && green == g_skin && blue == b_skin || !(species.flags & HAS_SKIN_COLOR)) + if(red == r_skin && green == g_skin && blue == b_skin || !(species.bodyflags & HAS_SKIN_COLOR)) return r_skin = red @@ -122,7 +122,7 @@ return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) - if(s_tone == tone || !(species.flags & HAS_SKIN_TONE)) + if(s_tone == tone || !(species.bodyflags & HAS_SKIN_TONE)) return s_tone = tone @@ -182,4 +182,3 @@ valid_facial_hairstyles += facialhairstyle return valid_facial_hairstyles - \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index a9cf1ea1094..4307c6cbd0b 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -133,8 +133,8 @@ update_canmove() if(client) blind.layer = 0 - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) if(ticker && ticker.mode) // log_to_dd("k") sql_report_death(src) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 95e60ade252..338727330f5 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,4 +1,7 @@ /mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null) + if(stat) + return + var/param = null if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) @@ -334,8 +337,12 @@ m_type = 2 if ("deathgasp") - message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." - m_type = 1 + if (species.name == "Machine") + message = "[src] gives one shrill beep before falling limp, screen quickly flashing blue before shutting off entirely." + m_type = 1 + else + message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." + m_type = 1 if ("giggle") if(miming) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0e943d8c257..1b1964a000f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -10,6 +10,11 @@ var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. /mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna=0) + + if(!dna) + dna = new /datum/dna(null) + // Species name is handled by set_species() + if(!species) if(new_species) set_species(new_species,1) @@ -36,9 +41,6 @@ ..() - if(dna) - dna.real_name = real_name - prev_gender = gender // Debug for plural genders make_blood() @@ -46,8 +48,10 @@ faction |= "\ref[M]" // Set up DNA. - if(!delay_ready_dna) + if(!delay_ready_dna && dna) dna.ready_dna(src) + dna.real_name = real_name + sync_organ_dna() //this shouldn't be necessaaaarrrryyyyyyyy UpdateAppearance() /mob/living/carbon/human/Destroy() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 4f404d1f314..c0587ddee86 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -22,15 +22,6 @@ update_revive() return -/mob/living/carbon/human/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair) - stat = CONSCIOUS - dead_mob_list -= src - living_mob_list |= src - mob_list |= src - ear_deaf = 0 - tod = 0 - timeofdeath = 0 - /mob/living/carbon/human/adjustBrainLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index eead644cc58..ef88db4a6dc 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -84,4 +84,4 @@ var/fire_dmi = 'icons/mob/OnFire.dmi' var/fire_sprite = "Standing" - var/datum/body_accessory/body_accessory = null + var/datum/body_accessory/body_accessory = null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f61318e09c6..b54c7f5ee36 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -24,20 +24,10 @@ if(wear_suit) tally += wear_suit.slowdown - if(!buckled || (buckled && !istype(buckled, /obj/structure/stool/bed/chair/wheelchair))) + if(!buckled) if(shoes) tally += shoes.slowdown - if(buckled && istype(buckled, /obj/structure/stool/bed/chair/wheelchair)) - for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm")) - var/obj/item/organ/external/E = get_organ(organ_name) - if(!E || (E.status & ORGAN_DESTROYED)) - tally += 4 - else if(E.status & ORGAN_SPLINTED) - tally += 0.5 - else if(E.status & ORGAN_BROKEN) - tally += 1.5 - if(shock_stage >= 10) tally += 3 if(back) diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 8889e5370da..7654b0d2e3b 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -144,4 +144,9 @@ //New are added for reagents to random organs. for(var/datum/reagent/A in reagents.reagent_list) var/obj/item/organ/O = pick(organs) - O.trace_chemicals[A.name] = 100 \ No newline at end of file + O.trace_chemicals[A.name] = 100 + +/mob/living/carbon/human/proc/sync_organ_dna() + var/list/all_bits = internal_organs|organs + for(var/obj/item/organ/O in all_bits) + O.set_dna(dna) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 875a3a85260..8967e1519d6 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -768,7 +768,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc light_amount = T.get_lumcount()*10 if(light_amount > species.light_dam && !incorporeal_move) //if there's enough light, start dying if(species.light_effect_amp) - adjustFireLoss(5) //This gets doubled by Shadowling's innate fire weakness, so it ends up being 10. + adjustFireLoss(4.7) //This gets multiplied by 1.5 due to Shadowling's innate fire weakness, so it ends up being about 7. else adjustFireLoss(1) adjustBruteLoss(1) @@ -968,7 +968,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc var/obj/item/organ/vision if(species.vision_organ) vision = internal_organs_by_name[species.vision_organ] - + if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. eye_blind = 0 blinded = 0 @@ -977,7 +977,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc eye_blind = 1 blinded = 1 eye_blurry = 1 - else + else //blindness if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own blinded = 1 @@ -987,7 +987,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster eye_blurry = max(eye_blurry-3, 0) blinded = 1 - + //blurry sight if(vision.is_bruised()) // Vision organs impaired? Permablurry. eye_blurry = 1 @@ -1220,13 +1220,17 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc if(ANTAGHUD) process_antag_hud(src) - - - else if(!seer) see_in_dark = species.darksight see_invisible = SEE_INVISIBLE_LIVING - + + if(vision_type) + see_in_dark = max(see_in_dark, vision_type.see_in_dark, species.darksight) + see_invisible = vision_type.see_invisible + if(vision_type.light_sensitive) + weakeyes = 1 + sight |= vision_type.sight_flags + if(see_override) //Override all see_invisible = see_override diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index 14372e6c976..28862cf6cfc 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -5,5 +5,6 @@ src << "You can ventcrawl! Use alt+click on vents to quickly travel about the station." update_pipe_vision() update_hud() - ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. + if(ticker && ticker.mode) + ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. return diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index b525919b5bc..f3d61c038c7 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -59,7 +59,7 @@ /datum/species/unathi/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) - + /datum/species/unathi/equip(var/mob/living/carbon/human/H) if(H.mind.assigned_role != "Clown") H.unEquip(H.shoes) @@ -105,7 +105,7 @@ /datum/species/tajaran/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) - + /datum/species/tajaran/equip(var/mob/living/carbon/human/H) if(H.mind.assigned_role != "Clown") H.unEquip(H.shoes) @@ -219,7 +219,7 @@ i++ newname += pick(vox_name_syllables) return capitalize(newname) - + /datum/species/vox/equip(var/mob/living/carbon/human/H) if(H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime") H.unEquip(H.wear_mask) @@ -235,7 +235,7 @@ H.internal = H.l_hand if (H.internals) H.internals.icon_state = "internal1" - + /* /datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) H.verbs += /mob/living/carbon/human/proc/leap @@ -469,20 +469,20 @@ /datum/species/machine name = "Machine" name_plural = "Machines" - + blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \ robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \ to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \ generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \ - inhuman in outlook and perspective." - + inhuman in outlook and perspective." + icobase = 'icons/mob/human_races/r_machine.dmi' deform = 'icons/mob/human_races/r_machine.dmi' path = /mob/living/carbon/human/machine default_language = "Galactic Common" language = "Trinary" unarmed_type = /datum/unarmed_attack/punch - + eyes = "blank_eyes" brute_mod = 2.5 // 100% * 2.5 * 0.6 (robolimbs) ~= 150% burn_mod = 2.5 // So they take 50% extra damage from brute/burn overall. @@ -500,20 +500,21 @@ flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_DNA_RAD clothing_flags = HAS_SOCKS + bodyflags = HAS_SKIN_COLOR dietflags = 0 //IPCs can't eat, so no diet blood_color = "#1F181F" flesh_color = "#AAAAAA" virus_immune = 1 can_revive_by_healing = 1 reagent_tag = PROCESS_SYN - + has_organ = list( "brain" = /obj/item/organ/mmi_holder/posibrain, "cell" = /obj/item/organ/cell, "optics" = /obj/item/organ/optical_sensor ) - vision_organ = "optics" + vision_organ = "optics" has_limbs = list( "chest" = list("path" = /obj/item/organ/external/chest/ipc), "groin" = list("path" = /obj/item/organ/external/groin/ipc), @@ -532,7 +533,7 @@ H.h_style = "" spawn(100) if(H) H.update_hair() - + /datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H) ..() H.verbs += /mob/living/carbon/human/proc/change_monitor \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 4c99dd12895..86c2d79eb7b 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -238,15 +238,13 @@ var/global/list/damage_icon_parts = list() var/hulk = (HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) - var/g = (gender == FEMALE ? "f" : "m") - //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. if(stand_icon) qdel(stand_icon) stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]" + var/icon_key = "" var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"] if(eyes) @@ -265,6 +263,13 @@ var/global/list/damage_icon_parts = list() else icon_key += "1" + if(part) + icon_key += "[part.species.race_key]" + icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" + icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" + if(part.s_col) + icon_key += "[rgb(part.s_col[1], part.s_col[2], part.s_col[3])]" + icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" var/icon/base_icon @@ -868,8 +873,8 @@ var/global/list/damage_icon_parts = list() var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]") I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension) - overlays_standing[R_HAND_LAYER] = I - + overlays_standing[R_HAND_LAYER] = I + if (handcuffed) drop_r_hand() else overlays_standing[R_HAND_LAYER] = null diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm index 2cbc139f5a1..3c95bea1a43 100644 --- a/code/modules/mob/living/carbon/metroid/emote.dm +++ b/code/modules/mob/living/carbon/metroid/emote.dm @@ -1,5 +1,6 @@ /mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null) - + if(stat) + return if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6ead72a36f5..808f8b3e772 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -317,9 +317,16 @@ C.reagents.addiction_list.Cut() hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD + +/mob/living/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair) + stat = CONSCIOUS + dead_mob_list -= src + living_mob_list |= src + mob_list |= src + ear_deaf = 0 + timeofdeath = 0 /mob/living/proc/rejuvenate() - // shut down various types of badness setToxLoss(0) setOxyLoss(0) @@ -367,10 +374,9 @@ human_mob.decaylevel = 0 restore_all_organs() - if(stat == 2) + if(stat == DEAD) dead_mob_list -= src living_mob_list += src - tod = null timeofdeath = 0 stat = CONSCIOUS diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index cf6204e710c..08a99c0dba2 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -34,8 +34,6 @@ var/atom/movable/cameraFollow = null - var/tod = null // Time of death - var/on_fire = 0 //The "Are we on fire?" var var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20 diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index dfa05ddc5d0..fe96da3c35e 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -53,7 +53,7 @@ if (istype(loc, /obj/item/device/aicard)) loc.icon_state = "aicard-404" - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) return ..(gibbed) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm index f7ead12e4cc..8c28d407ede 100644 --- a/code/modules/mob/living/silicon/emote.dm +++ b/code/modules/mob/living/silicon/emote.dm @@ -1,4 +1,7 @@ /mob/living/silicon/emote(var/act, var/m_type=1, var/message = null) + if(stat) + return + var/param = null if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 8fccd74ff39..9cb442e3d37 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -12,7 +12,8 @@ /mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg) laws_sanity_check() laws.set_zeroth_law(law, law_borg) - log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]") + if(!isnull(usr) && law) + log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]") /mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg) ..() @@ -22,39 +23,43 @@ /mob/living/silicon/proc/add_ion_law(var/law) laws_sanity_check() laws.add_ion_law(law) - log_and_message_admins("has given [src] the ion law: [law]") + if(!isnull(usr) && law) + log_and_message_admins("has given [src] the ion law: [law]") /mob/living/silicon/proc/add_inherent_law(var/law) laws_sanity_check() laws.add_inherent_law(law) - log_and_message_admins("has given [src] the inherent law: [law]") + if(!isnull(usr) && law) + log_and_message_admins("has given [src] the inherent law: [law]") /mob/living/silicon/proc/add_supplied_law(var/number, var/law) laws_sanity_check() laws.add_supplied_law(number, law) - log_and_message_admins("has given [src] the supplied law: [law]") + if(!isnull(usr) && law) + log_and_message_admins("has given [src] the supplied law: [law]") /mob/living/silicon/proc/delete_law(var/datum/ai_law/law) laws_sanity_check() laws.delete_law(law) - log_and_message_admins("has deleted a law belonging to [src]: [law.law]") + if(!isnull(usr) && law) + log_and_message_admins("has deleted a law belonging to [src]: [law.law]") /mob/living/silicon/proc/clear_inherent_laws(var/silent = 0) laws_sanity_check() laws.clear_inherent_laws() - if(!silent) + if(!silent && !isnull(usr)) log_and_message_admins("cleared the inherent laws of [src]") /mob/living/silicon/proc/clear_ion_laws(var/silent = 0) laws_sanity_check() laws.clear_ion_laws() - if(!silent) + if(!silent && !isnull(usr)) log_and_message_admins("cleared the ion laws of [src]") /mob/living/silicon/proc/clear_supplied_laws(var/silent = 0) laws_sanity_check() laws.clear_supplied_laws() - if(!silent) + if(!silent && !isnull(usr)) log_and_message_admins("cleared the supplied laws of [src]") /mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws) diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm index a8eeac8cbb7..2fce92f2883 100644 --- a/code/modules/mob/living/silicon/pai/emote.dm +++ b/code/modules/mob/living/silicon/pai/emote.dm @@ -1,4 +1,7 @@ /mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null) + if(stat) + return + switch(act) if ("help") src << "ping, beep, buzz." diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index d0469bc42dc..7eb1e62090c 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -1,14 +1,15 @@ // TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system -/datum/robot_component/var/name -/datum/robot_component/var/installed = 0 -/datum/robot_component/var/powered = 0 -/datum/robot_component/var/toggled = 1 -/datum/robot_component/var/brute_damage = 0 -/datum/robot_component/var/electronics_damage = 0 -/datum/robot_component/var/energy_consumption = 0 -/datum/robot_component/var/max_damage = 30 -/datum/robot_component/var/mob/living/silicon/robot/owner +/datum/robot_component + var/name = "Component" + var/installed = 0 + var/powered = 1 + var/toggled = 1 + var/brute_damage = 0 + var/electronics_damage = 0 + var/energy_consumption = 0 + var/max_damage = 30 + var/mob/living/silicon/robot/owner // The actual device object that has to be installed for this. /datum/robot_component/var/external_type = null @@ -206,8 +207,8 @@ user << "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health - M.halloss]% functional"]" user << "\t Key: Electronics/Brute" user << "\t Damage Specifics: [BU] - [BR]" - if(M.tod && M.stat == DEAD) - user << "Time of Disable: [M.tod]" + if(M.timeofdeath && M.stat == DEAD) + user << "Time of Disable: [M.timeofdeath]" var/mob/living/silicon/robot/H = M var/list/damaged = H.get_damaged_components(1,1,1) user << "Localized Damage:" diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index cf9427242d8..cafb53d8621 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -62,8 +62,8 @@ see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO update_icons() - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) + timeofdeath = worldtime2text() + if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) sql_report_cyborg_death(src) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 9c01f9ee5ec..45a086f0fe7 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -1,4 +1,7 @@ /mob/living/silicon/robot/emote(var/act, var/m_type=1, var/message = null) + if(stat) + return + var/param = null if (findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 3a8812a011b..f355b00ff2f 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1146,7 +1146,7 @@ var/list/robot_verbs_default = list( S.dirt = 0 for(var/A in tile) if(istype(A, /obj/effect)) - if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay)) + if(is_cleanable(A)) qdel(A) else if(istype(A, /obj/item)) var/obj/item/cleaned_item = A diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm index 9a1c713ab72..fa3dcfd2cfa 100644 --- a/code/modules/mob/living/silicon/subsystems.dm +++ b/code/modules/mob/living/silicon/subsystems.dm @@ -81,7 +81,7 @@ set name = "Law Manager" set category = "Subsystems" - law_manager.ui_interact(usr, state = self_state) + law_manager.ui_interact(usr, state = conscious_state) /******************** * Power Monitor * diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 221b8962ca8..a644ec9d7d3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -639,11 +639,6 @@ var/list/slot_equipment_priority = list( \ flavor_text = msg -/mob/proc/warn_flavor_changed() - if(flavor_text && flavor_text != "") // don't spam people that don't use it! - src << "

OOC Warning:

" - src << "Your flavor text is likely out of date! Change" - /mob/proc/print_flavor_text(var/shrink = 1) if (flavor_text && flavor_text != "") var/msg = replacetext(flavor_text, "\n", " ") diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 312f9fb3ff1..4bc62d88f81 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -201,6 +201,7 @@ var/area/lastarea = null var/digitalcamo = 0 // Can they be tracked by the AI? + var/weakeyes //Are they vulnerable to flashes? var/list/radar_blips = list() // list of screen objects, radar blips var/radar_open = 0 // nonzero is radar is open @@ -232,4 +233,6 @@ var/last_movement = -100 // Last world.time the mob actually moved of its own accord. - var/resize = 1 //Badminnery resize \ No newline at end of file + var/resize = 1 //Badminnery resize + + var/datum/vision_override/vision_type = null //Vision override datum. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 3830c9b2705..6f3bea0cef8 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -509,7 +509,7 @@ proc/has_admin_rights() - return client.holder.rights & R_ADMIN + return check_rights(R_ADMIN, 0, src) proc/is_species_whitelisted(datum/species/S) if(!S) return 1 diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm new file mode 100644 index 00000000000..143bc24956f --- /dev/null +++ b/code/modules/nano/interaction/conscious.dm @@ -0,0 +1,7 @@ +/* + This state only checks if user is conscious. +*/ +/var/global/datum/topic_state/conscious_state/conscious_state = new() + +/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user) + return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 1a5808ec7d3..a93d2a278a8 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -21,7 +21,8 @@ var/list/organ_cache = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, // links chemical IDs to number of ticks for which they'll stay in the blood germ_level = 0 - + var/datum/dna/dna + var/datum/species/species /obj/item/organ/Destroy() if(!owner) @@ -59,6 +60,12 @@ var/list/organ_cache = list() max_damage = min_broken_damage * 2 if(istype(holder)) src.owner = holder + species = all_species["Human"] + if(holder.dna) + dna = holder.dna.Clone() + species = all_species[dna.species] + else + log_to_dd("[src] at [loc] spawned without a proper DNA.") var/mob/living/carbon/human/H = holder if(istype(H)) if(internal) @@ -67,13 +74,19 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src - if(H.dna) + if(dna) if(!blood_DNA) blood_DNA = list() - blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + blood_DNA[dna.unique_enzymes] = dna.b_type if(internal) holder.internal_organs |= src +/obj/item/organ/proc/set_dna(var/datum/dna/new_dna) + if(new_dna) + dna = new_dna.Clone() + blood_DNA.Cut() + blood_DNA[dna.unique_enzymes] = dna.b_type + /obj/item/organ/proc/die() if(status & ORGAN_ROBOT) return diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 26ca1f5079a..e3e95e78df3 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -12,13 +12,25 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) s_tone = null s_col = null - if(status & ORGAN_ROBOT) + if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color + return + if(species && human.species && species.name != human.species.name) return if(!isnull(human.s_tone) && (human.species.bodyflags & HAS_SKIN_TONE)) s_tone = human.s_tone if(human.species.bodyflags & HAS_SKIN_COLOR) s_col = list(human.r_skin, human.g_skin, human.b_skin) +/obj/item/organ/external/proc/sync_colour_to_dna() + s_tone = null + s_col = null + if(status & ORGAN_ROBOT) + return + if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE)) + s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) + if(species.flags & HAS_SKIN_COLOR) + s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B)) + /obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human) ..() var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] @@ -34,11 +46,11 @@ var/global/list/limb_icon_cache = list() overlays.Cut() if(!owner) return - - if(owner.species.has_organ["eyes"]) + + if(species.has_organ["eyes"]) var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] - if(owner.species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', owner.species.eyes) + if(species.eyes) + var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) if(eyes) eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) else @@ -46,14 +58,14 @@ var/global/list/limb_icon_cache = list() mob_icon.Blend(eyes_icon, ICON_OVERLAY) overlays |= eyes_icon - if(owner.lip_style && (owner.species && (owner.species.flags & HAS_LIPS))) + if(owner.lip_style && (species && (species.flags & HAS_LIPS))) var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (owner.species.name in facial_hair_style.species_allowed)) + if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) @@ -61,7 +73,7 @@ var/global/list/limb_icon_cache = list() if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && (owner.species.name in hair_style.species_allowed)) + if(hair_style && (species.name in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD) @@ -74,26 +86,29 @@ var/global/list/limb_icon_cache = list() var/gender if(force_icon) mob_icon = new /icon(force_icon, "[icon_name]") + if(species && species.name == "Machine") //snowflake for IPC's, sorry. + if(s_col && s_col.len >= 3) + mob_icon.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) else - if(!owner) + if(!dna) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]") else if(gendered_icon) - if(owner.gender == FEMALE) + if(dna.GetUIState(DNA_UI_GENDER)) gender = "f" else gender = "m" if(skeletal) mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]") - else if (status & ORGAN_ROBOT) + else if(status & ORGAN_ROBOT) mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]") else if (status & ORGAN_MUTATED) - mob_icon = new /icon(owner.species.deform, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]") else - mob_icon = new /icon(owner.species.icobase, "[icon_name][gender ? "_[gender]" : ""]") + mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]") if(status & ORGAN_DEAD) mob_icon.ColorTone(rgb(10,50,0)) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 9e27818eb8b..c4170888d3d 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -60,6 +60,9 @@ consume(user) return 1 +/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man! + return 0 + /obj/singularity/blob_act(severity) return @@ -268,8 +271,6 @@ step(src, movement_dir) -/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man! - return 0 /obj/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) if(!direction) @@ -360,18 +361,13 @@ /obj/singularity/proc/toxmob() var/toxrange = 10 - var/toxdamage = 4 var/radiation = 15 var/radiationmin = 3 - if (src.energy>200) - toxdamage = round(((src.energy-150)/50)*4,1) - radiation = round(((src.energy-150)/50)*5,1) - radiationmin = round((radiation/5),1)// + if (energy>200) + radiation += round((energy-150)/10,1) + radiationmin = round((radiation/5),1) for(var/mob/living/M in view(toxrange, src.loc)) M.apply_effect(rand(radiationmin,radiation), IRRADIATE) - toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad"))) - M.apply_effect(toxdamage, TOX) - return /obj/singularity/proc/combust_mobs() @@ -382,6 +378,7 @@ C.IgniteMob() return + /obj/singularity/proc/mezzer() for(var/mob/living/carbon/M in oviewers(8, src)) if(istype(M, /mob/living/carbon/brain)) //Ignore brains diff --git a/code/modules/procedural mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm similarity index 100% rename from code/modules/procedural mapping/mapGenerator.dm rename to code/modules/procedural_mapping/mapGenerator.dm diff --git a/code/modules/procedural mapping/mapGeneratorModule.dm b/code/modules/procedural_mapping/mapGeneratorModule.dm similarity index 100% rename from code/modules/procedural mapping/mapGeneratorModule.dm rename to code/modules/procedural_mapping/mapGeneratorModule.dm diff --git a/code/modules/procedural mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm similarity index 100% rename from code/modules/procedural mapping/mapGeneratorModules/helpers.dm rename to code/modules/procedural_mapping/mapGeneratorModules/helpers.dm diff --git a/code/modules/procedural mapping/mapGeneratorModules/nature.dm b/code/modules/procedural_mapping/mapGeneratorModules/nature.dm similarity index 100% rename from code/modules/procedural mapping/mapGeneratorModules/nature.dm rename to code/modules/procedural_mapping/mapGeneratorModules/nature.dm diff --git a/code/modules/procedural mapping/mapGeneratorReadme.dm b/code/modules/procedural_mapping/mapGeneratorReadme.dm similarity index 100% rename from code/modules/procedural mapping/mapGeneratorReadme.dm rename to code/modules/procedural_mapping/mapGeneratorReadme.dm diff --git a/code/modules/procedural mapping/mapGenerators/asteroid.dm b/code/modules/procedural_mapping/mapGenerators/asteroid.dm similarity index 100% rename from code/modules/procedural mapping/mapGenerators/asteroid.dm rename to code/modules/procedural_mapping/mapGenerators/asteroid.dm diff --git a/code/modules/procedural mapping/mapGenerators/nature.dm b/code/modules/procedural_mapping/mapGenerators/nature.dm similarity index 100% rename from code/modules/procedural mapping/mapGenerators/nature.dm rename to code/modules/procedural_mapping/mapGenerators/nature.dm diff --git a/code/modules/procedural mapping/mapGenerators/syndicate.dm b/code/modules/procedural_mapping/mapGenerators/syndicate.dm similarity index 100% rename from code/modules/procedural mapping/mapGenerators/syndicate.dm rename to code/modules/procedural_mapping/mapGenerators/syndicate.dm diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm index 1f6f374aef0..8d33a9e2508 100644 --- a/code/modules/projectiles/guns/energy/temperature.dm +++ b/code/modules/projectiles/guns/energy/temperature.dm @@ -29,7 +29,7 @@ /obj/item/weapon/gun/energy/temperature/Destroy() processing_objects.Remove(src) - ..() + return ..() /obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 46bb04ee636..e0127fe9862 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -218,15 +218,17 @@ if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food/drinks)) src.beaker = B - user.drop_item() - B.loc = src - user << "You set [B] on the machine." - nanomanager.update_uis(src) // update all UIs attached to src - if(!icon_beaker) - icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position. - icon_beaker.pixel_x = rand(-10,5) - overlays += icon_beaker - return + if(user.drop_item()) + B.forceMove(src) + user << "You set [B] on the machine." + nanomanager.update_uis(src) // update all UIs attached to src + if(!icon_beaker) + icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position. + icon_beaker.pixel_x = rand(-10,5) + overlays += icon_beaker + return + else + user << "\The [B] is stuck to you!" /obj/machinery/chem_dispenser/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob, params) ..() @@ -591,6 +593,8 @@ if(!condi) var/count = 1 if (href_list["createpatch_multiple"]) count = isgoodnumber(input("Select the number of patches to make.", 10, patchamount) as num) + if(!count || count <= 0) + return if (count > 20) count = 20 //Pevent people from creating huge stacks of patches easily. Maybe move the number to defines? var/amount_per_patch = reagents.total_volume/count if (amount_per_patch > 40) amount_per_patch = 40 diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm index a54072e9bbb..e79667be06e 100644 --- a/code/modules/reagents/newchem/medicine.dm +++ b/code/modules/reagents/newchem/medicine.dm @@ -633,6 +633,7 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T if(method == TOUCH) if(M.stat == DEAD) M.health = M.maxHealth + M.update_revive() M.visible_message("[M] seems to rise from the dead!") if(istype(M, /mob/living/carbon)) if(method == INGEST) @@ -648,13 +649,12 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T M.visible_message("[M] doesn't appear to respond, perhaps try again later?") if(!M.suiciding && !ghost && !(NOCLONE in M.mutations)) M.visible_message("[M] seems to rise from the dead!") - M.stat = 1 M.setOxyLoss(0) M.adjustBruteLoss(rand(0,15)) M.adjustToxLoss(rand(0,15)) M.adjustFireLoss(rand(0,15)) - dead_mob_list -= M - living_mob_list |= list(M) + M.update_revive() + M.stat = UNCONSCIOUS add_logs(M, M, "revived", object="strange reagent") ..() return diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index aeda3fcbec3..7f9c3ee3c98 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -63,7 +63,7 @@ /obj/item/weapon/reagent_containers/proc/reagentlist(var/obj/item/weapon/reagent_containers/snack) //Attack logs for regents in pills var/data - if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries + if(snack && snack.reagents && snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. return data diff --git a/code/modules/research/designs/janitorial_designs.dm b/code/modules/research/designs/janitorial_designs.dm index 76a469d04e6..8c575425ebe 100644 --- a/code/modules/research/designs/janitorial_designs.dm +++ b/code/modules/research/designs/janitorial_designs.dm @@ -11,6 +11,26 @@ build_path = /obj/item/weapon/mop/advanced category = list("Janitorial") +/datum/design/blutrash + name = "Trashbag of Holding" + desc = "An advanced trashabg with bluespace properties; capable of holding a plethora of garbage." + id = "blutrash" + req_tech = list("materials" = 5, "bluespace" = 3) + build_type = PROTOLATHE + materials = list(MAT_GOLD = 1500, MAT_URANIUM = 250, MAT_PLASMA = 1500) + build_path = /obj/item/weapon/storage/bag/trash/bluespace + category = list("Janitorial") + +/datum/design/buffer + name = "Floor Buffer Upgrade" + desc = "A floor buffer that can be attached to vehicular janicarts." + id = "buffer" + req_tech = list("materials" = 5, "engineering" = 3) + build_type = PROTOLATHE + materials = list(MAT_METAL = 3000, MAT_GLASS = 200) + build_path = /obj/item/janiupgrade + category = list("Janitorial") + /datum/design/holosign name = "Holographic Sign Projector" desc = "A holograpic projector used to project various warning signs." diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 577397b70fc..9072217e4f7 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -184,7 +184,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(..()) return 1 - if(!allowed(usr)) + if(!allowed(usr) && !isobserver(usr)) return 1 add_fingerprint(usr) @@ -324,7 +324,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, use_power(250) updateUsrDialog() - else if(href_list["lock"]) //Lock the console from use by anyone without tox access. + else if(href_list["lock"]) //Lock the console from use by anyone without access. if(src.allowed(usr)) screen = text2num(href_list["lock"]) else @@ -606,7 +606,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, /obj/machinery/computer/rdconsole/attack_hand(mob/user as mob) if(..()) return 1 - if(!allowed(user)) + if(!allowed(user) && !isobserver(user)) user << "Access denied." return 1 interact(user) @@ -1115,26 +1115,26 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "" return dat + +/obj/machinery/computer/rdconsole/core + name = "Core R&D Console" + desc = "A console used to interface with R&D tools." + id = 1 /obj/machinery/computer/rdconsole/robotics name = "Robotics R&D Console" desc = "A console used to interface with R&D tools." id = 2 req_access = list(access_robotics) + +/obj/machinery/computer/rdconsole/experiment + name = "E.X.P.E.R.I-MENTOR R&D Console" + desc = "A console used to interface with R&D tools." + id = 3 /obj/machinery/computer/rdconsole/mechanics name = "Mechanics R&D Console" desc = "A console used to interface with R&D tools." id = 4 req_access = list(access_mechanic) - -/obj/machinery/computer/rdconsole/core - name = "Core R&D Console" - desc = "A console used to interface with R&D tools." - id = 1 - -/obj/machinery/computer/rdconsole/experiment - name = "E.X.P.E.R.I-MENTOR R&D Console" - desc = "A console used to interface with R&D tools." - id = 3 \ No newline at end of file diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 67cf7cd9217..a520fe6ec92 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -335,16 +335,15 @@ emagged = 1 user << "\blue You you disable the security protocols" src.updateUsrDialog() - -/obj/machinery/r_n_d/server/robotics - name = "Robotics R&D Server" - id_with_upload_string = "1;2" - id_with_download_string = "1;2" - server_id = 2 - - + /obj/machinery/r_n_d/server/core name = "Core R&D Server" - id_with_upload_string = "1" - id_with_download_string = "1" + id_with_upload_string = "1;3" + id_with_download_string = "1;3" server_id = 1 + +/obj/machinery/r_n_d/server/robotics + name = "Robotics and Mechanic R&D Server" + id_with_upload_string = "1;2;4" + id_with_download_string = "1;2;4" + server_id = 2 diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm similarity index 96% rename from code/modules/security levels/keycard authentication.dm rename to code/modules/security_levels/keycard authentication.dm index 7a9fd05da3e..0fbff9cd68a 100644 --- a/code/modules/security levels/keycard authentication.dm +++ b/code/modules/security_levels/keycard authentication.dm @@ -1,186 +1,186 @@ -/obj/machinery/keycard_auth - name = "Keycard Authentication Device" - desc = "This device is used to trigger station functions, which require more than one ID card to authenticate." - icon = 'icons/obj/monitors.dmi' - icon_state = "auth_off" - var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made. - var/event = "" - var/screen = 1 - var/list/ert_chosen = list() - var/confirmed = 0 //This variable is set by the device that confirms the request. - var/confirm_delay = 20 //(2 seconds) - var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device. - var/obj/machinery/keycard_auth/event_source - var/mob/event_triggered_by - var/mob/event_confirmed_by - var/ert_reason = "Reason for ERT" - //1 = select event - //2 = authenticate - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 6 - power_channel = ENVIRON - -/obj/machinery/keycard_auth/attack_ai(mob/user as mob) - user << "The station AI is not to interact with these devices." - return - -/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(stat & (NOPOWER|BROKEN)) - user << "This device is not powered." - return - if(istype(W,/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = W - if(access_keycard_auth in ID.access) - if(active == 1) - //This is not the device that made the initial request. It is the device confirming the request. - if(event_source) - event_source.confirmed = 1 - event_source.event_confirmed_by = usr - else if(screen == 2) - if(event == "Emergency Response Team" && ert_reason == "Reason for ERT") - user << "Supply a reason for calling the ERT first!" - return - event_triggered_by = usr - broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices - -/obj/machinery/keycard_auth/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - icon_state = "auth_off" - else - stat |= NOPOWER - -/obj/machinery/keycard_auth/attack_hand(mob/user as mob) - if(!user.IsAdvancedToolUser()) - return 0 - ui_interact(user) - -/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(user.stat || stat & (NOPOWER|BROKEN)) - user << "This device is not powered." - return - if(busy) - user << "This device is busy." - return - - user.set_machine(src) - - var/data[0] - data["screen"] = screen - data["event"] = event - data["ertreason"] = ert_reason - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320) - ui.set_initial_data(data) - ui.open() - -/obj/machinery/keycard_auth/Topic(href, href_list) - if(..()) - return - if(busy) - usr << "This device is busy." - return - if(usr.stat || stat & (BROKEN|NOPOWER)) - usr << "This device is without power." - return - if(href_list["triggerevent"]) - event = href_list["triggerevent"] - screen = 2 - if(href_list["reset"]) - reset() - if(href_list["ert"]) - ert_reason = input(usr, "Reason for ERT Call:", "", "") - - nanomanager.update_uis(src) - add_fingerprint(usr) - return - -/obj/machinery/keycard_auth/proc/reset() - active = 0 - event = "" - screen = 1 - confirmed = 0 - event_source = null - icon_state = "auth_off" - event_triggered_by = null - event_confirmed_by = null - -/obj/machinery/keycard_auth/proc/broadcast_request() - icon_state = "auth_on" - for(var/obj/machinery/keycard_auth/KA in world) - if(KA == src) continue - KA.reset() - spawn() - KA.receive_request(src) - - sleep(confirm_delay) - if(confirmed) - confirmed = 0 - trigger_event(event) - log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]") - message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1) - reset() - -/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source) - if(stat & (BROKEN|NOPOWER)) - return - event_source = source - busy = 1 - active = 1 - icon_state = "auth_on" - - sleep(confirm_delay) - - event_source = null - icon_state = "auth_off" - active = 0 - busy = 0 - -/obj/machinery/keycard_auth/proc/trigger_event() - switch(event) - if("Red Alert") - set_security_level(SEC_LEVEL_RED) - feedback_inc("alert_keycard_auth_red",1) - if("Grant Emergency Maintenance Access") - make_maint_all_access() - feedback_inc("alert_keycard_auth_maintGrant",1) - if("Revoke Emergency Maintenance Access") - revoke_maint_all_access() - feedback_inc("alert_keycard_auth_maintRevoke",1) - if("Emergency Response Team") - if(is_ert_blocked()) - usr << "\red All Emergency Response Teams are dispatched and can not be called at this time." - return - - usr << "ERT request transmitted." - if(admins.len) - ERT_Announce(ert_reason , event_triggered_by) - ert_reason = "Reason for ERT" - feedback_inc("alert_keycard_auth_ert",1) - else - trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT. - -/obj/machinery/keycard_auth/proc/is_ert_blocked() - return ticker.mode && ticker.mode.ert_disabled - -var/global/maint_all_access = 0 - -/proc/make_maint_all_access() - for(var/area/maintenance/A in world) - for(var/obj/machinery/door/airlock/D in A) - D.emergency = 1 - D.update_icon(0) - minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.") - maint_all_access = 1 - -/proc/revoke_maint_all_access() - for(var/area/maintenance/A in world) - for(var/obj/machinery/door/airlock/D in A) - D.emergency = 0 - D.update_icon(0) - minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.") +/obj/machinery/keycard_auth + name = "Keycard Authentication Device" + desc = "This device is used to trigger station functions, which require more than one ID card to authenticate." + icon = 'icons/obj/monitors.dmi' + icon_state = "auth_off" + var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made. + var/event = "" + var/screen = 1 + var/list/ert_chosen = list() + var/confirmed = 0 //This variable is set by the device that confirms the request. + var/confirm_delay = 20 //(2 seconds) + var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device. + var/obj/machinery/keycard_auth/event_source + var/mob/event_triggered_by + var/mob/event_confirmed_by + var/ert_reason = "Reason for ERT" + //1 = select event + //2 = authenticate + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 6 + power_channel = ENVIRON + +/obj/machinery/keycard_auth/attack_ai(mob/user as mob) + user << "The station AI is not to interact with these devices." + return + +/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params) + if(stat & (NOPOWER|BROKEN)) + user << "This device is not powered." + return + if(istype(W,/obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/ID = W + if(access_keycard_auth in ID.access) + if(active == 1) + //This is not the device that made the initial request. It is the device confirming the request. + if(event_source) + event_source.confirmed = 1 + event_source.event_confirmed_by = usr + else if(screen == 2) + if(event == "Emergency Response Team" && ert_reason == "Reason for ERT") + user << "Supply a reason for calling the ERT first!" + return + event_triggered_by = usr + broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices + +/obj/machinery/keycard_auth/power_change() + if(powered(ENVIRON)) + stat &= ~NOPOWER + icon_state = "auth_off" + else + stat |= NOPOWER + +/obj/machinery/keycard_auth/attack_hand(mob/user as mob) + if(!user.IsAdvancedToolUser()) + return 0 + ui_interact(user) + +/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + if(user.stat || stat & (NOPOWER|BROKEN)) + user << "This device is not powered." + return + if(busy) + user << "This device is busy." + return + + user.set_machine(src) + + var/data[0] + data["screen"] = screen + data["event"] = event + data["ertreason"] = ert_reason + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320) + ui.set_initial_data(data) + ui.open() + +/obj/machinery/keycard_auth/Topic(href, href_list) + if(..()) + return + if(busy) + usr << "This device is busy." + return + if(usr.stat || stat & (BROKEN|NOPOWER)) + usr << "This device is without power." + return + if(href_list["triggerevent"]) + event = href_list["triggerevent"] + screen = 2 + if(href_list["reset"]) + reset() + if(href_list["ert"]) + ert_reason = input(usr, "Reason for ERT Call:", "", "") + + nanomanager.update_uis(src) + add_fingerprint(usr) + return + +/obj/machinery/keycard_auth/proc/reset() + active = 0 + event = "" + screen = 1 + confirmed = 0 + event_source = null + icon_state = "auth_off" + event_triggered_by = null + event_confirmed_by = null + +/obj/machinery/keycard_auth/proc/broadcast_request() + icon_state = "auth_on" + for(var/obj/machinery/keycard_auth/KA in world) + if(KA == src) continue + KA.reset() + spawn() + KA.receive_request(src) + + sleep(confirm_delay) + if(confirmed) + confirmed = 0 + trigger_event(event) + log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]") + message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1) + reset() + +/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source) + if(stat & (BROKEN|NOPOWER)) + return + event_source = source + busy = 1 + active = 1 + icon_state = "auth_on" + + sleep(confirm_delay) + + event_source = null + icon_state = "auth_off" + active = 0 + busy = 0 + +/obj/machinery/keycard_auth/proc/trigger_event() + switch(event) + if("Red Alert") + set_security_level(SEC_LEVEL_RED) + feedback_inc("alert_keycard_auth_red",1) + if("Grant Emergency Maintenance Access") + make_maint_all_access() + feedback_inc("alert_keycard_auth_maintGrant",1) + if("Revoke Emergency Maintenance Access") + revoke_maint_all_access() + feedback_inc("alert_keycard_auth_maintRevoke",1) + if("Emergency Response Team") + if(is_ert_blocked()) + usr << "\red All Emergency Response Teams are dispatched and can not be called at this time." + return + + usr << "ERT request transmitted." + if(admins.len) + ERT_Announce(ert_reason , event_triggered_by) + ert_reason = "Reason for ERT" + feedback_inc("alert_keycard_auth_ert",1) + else + trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT. + +/obj/machinery/keycard_auth/proc/is_ert_blocked() + return ticker.mode && ticker.mode.ert_disabled + +var/global/maint_all_access = 0 + +/proc/make_maint_all_access() + for(var/area/maintenance/A in world) + for(var/obj/machinery/door/airlock/D in A) + D.emergency = 1 + D.update_icon(0) + minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.") + maint_all_access = 1 + +/proc/revoke_maint_all_access() + for(var/area/maintenance/A in world) + for(var/obj/machinery/door/airlock/D in A) + D.emergency = 0 + D.update_icon(0) + minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.") maint_all_access = 0 \ No newline at end of file diff --git a/code/modules/security levels/security levels.dm b/code/modules/security_levels/security levels.dm similarity index 97% rename from code/modules/security levels/security levels.dm rename to code/modules/security_levels/security levels.dm index 5ac35d1188e..051d7b502cf 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security_levels/security levels.dm @@ -1,184 +1,184 @@ -/var/security_level = 0 -//0 = code green -//1 = code blue -//2 = code red -//3 = gamma -//4 = epsilon -//5 = code delta - -//config.alert_desc_blue_downto -/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg')) -/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1) - -/proc/set_security_level(var/level) - switch(level) - if("green") - level = SEC_LEVEL_GREEN - if("blue") - level = SEC_LEVEL_BLUE - if("red") - level = SEC_LEVEL_RED - if("gamma") - level = SEC_LEVEL_GAMMA - if("epsilon") - level = SEC_LEVEL_EPSILON - if("delta") - level = SEC_LEVEL_DELTA - - //Will not be announced if you try to set to the same level as it already is - if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) - switch(level) - if(SEC_LEVEL_GREEN) - security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.") - security_level = SEC_LEVEL_GREEN - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") - - if(SEC_LEVEL_BLUE) - if(security_level < SEC_LEVEL_BLUE) - security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.") - else - security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.") - security_level = SEC_LEVEL_BLUE - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") - - if(SEC_LEVEL_RED) - if(security_level < SEC_LEVEL_RED) - security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") - else - security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") - security_level = SEC_LEVEL_RED - - var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world - if(R && (R.z in config.station_levels)) - R.locked = 0 - R.update_icon() - - var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) - if(CC) - CC.post_status("alert", "redalert") - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") - - if(SEC_LEVEL_GAMMA) - security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!") - security_level = SEC_LEVEL_GAMMA - - move_gamma_ship() - - if(security_level < SEC_LEVEL_RED) - for(var/obj/machinery/door/airlock/highsecurity/red/R in world) - if((R.z in config.station_levels)) - R.locked = 0 - R.update_icon() - - for(var/obj/machinery/door/airlock/hatch/gamma/H in world) - if((H.z in config.station_levels)) - H.locked = 0 - H.update_icon() - - var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) - if(CC) - CC.post_status("alert", "redalert") - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma") - FA.update_icon() - - if(SEC_LEVEL_EPSILON) - security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!") - security_level = SEC_LEVEL_EPSILON - - var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) - if(CC) - CC.post_status("alert", "redalert") - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon") - - if(SEC_LEVEL_DELTA) - security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!") - security_level = SEC_LEVEL_DELTA - - var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) - if(CC) - CC.post_status("alert", "redalert") - - for(var/obj/machinery/firealarm/FA in world) - if((FA.z in config.contact_levels)) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") - - else - return - -/proc/get_security_level() - switch(security_level) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_GAMMA) - return "gamma" - if(SEC_LEVEL_EPSILON) - return "epsilon" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/num2seclevel(var/num) - switch(num) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_GAMMA) - return "gamma" - if(SEC_LEVEL_EPSILON) - return "epsilon" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/seclevel2num(var/seclevel) - switch( lowertext(seclevel) ) - if("green") - return SEC_LEVEL_GREEN - if("blue") - return SEC_LEVEL_BLUE - if("red") - return SEC_LEVEL_RED - if("gamma") - return SEC_LEVEL_GAMMA - if("epsilon") - return SEC_LEVEL_EPSILON - if("delta") - return SEC_LEVEL_DELTA - - -/*DEBUG -/mob/verb/set_thing0() - set_security_level(0) -/mob/verb/set_thing1() - set_security_level(1) -/mob/verb/set_thing2() - set_security_level(2) -/mob/verb/set_thing3() - set_security_level(3) +/var/security_level = 0 +//0 = code green +//1 = code blue +//2 = code red +//3 = gamma +//4 = epsilon +//5 = code delta + +//config.alert_desc_blue_downto +/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg')) +/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1) + +/proc/set_security_level(var/level) + switch(level) + if("green") + level = SEC_LEVEL_GREEN + if("blue") + level = SEC_LEVEL_BLUE + if("red") + level = SEC_LEVEL_RED + if("gamma") + level = SEC_LEVEL_GAMMA + if("epsilon") + level = SEC_LEVEL_EPSILON + if("delta") + level = SEC_LEVEL_DELTA + + //Will not be announced if you try to set to the same level as it already is + if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) + switch(level) + if(SEC_LEVEL_GREEN) + security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.") + security_level = SEC_LEVEL_GREEN + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") + + if(SEC_LEVEL_BLUE) + if(security_level < SEC_LEVEL_BLUE) + security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.") + else + security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.") + security_level = SEC_LEVEL_BLUE + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") + + if(SEC_LEVEL_RED) + if(security_level < SEC_LEVEL_RED) + security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") + else + security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") + security_level = SEC_LEVEL_RED + + var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world + if(R && (R.z in config.station_levels)) + R.locked = 0 + R.update_icon() + + var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) + if(CC) + CC.post_status("alert", "redalert") + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") + + if(SEC_LEVEL_GAMMA) + security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!") + security_level = SEC_LEVEL_GAMMA + + move_gamma_ship() + + if(security_level < SEC_LEVEL_RED) + for(var/obj/machinery/door/airlock/highsecurity/red/R in world) + if((R.z in config.station_levels)) + R.locked = 0 + R.update_icon() + + for(var/obj/machinery/door/airlock/hatch/gamma/H in world) + if((H.z in config.station_levels)) + H.locked = 0 + H.update_icon() + + var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) + if(CC) + CC.post_status("alert", "redalert") + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma") + FA.update_icon() + + if(SEC_LEVEL_EPSILON) + security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!") + security_level = SEC_LEVEL_EPSILON + + var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) + if(CC) + CC.post_status("alert", "redalert") + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon") + + if(SEC_LEVEL_DELTA) + security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!") + security_level = SEC_LEVEL_DELTA + + var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) + if(CC) + CC.post_status("alert", "redalert") + + for(var/obj/machinery/firealarm/FA in world) + if((FA.z in config.contact_levels)) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") + + else + return + +/proc/get_security_level() + switch(security_level) + if(SEC_LEVEL_GREEN) + return "green" + if(SEC_LEVEL_BLUE) + return "blue" + if(SEC_LEVEL_RED) + return "red" + if(SEC_LEVEL_GAMMA) + return "gamma" + if(SEC_LEVEL_EPSILON) + return "epsilon" + if(SEC_LEVEL_DELTA) + return "delta" + +/proc/num2seclevel(var/num) + switch(num) + if(SEC_LEVEL_GREEN) + return "green" + if(SEC_LEVEL_BLUE) + return "blue" + if(SEC_LEVEL_RED) + return "red" + if(SEC_LEVEL_GAMMA) + return "gamma" + if(SEC_LEVEL_EPSILON) + return "epsilon" + if(SEC_LEVEL_DELTA) + return "delta" + +/proc/seclevel2num(var/seclevel) + switch( lowertext(seclevel) ) + if("green") + return SEC_LEVEL_GREEN + if("blue") + return SEC_LEVEL_BLUE + if("red") + return SEC_LEVEL_RED + if("gamma") + return SEC_LEVEL_GAMMA + if("epsilon") + return SEC_LEVEL_EPSILON + if("delta") + return SEC_LEVEL_DELTA + + +/*DEBUG +/mob/verb/set_thing0() + set_security_level(0) +/mob/verb/set_thing1() + set_security_level(1) +/mob/verb/set_thing2() + set_security_level(2) +/mob/verb/set_thing3() + set_security_level(3) */ \ No newline at end of file diff --git a/code/modules/space_transition/space_transition.dm b/code/modules/space_transition/space_transition.dm new file mode 100644 index 00000000000..81be4604193 --- /dev/null +++ b/code/modules/space_transition/space_transition.dm @@ -0,0 +1,187 @@ +//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube + +#define Z_LEVEL_NORTH "1" +#define Z_LEVEL_SOUTH "2" +#define Z_LEVEL_EAST "4" +#define Z_LEVEL_WEST "8" + + +var/list/z_levels_list = list() + +/datum/space_level + var/name = "Your config settings failed, you need to fix this for the datum space levels to work" + var/list/neigbours + var/z_value = 1 //actual z placement + var/linked = 1 + var/xi + var/yi //imaginary placements on the grid + +/datum/space_level/New() + neigbours = list() + var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST) + for(var/A in L) + neigbours[A] = src + +/datum/space_level/proc/set_neigbours(list/L) + for(var/datum/point/P in L) + if(P.x == xi) + if(P.y == yi+1) + neigbours[Z_LEVEL_NORTH] = P.spl + P.spl.neigbours[Z_LEVEL_SOUTH] = src + else if(P.y == yi-1) + neigbours[Z_LEVEL_SOUTH] = P.spl + P.spl.neigbours[Z_LEVEL_NORTH] = src + else if(P.y == yi) + if(P.x == xi+1) + neigbours[Z_LEVEL_EAST] = P.spl + P.spl.neigbours[Z_LEVEL_WEST] = src + else if(P.x == xi-1) + neigbours[Z_LEVEL_WEST] = P.spl + P.spl.neigbours[Z_LEVEL_EAST] = src + +/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else + var/list/neigbours = list() + var/x + var/y + var/datum/space_level/spl + +/datum/point/New(nx, ny, list/point_grid) + if(!point_grid) + qdel(src) + return + var/list/L = point_grid[1] + if(nx > point_grid.len || ny > L.len) + qdel(src) + return + x = nx + y = ny + if(point_grid[x][y]) + return + point_grid[x][y] = src + +/datum/point/proc/set_neigbours(list/grid) + var/max_X = grid.len + var/list/max_Y = grid[1] + max_Y = max_Y.len + neigbours.Cut() + if(x+1 <= max_X) + neigbours |= grid[x+1][y] + if(x-1 >= 1) + neigbours |= grid[x-1][y] + if(y+1 <= max_Y) + neigbours |= grid[x][y+1] + if(y-1 >= 1) + neigbours |= grid[x][y-1] + + +//config/space_levels.txt is where you define your zlevel datum names, their connection to actual z levels and if you want them connected to one another or not +//Grammar: Name;z value;linked/unlinked +//Name is the name of the datum, just for the sake of it +//z value is to what actual map z level this datum is pointing +//linked/unlinked decide if you want the z level in the general map or not, for example centcomm is not reachable +//Each entry must be separated with a single empty line, no spaces outside the name +//No comments in the file allowed + +/proc/setup_map_transitions() //listamania + var/list/SLS = file2list("config/space_levels.txt", "\n\n") + var/datum/space_level/D + var/list/config_settings[SLS.len][] + for(var/A in SLS) + config_settings[SLS.Find(A)] = text2list(A, ";") + var/conf_set_len = SLS.len + SLS.Cut() + for(var/A in config_settings) + D = new() + D.name = A[1] + D.z_value = text2num(A[2]) + if(A[3] != "linked") + D.linked = 0 + z_levels_list["[D.z_value]"] = D + else + SLS.Add(D) + var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1] + var/list/grid = list() + var/datum/point/P + for(var/i = 1, i<=conf_set_len*2+1, i++) + for(var/j = 1, j<=conf_set_len*2+1, j++) + P = new/datum/point(i,j, point_grid) + point_grid[i][j] = P + grid.Add(P) + for(var/datum/point/pnt in grid) + pnt.set_neigbours(point_grid) + P = point_grid[conf_set_len][conf_set_len] + var/list/possible_points = list() + var/list/used_points = list() + grid.Cut() + while(SLS.len) + D = pick(SLS) + SLS.Remove(D) + D.xi = P.x + D.yi = P.y + P.spl = D + possible_points |= P.neigbours + used_points |= P + possible_points.Remove(used_points) + D.set_neigbours(used_points) + P = pick(possible_points) + grid["[D.z_value]"] = D + + for(var/A in z_levels_list) + grid[A] = z_levels_list[A] + + for(var/turf/space/S in world) //Define the transistions of the z levels + if(S.x <= TRANSITIONEDGE) + D = grid["[S.z]"] + if(D.neigbours[Z_LEVEL_WEST] != D) + D = D.neigbours[Z_LEVEL_WEST] + S.destination_z = D.z_value + else + while(D.neigbours[Z_LEVEL_EAST] != D) + D = D.neigbours[Z_LEVEL_EAST] + S.destination_z = D.z_value + S.destination_x = world.maxx - TRANSITIONEDGE - 2 + S.destination_y = S.y + + if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) + D = grid["[S.z]"] + if(D.neigbours[Z_LEVEL_EAST] != D) + D = D.neigbours[Z_LEVEL_EAST] + S.destination_z = D.z_value + else + while(D.neigbours[Z_LEVEL_WEST] != D) + D = D.neigbours[Z_LEVEL_WEST] + S.destination_z = D.z_value + S.destination_x = TRANSITIONEDGE + 2 + S.destination_y = S.y + + if(S.y <= TRANSITIONEDGE) + D = grid["[S.z]"] + if(D.neigbours[Z_LEVEL_SOUTH] != D) + D = D.neigbours[Z_LEVEL_SOUTH] + S.destination_z = D.z_value + else + while(D.neigbours[Z_LEVEL_NORTH] != D) + D = D.neigbours[Z_LEVEL_NORTH] + S.destination_z = D.z_value + S.destination_x = S.x + S.destination_y = world.maxy - TRANSITIONEDGE - 2 + + if(S.y >= (world.maxy - TRANSITIONEDGE - 1)) + D = grid["[S.z]"] + if(D.neigbours[Z_LEVEL_NORTH] != D) + D = D.neigbours[Z_LEVEL_NORTH] + S.destination_z = D.z_value + else + while(D.neigbours[Z_LEVEL_SOUTH] != D) + D = D.neigbours[Z_LEVEL_SOUTH] + S.destination_z = D.z_value + S.destination_x = S.x + S.destination_y = TRANSITIONEDGE + 2 + + for(var/A in grid) + z_levels_list[A] = grid[A] + +#undef Z_LEVEL_NORTH +#undef Z_LEVEL_SOUTH +#undef Z_LEVEL_EAST +#undef Z_LEVEL_WEST diff --git a/code/modules/vehicle/train/trains/janicart.dm b/code/modules/vehicle/train/trains/janicart.dm deleted file mode 100644 index a1fae332782..00000000000 --- a/code/modules/vehicle/train/trains/janicart.dm +++ /dev/null @@ -1,342 +0,0 @@ -/obj/vehicle/train/janitor/engine - name = "janitor train tug" - desc = "A ridable electric car designed for pulling janitor trolleys." - icon = 'icons/obj/vehicles.dmi' - icon_state = "pussywagon" //mulebot icons until I get some proper icons - on = 0 - powered = 1 - locked = 0 - layer = MOB_LAYER + 0.1 - load_item_visible = 1 - load_offset_x = 0 - load_offset_y = 7 - - var/car_limit = 3 //how many cars an engine can pull before performance degrades - active_engines = 1 - var/obj/item/weapon/key/janitor_train/key - flags = OPENCONTAINER - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - var/obj/item/weapon/storage/bag/trash/mybag = null - -/obj/item/weapon/key/janitor_train - name = "key" - desc = "A keyring with a small steel key, and a yellow fob reading \"Choo Choo!\"." - icon = 'icons/obj/vehicles.dmi' - icon_state = "keys" - w_class = 1 - -/obj/vehicle/train/janitor/trolley - name = "janitor train trolley" - icon = 'icons/obj/janitor.dmi' - icon_state = "trashcart" - anchored = 0 - passenger_allowed = 0 - locked = 0 - load_item_visible = 1 - load_offset_x = 1 - load_offset_y = 7 - - var/openTop = 0 - var/organs = 0 -//------------------------------------------- -// Standard procs -//------------------------------------------- -/obj/vehicle/train/janitor/engine/New() - ..() - cell = new /obj/item/weapon/stock_parts/cell/high - verbs -= /atom/movable/verb/pull - key = new() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - -/obj/vehicle/train/janitor/engine/Move() - . = ..() - handle_rotation() - update_mob() - -/obj/vehicle/train/janitor/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(openTop) - W.loc = src - user.visible_message("[user] puts [W] in [src].","You put [W] in [src].") - if(istype(W,/obj/item/weapon/organ)) - organs = 1 - update_icon() - else - user << "The top is closed!" - -/obj/vehicle/train/janitor/trolley/attack_hand(mob/user) - openTop = !openTop - user.visible_message("[user] [openTop ? "opens" : "closes"] the top of [src].","You [openTop ? "open" : "close"] the the top of [src].") - update_icon() - ..() - -/obj/vehicle/train/janitor/trolley/update_icon() - if(openTop) - if(organs) - icon_state = "trashcartopengib" - else - icon_state = "trashcartopen" - else - if(organs) - icon_state = "trashcartgib" - else - icon_state = "trashcart" - -/obj/vehicle/train/janitor/engine/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/weapon/key/janitor_train)) - if(!key) - user.drop_item() - key = W - W.loc = src - verbs += /obj/vehicle/train/janitor/engine/verb/remove_key - return - else if(istype(W, /obj/item/weapon/mop)) - if(reagents.total_volume >= 2) - reagents.trans_to(W, 2) - user << "You wet the mop in the pimpin' ride." - playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1) - if(reagents.total_volume < 1) - user << "This pimpin' ride is out of water!" - return - else if(istype(W, /obj/item/weapon/storage/bag/trash)) - user << "You hook the trashbag onto the pimpin' ride." - user.drop_item() - W.loc = src - mybag = W - return - ..() - -/obj/vehicle/train/janitor/engine/attack_hand(mob/user) - if(mybag) - mybag.loc = get_turf(user) - user.put_in_hands(mybag) - mybag = null - else - ..() - -/obj/vehicle/train/janitor/update_icon() - if(open) - //icon_state = "mulebot-hatch" - icon_state = initial(icon_state) - else - icon_state = initial(icon_state) - -/obj/vehicle/train/janitor/engine/Emag(mob/user as mob) - ..() - flick("mulebot-emagged", src) - -/obj/vehicle/train/janitor/trolley/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H) - return - -/obj/vehicle/train/janitor/engine/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H) - ..() - update_stats() - -/obj/vehicle/train/janitor/engine/remove_cell(var/mob/living/carbon/human/H) - ..() - update_stats() - -/obj/vehicle/train/janitor/engine/Bump(atom/Obstacle) - var/obj/machinery/door/D = Obstacle - var/mob/living/carbon/human/H = load - if(istype(D) && istype(H)) - D.Bumped(H) //a little hacky, but hey, it works, and repects access rights - - ..() - -/obj/vehicle/train/janitor/trolley/Bump(atom/Obstacle) - if(!lead) - return //so people can't knock others over by pushing a trolley around - ..() - -/obj/vehicle/train/janitor/engine/handle_rotation() - if(dir == SOUTH) - layer = FLY_LAYER - else - layer = OBJ_LAYER - -/obj/vehicle/train/janitor/engine/proc/update_mob() - if(load) - load.dir = dir - switch(dir) - if(SOUTH) - load.pixel_x = 0 - load.pixel_y = 7 - if(WEST) - load.pixel_x = 13 - load.pixel_y = 7 - if(NORTH) - load.pixel_x = 0 - load.pixel_y = 4 - if(EAST) - load.pixel_x = -13 - load.pixel_y = 7 - - -//------------------------------------------- -// Train procs -//------------------------------------------- -/obj/vehicle/train/janitor/engine/turn_on() - if(!key) - return - else - ..() - update_stats() - -/obj/vehicle/train/janitor/RunOver(var/mob/living/carbon/human/H) - var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm") - - H.apply_effects(5, 5) - for(var/i = 0, i < rand(1,3), i++) - H.apply_damage(rand(1,5), BRUTE, pick(parts)) - -/obj/vehicle/train/janitor/trolley/RunOver(var/mob/living/carbon/human/H) - ..() - attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") - -/obj/vehicle/train/janitor/engine/RunOver(var/mob/living/carbon/human/H) - ..() - - if(is_train_head() && istype(load, /mob/living/carbon/human)) - var/mob/living/carbon/human/D = load - D << "\red \b You ran over [H]!" - visible_message("\red \The [src] ran over [H]!") - attack_log += text("\[[time_stamp()]\] ran over [key_name(H)], driven by [key_name(D)]") - msg_admin_attack("[key_name_admin(D)] ran over [key_name_admin(H)]") - else - attack_log += text("\[[time_stamp()]\] ran over [key_name(H)]") - - -//------------------------------------------- -// Interaction procs -//------------------------------------------- -/obj/vehicle/train/janitor/engine/relaymove(mob/user, direction) - if(user != load) - return 0 - - if(is_train_head()) - if(direction == reverse_direction(dir)) - return 0 - if(Move(get_step(src, direction))) - return 1 - return 0 - else - return ..() - - -/obj/vehicle/train/janitor/engine/examine(mob/user) - if(!..(user, 1)) - return - - user << "\icon[src] This [name] contains [reagents.total_volume] unit\s of [reagents]!" - if(mybag) - user << "\A [mybag] is hanging on the [name]." - - user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." - -/obj/vehicle/train/janitor/engine/verb/check_power() - set name = "Check power level" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living/carbon/human)) - return - - if(!cell) - usr << "There is no power cell installed in [src]." - return - - usr << "The power meter reads [round(cell.percent(), 0.01)]%" - -/obj/vehicle/train/janitor/engine/verb/start_engine() - set name = "Start engine" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living/carbon/human)) - return - - if(on) - usr << "The engine is already running." - return - - turn_on() - if (on) - usr << "You start [src]'s engine." - else - if(cell.charge < charge_use) - usr << "[src] is out of power." - else - usr << "[src]'s engine won't start." - -/obj/vehicle/train/janitor/engine/verb/stop_engine() - set name = "Stop engine" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living/carbon/human)) - return - - if(!on) - usr << "The engine is already stopped." - return - - turn_off() - if (!on) - usr << "You stop [src]'s engine." - -/obj/vehicle/train/janitor/engine/verb/remove_key() - set name = "Remove key" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living/carbon/human)) - return - - if(!key || (load && load != usr)) - return - - if(on) - turn_off() - - key.loc = usr.loc - if(!usr.get_active_hand()) - usr.put_in_hands(key) - key = null - - verbs -= /obj/vehicle/train/janitor/engine/verb/remove_key - -//------------------------------------------- -// Loading/unloading procs -//------------------------------------------- -/obj/vehicle/train/janitor/trolley/load(var/atom/movable/C) - return 0 - -/obj/vehicle/train/janitor/engine/load(var/atom/movable/C) - if(!ismob(C)) - return 0 - - return ..() - - -//------------------------------------------------------- -// Stat update procs -// -// Update the trains stats for speed calculations. -// The longer the train, the slower it will go. car_limit -// sets the max number of cars one engine can pull at -// full speed. Adding more cars beyond this will slow the -// train proportionate to the length of the train. Adding -// more engines increases this limit by car_limit per -// engine. -//------------------------------------------------------- - -/obj/vehicle/train/janitor/engine/proc/update_move_delay() - if(!is_train_head() || !on) - move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind - else - move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains - move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) - move_delay += config.run_speed //base reference speed - move_delay *= 1.05 diff --git a/code/stylesheet.dm b/code/stylesheet.dm index ffd829c70b4..c0e951046fa 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -11,6 +11,8 @@ em {font-style: normal; font-weight: bold;} .motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;} +.italics { font-style: italic;} + .prefix { font-weight: bold;} .ooc { font-weight: bold;} diff --git a/config/example/config.txt b/config/example/config.txt index 33dd8659aae..076a0e80766 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -184,10 +184,10 @@ GUEST_BAN ## spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard # FEATURE_OBJECT_SPELL_SYSTEM -##Toggle for having jobs load up from the .txt +## Toggle for having jobs load up from the .txt LOAD_JOBS_FROM_TXT -##Remove the # mark infront of this to forbid admins from posssessing the singularity. +## Remove the # mark infront of this to forbid admins from posssessing the singularity. #FORBID_SINGULO_POSSESSION ## Remove the # to show a popup 'reply to' window to every non-admin that recieves an adminPM. diff --git a/config/example/space_levels.txt b/config/example/space_levels.txt new file mode 100644 index 00000000000..e724264daac --- /dev/null +++ b/config/example/space_levels.txt @@ -0,0 +1,15 @@ +Main Station;1;linked + +Central Command;2;unlinked + +Telecommunications Satellite;3;linked + +Engineering Outpost;4;linked + +Mining Asteroid;5;linked + +Derelicted Station;6;linked + +Empty Area;7;linked + +Syndicate Station;8;unlinked \ No newline at end of file diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi index 75f2ccef866..24e7f335be8 100644 Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index 79d773f7627..a55b4a75ae2 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 826c5ea1f4f..dd6cf13fc1e 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi index 38b93652f0e..119f3df0e37 100644 Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ diff --git a/icons/obj/money.dmi b/icons/obj/money.dmi index c052cb8ea93..7b8a5e09495 100644 Binary files a/icons/obj/money.dmi and b/icons/obj/money.dmi differ diff --git a/icons/obj/pipe-item.dmi b/icons/obj/pipe-item.dmi index 1ef48fbad13..34fedaa560f 100644 Binary files a/icons/obj/pipe-item.dmi and b/icons/obj/pipe-item.dmi differ diff --git a/icons/obj/trash.dmi b/icons/obj/trash.dmi index 1d0d126006b..600ecc9f8a5 100644 Binary files a/icons/obj/trash.dmi and b/icons/obj/trash.dmi differ diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi index 9d92dd02a81..63515f5b2e5 100644 Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ diff --git a/paradise.dme b/paradise.dme index 76969b151fa..510d4864fbe 100644 --- a/paradise.dme +++ b/paradise.dme @@ -121,6 +121,7 @@ #include "code\ATMOSPHERICS\components\unary_devices\heat_source.dm" #include "code\ATMOSPHERICS\components\unary_devices\outlet_injector.dm" #include "code\ATMOSPHERICS\components\unary_devices\oxygen_generator.dm" +#include "code\ATMOSPHERICS\components\unary_devices\passive_vent.dm" #include "code\ATMOSPHERICS\components\unary_devices\portables_connector.dm" #include "code\ATMOSPHERICS\components\unary_devices\tank.dm" #include "code\ATMOSPHERICS\components\unary_devices\thermal_plate.dm" @@ -186,6 +187,7 @@ #include "code\datums\spell.dm" #include "code\datums\supplypacks.dm" #include "code\datums\uplink_item.dm" +#include "code\datums\vision_override.dm" #include "code\datums\cache\air_alarm.dm" #include "code\datums\cache\apc.dm" #include "code\datums\cache\cache.dm" @@ -813,7 +815,6 @@ #include "code\game\objects\structures\musician.dm" #include "code\game\objects\structures\noticeboard.dm" #include "code\game\objects\structures\safe.dm" -#include "code\game\objects\structures\segway.dm" #include "code\game\objects\structures\signs.dm" #include "code\game\objects\structures\spirit_board.dm" #include "code\game\objects\structures\tables_racks.dm" @@ -907,6 +908,7 @@ #include "code\modules\admin\player_panel.dm" #include "code\modules\admin\secrets.dm" #include "code\modules\admin\sql_notes.dm" +#include "code\modules\admin\stickyban.dm" #include "code\modules\admin\topic.dm" #include "code\modules\admin\ToRban.dm" #include "code\modules\admin\watchlist.dm" @@ -998,6 +1000,7 @@ #include "code\modules\client\client defines.dm" #include "code\modules\client\client procs.dm" #include "code\modules\client\global_cache.dm" +#include "code\modules\client\message.dm" #include "code\modules\client\preferences.dm" #include "code\modules\client\preferences_mysql.dm" #include "code\modules\client\preferences_spawnpoints.dm" @@ -1091,10 +1094,10 @@ #include "code\modules\crafting\table.dm" #include "code\modules\customitems\item_defines.dm" #include "code\modules\customitems\item_spawning.dm" -#include "code\modules\DetectiveWork\detective_work.dm" -#include "code\modules\DetectiveWork\evidence.dm" -#include "code\modules\DetectiveWork\footprints_and_rag.dm" -#include "code\modules\DetectiveWork\scanner.dm" +#include "code\modules\detective_work\detective_work.dm" +#include "code\modules\detective_work\evidence.dm" +#include "code\modules\detective_work\footprints_and_rag.dm" +#include "code\modules\detective_work\scanner.dm" #include "code\modules\economy\Accounts.dm" #include "code\modules\economy\Accounts_DB.dm" #include "code\modules\economy\ATM.dm" @@ -1180,8 +1183,8 @@ #include "code\modules\food\recipes_microwave.dm" #include "code\modules\food\recipes_oven.dm" #include "code\modules\food\recipes_table.dm" -#include "code\modules\garbage collection\garbage_collector.dm" -#include "code\modules\garbage collection\gc_testing.dm" +#include "code\modules\garbage_collection\garbage_collector.dm" +#include "code\modules\garbage_collection\gc_testing.dm" #include "code\modules\holiday\christmas.dm" #include "code\modules\holiday\holiday.dm" #include "code\modules\hydroponics\grown.dm" @@ -1497,6 +1500,7 @@ #include "code\modules\nano\nanoui.dm" #include "code\modules\nano\interaction\admin.dm" #include "code\modules\nano\interaction\base.dm" +#include "code\modules\nano\interaction\conscious.dm" #include "code\modules\nano\interaction\contained.dm" #include "code\modules\nano\interaction\default.dm" #include "code\modules\nano\interaction\inventory.dm" @@ -1585,14 +1589,14 @@ #include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm" #include "code\modules\power\singularity\particle_accelerator\particle_power.dm" #include "code\modules\power\supermatter\supermatter.dm" -#include "code\modules\procedural mapping\mapGenerator.dm" -#include "code\modules\procedural mapping\mapGeneratorModule.dm" -#include "code\modules\procedural mapping\mapGeneratorReadme.dm" -#include "code\modules\procedural mapping\mapGeneratorModules\helpers.dm" -#include "code\modules\procedural mapping\mapGeneratorModules\nature.dm" -#include "code\modules\procedural mapping\mapGenerators\asteroid.dm" -#include "code\modules\procedural mapping\mapGenerators\nature.dm" -#include "code\modules\procedural mapping\mapGenerators\syndicate.dm" +#include "code\modules\procedural_mapping\mapGenerator.dm" +#include "code\modules\procedural_mapping\mapGeneratorModule.dm" +#include "code\modules\procedural_mapping\mapGeneratorReadme.dm" +#include "code\modules\procedural_mapping\mapGeneratorModules\helpers.dm" +#include "code\modules\procedural_mapping\mapGeneratorModules\nature.dm" +#include "code\modules\procedural_mapping\mapGenerators\asteroid.dm" +#include "code\modules\procedural_mapping\mapGenerators\nature.dm" +#include "code\modules\procedural_mapping\mapGenerators\syndicate.dm" #include "code\modules\projectiles\ammunition.dm" #include "code\modules\projectiles\gun.dm" #include "code\modules\projectiles\projectile.dm" @@ -1804,8 +1808,8 @@ #include "code\modules\scripting\Parser\Parser.dm" #include "code\modules\scripting\Scanner\Scanner.dm" #include "code\modules\scripting\Scanner\Tokens.dm" -#include "code\modules\security levels\keycard authentication.dm" -#include "code\modules\security levels\security levels.dm" +#include "code\modules\security_levels\keycard authentication.dm" +#include "code\modules\security_levels\security levels.dm" #include "code\modules\shieldgen\circuits_and_designs.dm" #include "code\modules\shieldgen\energy_field.dm" #include "code\modules\shieldgen\shield_capacitor.dm" @@ -1822,6 +1826,7 @@ #include "code\modules\shuttles\shuttle_supply.dm" #include "code\modules\shuttles\shuttles_multi.dm" #include "code\modules\shuttles\whiteship.dm" +#include "code\modules\space_transition\space_transition.dm" #include "code\modules\store\items.dm" #include "code\modules\store\store.dm" #include "code\modules\surgery\bones.dm" @@ -1848,7 +1853,6 @@ #include "code\modules\vehicle\vehicle.dm" #include "code\modules\vehicle\train\train.dm" #include "code\modules\vehicle\train\trains\ambulance.dm" -#include "code\modules\vehicle\train\trains\janicart.dm" #include "code\modules\vehicle\train\trains\cargo\cargo_train.dm" #include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\fourwheeler.dm" #include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\motorcycle.dm"