From bf5200daf87955af312b6781908ccb8f918c7678 Mon Sep 17 00:00:00 2001 From: ikarrus Date: Sun, 15 Jun 2014 21:24:07 -0600 Subject: [PATCH 01/17] [Config] Security Officer Scaling Intended for high-population servers Open security officer positions scale with population, between 5 slots at ~40 players to 12 slots at ~96 players Default coefficient is 8, but may be modified (or disabled) in the config. Extra lockers will spawn if there aren't enough lockers. --- _maps/map_files/tgstation.2.1.3.dmm | 57 +++++++++++++------------- code/_globalvars/lists/mapping.dm | 1 + code/controllers/configuration.dm | 3 ++ code/game/jobs/job/security.dm | 4 +- code/game/jobs/job_controller.dm | 21 ++++++++++ code/game/objects/effects/landmarks.dm | 5 ++- config/game_options.txt | 5 +++ 7 files changed, 65 insertions(+), 31 deletions(-) diff --git a/_maps/map_files/tgstation.2.1.3.dmm b/_maps/map_files/tgstation.2.1.3.dmm index 2cd7fe99609..588f6c4f6a3 100644 --- a/_maps/map_files/tgstation.2.1.3.dmm +++ b/_maps/map_files/tgstation.2.1.3.dmm @@ -65,7 +65,7 @@ "abm" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/brig) "abn" = (/obj/machinery/atmospherics/pipe/manifold{pipe_color = "blue"; icon_state = "manifold-b-f"; level = 1; name = "pipe manifold"},/turf/simulated/floor{icon_state = "dark"},/area/security/brig) "abo" = (/turf/simulated/floor/carpet,/area/security/hos) -"abp" = (/obj/structure/extinguisher_cabinet{pixel_x = 5; pixel_y = -32},/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor{icon_state = "red"},/area/security/main) +"abp" = (/obj/structure/extinguisher_cabinet{pixel_x = 5; pixel_y = -32},/turf/simulated/floor{icon_state = "red"},/area/security/main) "abq" = (/obj/structure/sign/securearea{pixel_y = -32},/turf/space,/area/space) "abr" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plating/airless,/area/solar/auxstarboard) "abs" = (/obj/structure/stool/bed,/obj/machinery/camera{c_tag = "Prison Cell 3"; network = list("SS13","Prison")},/obj/item/device/radio/intercom{desc = "Talk through this. It looks like it has been modified to not broadcast."; dir = 2; name = "Prison Intercom (General)"; pixel_x = 0; pixel_y = 24; prison_radio = 1},/turf/simulated/floor{icon_state = "floorgrime"},/area/security/prison) @@ -103,11 +103,11 @@ "abY" = (/obj/structure/rack,/obj/item/weapon/shield/riot{pixel_x = -3; pixel_y = 3},/obj/item/weapon/shield/riot,/obj/item/weapon/shield/riot{pixel_x = 3; pixel_y = -3},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/ai_monitored/security/armory) "abZ" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/brig) "aca" = (/obj/structure/closet/l3closet/security,/obj/machinery/camera{c_tag = "Brig Equipment Room"; dir = 4},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) -"acb" = (/obj/structure/table,/obj/item/weapon/packageWrap,/obj/item/weapon/pen,/turf/simulated/floor{icon_state = "red"},/area/security/main) -"acc" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/structure/disposalpipe/sortjunction{dir = 8; icon_state = "pipe-j2s"; sortType = 7},/turf/simulated/floor,/area/security/main) +"acb" = (/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"},/area/security/main) +"acc" = (/obj/machinery/light,/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"},/area/security/main) "acd" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/security/hos) "ace" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/carpet,/area/security/hos) -"acf" = (/obj/machinery/light,/turf/simulated/floor{icon_state = "red"},/area/security/main) +"acf" = (/obj/machinery/light_switch{pixel_y = -23},/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"},/area/security/main) "acg" = (/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -29},/obj/machinery/computer/security,/turf/simulated/floor{icon_state = "red"},/area/security/main) "ach" = (/obj/machinery/camera{c_tag = "Security Office"; dir = 1; network = list("SS13")},/obj/machinery/computer/secure_data,/turf/simulated/floor{icon_state = "red"},/area/security/main) "aci" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = -32; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/fsmaint) @@ -122,7 +122,7 @@ "acr" = (/obj/machinery/power/apc{dir = 1; name = "Labor Shuttle Dock APC"; pixel_y = 24},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/brig) "acs" = (/obj/machinery/vending/security,/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) "act" = (/obj/structure/disposalpipe/junction{icon_state = "pipe-y"; dir = 1},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/structure/stool/bed/chair,/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor,/area/security/main) -"acu" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) +"acu" = (/obj/structure/noticeboard{dir = 1; pixel_y = -27},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"},/area/security/main) "acv" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/carpet,/area/security/hos) "acw" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/carpet,/area/security/hos) "acx" = (/obj/machinery/light_switch{pixel_y = -23},/turf/simulated/floor/carpet,/area/security/hos) @@ -164,9 +164,9 @@ "adh" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/security/hos) "adi" = (/obj/machinery/door/airlock/glass_command{name = "Head of Security"; req_access_txt = "58"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/carpet,/area/security/hos) "adj" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/grille,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/security/hos) -"adk" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) +"adk" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor,/area/security/main) "adl" = (/obj/machinery/hologram/holopad,/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor,/area/security/main) -"adm" = (/turf/simulated/floor{dir = 5; icon_state = "warning"},/area/security/main) +"adm" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/structure/disposalpipe/sortjunction{dir = 4; icon_state = "pipe-j2s"; sortType = 7},/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) "adn" = (/obj/machinery/camera{c_tag = "Security Escape Pod"; dir = 4; network = list("SS13")},/turf/simulated/floor/plating,/area/maintenance/fsmaint) "ado" = (/turf/simulated/floor/plating,/obj/structure/shuttle/engine/propulsion/burst{dir = 4},/turf/simulated/shuttle/wall{icon_state = "swall_f6"; dir = 2},/area/shuttle/escape_pod3/station) "adp" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/escape_pod3/station) @@ -198,11 +198,11 @@ "adP" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/brig) "adQ" = (/turf/simulated/floor,/area/security/main) "adR" = (/obj/effect/landmark/start{name = "Head of Security"},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) -"adS" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 6},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/main) -"adT" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 9},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) -"adU" = (/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) +"adS" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/structure/disposalpipe/segment,/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) +"adT" = (/obj/machinery/requests_console{department = "Security"; departmentType = 5; pixel_y = 30},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) +"adU" = (/obj/machinery/atmospherics/pipe/manifold{pipe_color = "blue"; dir = 8; icon_state = "manifold-b-f"; initialize_directions = 11; level = 1; name = "pipe manifold"},/obj/effect/landmark{name = "secequipment"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) "adV" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/structure/table,/obj/machinery/recharger,/obj/item/device/radio/intercom{freerange = 0; frequency = 1459; name = "Station Intercom (General)"; pixel_x = 29},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) -"adW" = (/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/security/main) +"adW" = (/obj/effect/landmark/start{name = "Security Officer"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) "adX" = (/obj/machinery/door/airlock/external{name = "Security Escape Pod"; req_access_txt = "63"},/turf/simulated/floor/plating,/area/security/main) "adY" = (/turf/simulated/floor/plating,/area/maintenance/fsmaint) "adZ" = (/obj/machinery/door/airlock/shuttle{name = "Escape Pod Airlock"},/turf/simulated/shuttle/floor,/area/shuttle/escape_pod3/station) @@ -218,16 +218,16 @@ "aej" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating/airless,/area/solar/auxport) "aek" = (/turf/simulated/floor{icon_state = "warnwhite"; dir = 1},/area/security/prison) "ael" = (/turf/simulated/floor{icon_state = "warnwhite"; dir = 5},/area/security/prison) -"aem" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) +"aem" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 6},/obj/effect/landmark/start{name = "Security Officer"},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/main) "aen" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/effect/landmark/start{name = "Security Officer"},/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor,/area/security/main) "aeo" = (/obj/structure/table,/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/obj/item/weapon/razor{pixel_x = -6},/obj/item/stack/medical/ointment{pixel_y = 4},/obj/item/stack/medical/bruise_pack{pixel_x = 10; pixel_y = 2},/obj/item/weapon/reagent_containers/syringe/inaprovaline{pixel_x = 5; pixel_y = -2},/turf/simulated/floor{icon_state = "whitehall"; dir = 2},/area/security/prison) -"aep" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) +"aep" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 9},/obj/effect/landmark/start{name = "Security Officer"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) "aeq" = (/obj/structure/closet/secure_closet/brig{anchored = 1},/turf/simulated/floor{icon_state = "red"},/area/security/prison) "aer" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/glass_security{name = "Prison Wing"; req_access_txt = "2"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/prison) "aes" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/glass_security{name = "Prison Wing"; req_access_txt = "2"},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/prison) "aet" = (/obj/machinery/door/airlock/maintenance{name = "Security Maintenance"; req_access_txt = "2"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/security/processing) "aeu" = (/obj/machinery/flasher/portable,/obj/structure/window/reinforced,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/ai_monitored/security/armory) -"aev" = (/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/main) +"aev" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/effect/landmark/start{name = "Security Officer"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) "aew" = (/obj/structure/rack,/obj/item/weapon/gun/energy/laser{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/laser,/obj/item/weapon/gun/energy/laser{pixel_x = 3; pixel_y = -3},/obj/structure/window/reinforced,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/ai_monitored/security/armory) "aex" = (/obj/structure/rack,/obj/item/weapon/gun/energy/gun{pixel_x = -3; pixel_y = 3},/obj/item/weapon/gun/energy/gun,/obj/item/weapon/gun/energy/gun{pixel_x = 3; pixel_y = -3},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/ai_monitored/security/armory) "aey" = (/obj/structure/table/reinforced,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/door/window/brigdoor{dir = 1; name = "Armory Desk"; req_access_txt = "3"},/obj/machinery/door/window/southleft{name = "Reception Desk"; req_access_txt = "63"},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/warden) @@ -241,7 +241,7 @@ "aeG" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/warden) "aeH" = (/obj/structure/table,/obj/item/weapon/handcuffs,/obj/item/device/assembly/timer,/turf/simulated/floor,/area/security/main) "aeI" = (/obj/structure/table,/obj/item/device/radio/off,/obj/item/weapon/screwdriver{pixel_y = 10},/turf/simulated/floor,/area/security/main) -"aeJ" = (/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) +"aeJ" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/effect/landmark/start{name = "Security Officer"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) "aeK" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) "aeL" = (/obj/structure/sign/pods{pixel_x = 32; pixel_y = 0},/turf/simulated/floor{dir = 6; icon_state = "warning"},/area/security/main) "aeM" = (/obj/structure/closet/emcloset,/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/maintenance/fsmaint) @@ -277,7 +277,7 @@ "afq" = (/obj/item/weapon/cigbutt,/turf/simulated/floor{icon_state = "dark"},/area/security/brig) "afr" = (/obj/structure/closet{name = "Evidence Closet"},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/brig) "afs" = (/turf/simulated/floor{icon_state = "red"; dir = 8},/area/hallway/secondary/exit) -"aft" = (/obj/machinery/light_switch{pixel_y = -23},/turf/simulated/floor{icon_state = "red"},/area/security/main) +"aft" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/main) "afu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/brig) "afv" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/brig) "afw" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating,/area/security/warden) @@ -360,7 +360,7 @@ "agV" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor{icon_state = "barber"},/area/security/prison) "agW" = (/obj/structure/bookcase,/turf/simulated/floor{icon_state = "floorgrime"},/area/security/prison) "agX" = (/obj/machinery/alarm{pixel_y = 23},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) -"agY" = (/obj/structure/closet/secure_closet/security/sec,/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) +"agY" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/security/main) "agZ" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 5},/turf/simulated/floor{icon_state = "red"},/area/security/main) "aha" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor{icon_state = "red"; dir = 6},/area/security/main) "ahb" = (/obj/machinery/door/airlock/maintenance{name = "Security Maintenance"; req_access_txt = "63"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/floor/plating,/area/security/main) @@ -466,7 +466,7 @@ "aiX" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/brig) "aiY" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/brig) "aiZ" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/machinery/door_timer/cell_4,/obj/machinery/light,/turf/simulated/floor{icon_state = "red"},/area/security/brig) -"aja" = (/obj/structure/noticeboard{dir = 1; pixel_y = -27},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "red"},/area/security/main) +"aja" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/main) "ajb" = (/turf/simulated/floor,/area/security/brig) "ajc" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{req_access_txt = "0"},/turf/simulated/floor{icon_state = "red"; dir = 4},/area/security/brig) "ajd" = (/turf/simulated/floor{icon_state = "neutral"; dir = 8},/area/crew_quarters/courtroom) @@ -492,8 +492,8 @@ "ajx" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/security/brig) "ajy" = (/obj/machinery/door/airlock/glass_security{id_tag = "innerbrig"; name = "Brig"; req_access_txt = "63"},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/security/brig) "ajz" = (/obj/machinery/door/airlock/glass_security{id_tag = "innerbrig"; name = "Brig"; req_access_txt = "63"},/turf/simulated/floor{icon_state = "red"; dir = 5},/area/security/brig) -"ajA" = (/obj/machinery/requests_console{department = "Security"; departmentType = 5; pixel_y = 30},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) -"ajB" = (/obj/machinery/atmospherics/pipe/manifold{pipe_color = "blue"; dir = 8; icon_state = "manifold-b-f"; initialize_directions = 11; level = 1; name = "pipe manifold"},/turf/simulated/floor{icon_state = "red"; dir = 1},/area/security/main) +"ajA" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/turf/simulated/floor{dir = 5; icon_state = "warning"},/area/security/main) +"ajB" = (/obj/structure/table,/obj/item/weapon/packageWrap,/obj/item/weapon/pen,/turf/simulated/floor,/area/security/main) "ajC" = (/obj/structure/table,/obj/item/weapon/storage/box/bodybags,/obj/item/weapon/pen,/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 0; scrub_Toxins = 0},/obj/machinery/light/small{dir = 1},/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/prison) "ajD" = (/obj/structure/stool/bed/chair{dir = 4; name = "Prosecution"},/turf/simulated/floor{icon_state = "red"; dir = 9},/area/crew_quarters/courtroom) "ajE" = (/obj/structure/table/woodentable,/turf/simulated/floor{icon_state = "neutral"; dir = 8},/area/crew_quarters/courtroom) @@ -8921,6 +8921,7 @@ "dpC" = (/obj/machinery/atmospherics/pipe/tank/air{dir = 8},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 5},/area/medical/virology) "dpD" = (/obj/machinery/atmospherics/valve{dir = 4; icon_state = "valve1"; open = 1; openDuringInit = 1},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/medical/virology) "dpE" = (/obj/machinery/alarm{frequency = 1439; pixel_y = 23},/obj/item/weapon/wrench,/obj/machinery/atmospherics/pipe/manifold{pipe_color = "blue"; dir = 8; icon_state = "manifold-b-f"; level = 1; name = "pipe manifold"},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 9},/area/medical/virology) +"dpF" = (/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/structure/closet/secure_closet/security/sec,/turf/simulated/floor{icon_state = "showroomfloor"},/area/security/main) "dpH" = (/turf/simulated/wall,/area/aisat) "dpI" = (/obj/effect/landmark/start{name = "Cyborg"},/turf/simulated/floor{icon_state = "dark"},/area/turret_protected/aisat_interior) "dpJ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/wall/r_wall,/area/aisat) @@ -9216,18 +9217,18 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdabdabdabdabdabdabdaagaaiaaiamHaaxaaqaaqaayaazaaxaaqaataaAaaiahlaahaafaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaafaaaaafaaaaafaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdagqagvaikajCamGabdabdaaiaaBaaqaaqaaqaaxaaCafYaaqaaqaaEaaFaaiaaiaaiaafaaaaaaaaaaaaaaaaafaaaaahaaaaaaaaaaafaafaafaafaafaafaafaafaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaaGaaGaaHaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaatuagSaiJaiMaiKaiLagJaiIaaiaaIaaqaaJaaqaaqaaqaaqaaqaaqaaKaaqaaLaaMaaiaafaafaafaafaafaafaafaafabkabkablabkabkaaNaaNaaOaaPaaQaaNaaNaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaaaaafaaaaaRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabddoVdoWaojdoYdpoabddppaaiaaSaaqaaqaaTaaqaaqaaqaaUaaqaaKaaqaaVaaWaaiaafaaaaaaaaaaaaaaaaaaaaaablafmabBagXagYaaNdpcaaYaaZdpbdpdaaNaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafabcaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabddoVdoWaojdoYdpoabddppaaiaaSaaqaaqaaTaaqaaqaaqaaUaaqaaKaaqaaVaaWaaiaafaaaaaaaaaaaaaaaaaaaaaablafmabBagXdpFaaNdpcaaYaaZdpbdpdaaNaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafabcaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaHaaHaaGaaHaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabdabddpedpqdphdoLabddpgaaiabdabeabdabfabdabgabdabhabdabiabdabdabjaaiaafaaaaafaafaafaafaaaaafabkabCabBaNpafmaaNdpjabodpkabobmDaaNaaaaafabqaafaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaaGaaGaaGaaGaaaaaaaaaabraaaaaaaaaaaGaaGaaHaaHaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaafaaaaaRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafdpmdoLdpfdoLabddpiaaiabsaaqabtabfabuaaqabvabhabwaaKabxabdabyaaiabzabzabzabzabzabzabzabzabzabAabBaeKafmabDabodoJdoIabEagpaaNaaaaafabIabJabIaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaRaaaaaaaafaafaafaaaaaaabraafaafaaaaafaafaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafabKaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafdpmdoTdoRdoSagjdpnaaiabLaaqabMabNabOaaqabPabhabQaaKabPabdabRaaiabSabTabVabVabWabXabYdoOabzacaabBaeKafmacdaceabodoPabodoUaaNaafaafabIaciabIaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacjacjacjacjacjaafackaafacjacjacjacjacjaafaaGaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaHaaHaaGaaGaaaaaaaaaaclaaaaaaaaaaaGaaGaaHaaHaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlahlahlabddowdoxdosdoydozaaiabhacmabdabfabhacnabfabhabhacoabfabdabdaaiabSacpacqacqacqacqdoCdoAabzacsabBaeKafmaaNdoBacvacwacxacyaaNafOabkacBabJabIabIacCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacDacEacEacEacEacFacGacHacIacIacIacIacJaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaafaafaaaaaaaaaaclaafaafaaaaafaafaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlahlahlahlahlahlahldoMdoKdoDdoHacPacMacNdpaacPacQacRacSacPacTacUacVacWaaiacXacYdoEdoFadbdoGdoQdoZbYgabBadfadgabkaaNadhaaNadiaaNadjaaNadQadmabkadnadoadpadpadqaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadradradradradraafacGaafadradradradradraafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadsadsadsadsadsaafadtaafadsadsadsadsadsaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlahlahlahlahlahlahlaKubRDcdladzamJadwaliadBadzadAadBadzadzadCajwadEadFaaiadGamfadIadJadJadKalbakZalaajQaksadVabkadSadTadUadRaemaepadUaevadWadXadYadZaeaaohaecaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaafacGaaaaaaaaaaafaaaaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaedaeeaeeaeeaeeaefaegaehaeiaeiaeiaeiaejaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlaaaahlahlahlahldoraaiaaiaaiaaidoidoudotdbydbjaeodaZaeqaeqaeqabdaeraesaaiaoiaeudbaaewaexbEBcuwaeAabzaeBchVaeDabkcuGaeHadQcuUaeEaeIdovaeJaeLabkaeMaeNadpadpaeOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacjacjacjacjacjaafacGaafacjacjacjacjacjaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaePaePaePaePaePaafaegaafaePaePaePaePaePaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaiaaiabdafaabdaeSaeSaeSaeSaeSaeSaeSaeTaeUaeVafhaeXaeYaeZagdafbagkafdaeVafeagoajBajAaeWafjadQadlaeEafkaeFadkabkacBabIabIabIacCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacDacEacEacEacEacFacGacHacIacIacIacIacJaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaafaegaaaaaaaaaaafaaaaaaaaaaaRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaafaaaaaaaaiadHaekaelaeSafnafoafpafqafoaeSafuafvafwagMafxafyafcahmafBafMafXafNagbagaafHafIaenaczafIacAadyadxadvacuafPafQafRafSabIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadradradradradraafacGaafadradradradradraafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadsadsadsadsadsaafaegaafadsadsadsadsadsaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaafaafaafaafaafaafaafaafaaiadaaaDafKaeSafTafUafVafWafoaeSafuafLagGagHagiageagfaggaghafEagMafDafGafFagmagnacKagnagnactagraccagsagtabkabkadYaguabIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaaaacGaaaaaaaaaaafaaaaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaedaeeaeeaeeaeeaefaegaehaeiaeiaeiaeiaejaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaaiabFaaDadOagAabnagwagxagyagzagAadPaeCafwafCagcafiaflagKabGaeGagNaeQagPahsajaaftacfagUachacgacbabpagZahaahbahcahdaheahfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacjacjacjacjacjaafacGaafacjacjacjacjacjaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaafaafaaaaaaaaaaclaafaafaaaaafaafaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlahlahlahlahlahlahldoMdoKdoDdoHacPacMacNdpaacPacQacRacSacPacTacUacVacWaaiacXacYdoEdoFadbdoGdoQdoZbYgabBadfadgabkaaNadhaaNadiaaNadjaaNajBajAabkadnadoadpadpadqaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadradradradradraafacGaafadradradradradraafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadsadsadsadsadsaafadtaafadsadsadsadsadsaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlahlahlahlahlahlahlaKubRDcdladzamJadwaliadBadzadAadBadzadzadCajwadEadFaaiadGamfadIadJadJadKalbakZalaajQaksadVabkaemaepadWadRaevaeJadWaftagYadXadYadZaeaaohaecaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaafacGaaaaaaaaaaafaaaaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaedaeeaeeaeeaeeaefaegaehaeiaeiaeiaeiaejaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahlaaaahlahlahlahldoraaiaaiaaiaaidoidoudotdbydbjaeodaZaeqaeqaeqabdaeraesaaiaoiaeudbaaewaexbEBcuwaeAabzaeBchVaeDabkcuGaeHadQcuUaeEaeIdovajaaeLabkaeMaeNadpadpaeOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacjacjacjacjacjaafacGaafacjacjacjacjacjaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaePaePaePaePaePaafaegaafaePaePaePaePaePaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaiaaiabdafaabdaeSaeSaeSaeSaeSaeSaeSaeTaeUaeVafhaeXaeYaeZagdafbagkafdaeVafeagoadUadTaeWafjadQadlaeEafkaeFadSabkacBabIabIabIacCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacDacEacEacEacEacFacGacHacIacIacIacIacJaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaafaegaaaaaaaaaaafaaaaaaaaaaaRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaafaaaaaaaaiadHaekaelaeSafnafoafpafqafoaeSafuafvafwagMafxafyafcahmafBafMafXafNagbagaafHafIaenaczafIacAadyadxadvadmafPafQafRafSabIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadradradradradraafacGaafadradradradradraafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadsadsadsadsadsaafaegaafadsadsadsadsadsaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaafaafaafaafaafaafaafaafaaiadaaaDafKaeSafTafUafVafWafoaeSafuafLagGagHagiageagfaggaghafEagMafDafGafFagmagnacKagnagnactagradkagsagtabkabkadYaguabIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaaaacGaaaaaaaaaaafaaaaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaedaeeaeeaeeaeeaefaegaehaeiaeiaeiaeiaejaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaaiabFaaDadOagAabnagwagxagyagzagAadPaeCafwafCagcafiaflagKabGaeGagNaeQagPahsacuacfaccacbachacgagUabpagZahaahbahcahdaheahfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafacjacjacjacjacjaafacGaafacjacjacjacjacjaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafaePaePaePaePaePaafaegaafaePaePaePaePaePaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaafaafaafaafaafaaaaafaaaaaaaaiadLadMadNaeSahgahhahhahhahhahiadDagFaeVafAaezaeyahpahqaduafzaeVaeVacBagRahtacBacBabkabkabkabkabkabkabkabkahuahvahwahxaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaafacDacEacEacEacEacFacGacHacIacIacIacIacJaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaaaaaaaafaaaaaaaaaaegaaaaaaaaaaafaaaaaaaaaaaHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafahyahyakWahyadcaeRaddaeSaeSaeSaeSaeSaeSahzaeSahFahGahDahDahDahDahDahHahIahDahJahKahLagQahIagFaeRahMahNahOaawahQahRahSahTahUahVahWahXaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaadradradradradraafacGaafadradradradradraaaaaRaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGaafadsadsadsadsadsaafaegaafadsadsadsadsadsaafaaGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaahYahZahZahZaiaaaaaafahyabbabaacOacZaeRacLacraigahDabZabmabHailaimainaioaipaipaipaioaipaiqairaipairaipaipaglairaisaitaiuaivaiwaixaiyaizaiAaiBahuahvahwabIaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHaaaaafaaaaafaafaaaaaaacGaaaaaaaafaaaaaaaafaaaaaGaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index 9a746a952f6..ca4c3bb6d91 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -37,6 +37,7 @@ var/list/tdomeadmin = list() var/list/prisonsecuritywarp = list() //prison security goes to these var/list/prisonwarped = list() //list of players already warped var/list/blobstart = list() +var/list/secequipment = list() var/list/global_activeturfs //away missions diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index a4c1fac1f53..38eb5e8abc0 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -76,6 +76,7 @@ var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors var/changeling_scaling_coeff = 7 //how much does the amount of players get divided by to determine changelings + var/security_scaling_coeff = 8 //how much does the amount of players get divided by to determine open security officer positions var/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other var/allow_latejoin_antagonists = 0 // If late-joining players can be traitor/changeling @@ -344,6 +345,8 @@ config.traitor_scaling_coeff = text2num(value) if("changeling_scaling_coeff") config.changeling_scaling_coeff = text2num(value) + if("security_scaling_coeff") + config.security_scaling_coeff = text2num(value) if("probability") var/prob_pos = findtext(value, " ") var/prob_name = null diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 960908c55f5..df404d38fc1 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -152,8 +152,8 @@ Security Officer department_head = list("Head of Security") department_flag = ENGSEC faction = "Station" - total_positions = 5 - spawn_positions = 5 + total_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions() + spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions() supervisors = "the head of security, and the head of your assigned department (if applicable)" selection_color = "#ffeeee" minimal_player_age = 7 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index dc1088e55a3..c01c0a08ba3 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -189,6 +189,9 @@ var/global/datum/controller/occupations/job_master Debug("DO, Len: [unassigned.len]") if(unassigned.len == 0) return 0 + //Scale number of open security officer slots to population + setup_officer_positions() + //Shuffle players and jobs unassigned = shuffle(unassigned) @@ -308,6 +311,24 @@ var/global/datum/controller/occupations/job_master return 1 +/datum/controller/occupations/proc/setup_officer_positions() + var/officer_positions = 5 //Number of open security officer positions at round start + + if(config.security_scaling_coeff > 0) + officer_positions = min(12, max(5, (unassigned.len/config.security_scaling_coeff))) + var/datum/job/J = job_master.GetJob("Security Officer") + if(J || J.spawn_positions > 0) + Debug("Setting open security officer positions to [officer_positions]") + J.total_positions = officer_positions + J.spawn_positions = officer_positions + for(var/i=officer_positions-5, i>1, i--) //Spawn some extra lockers if we don't have enough + if(secequipment.len) + var/spawnloc = secequipment[1] + new /obj/structure/closet/secure_closet/security(spawnloc) + secequipment -= spawnloc + else //We ran out of spare locker spawns! + break + /datum/controller/occupations/proc/LoadJobs(jobsfile) //ran during round setup, reads info from jobs.txt -- Urist if(!config.load_jobs_from_txt) return 0 diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index bd605edfc5a..377d7777b0f 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -55,7 +55,10 @@ blobstart += loc qdel(src) return - + if("secequipment") + secequipment += loc + qdel(src) + return if("xeno_spawn") xeno_spawn += loc qdel(src) diff --git a/config/game_options.txt b/config/game_options.txt index b9ca7e763ca..44b3b968ccf 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -114,6 +114,11 @@ SHUTTLE_REFUEL_DELAY 12000 TRAITOR_SCALING_COEFF 6 CHANGELING_SCALING_COEFF 7 +## Variables calculate how number of open security officer positions will scale to population. +## Used as (Officers = Population / Coeff) +## Set to 0 to disable scaling and use default numbers instead. +SECURITY_SCALING_COEFF 8 + ## Uncomment to prohibit jobs that start with loyalty ## implants from being most antagonists. #PROTECT_ROLES_FROM_ANTAGONIST From 1d2ae48cf3854cc9dcddaaac38430024cc6f9b41 Mon Sep 17 00:00:00 2001 From: paprka Date: Fri, 20 Jun 2014 03:13:27 -0700 Subject: [PATCH 02/17] initial --- code/modules/mining/equipment_locker.dm | 20 +++++++++--------- code/modules/mining/mine_turfs.dm | 27 +++++++++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index f86ed7fce72..c9b5261763f 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -160,18 +160,18 @@ new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/cigarette/cigar/havana, 100), new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 150), new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 150), - new /datum/data/mining_equipment("Stimulant pills", /obj/item/weapon/storage/pill_bottle/stimulant, 350), - new /datum/data/mining_equipment("Alien toy", /obj/item/clothing/mask/facehugger/toy, 250), - new /datum/data/mining_equipment("Laser pointer", /obj/item/device/laser_pointer, 500), - new /datum/data/mining_equipment("Point card", /obj/item/weapon/card/mining_point_card, 500), - new /datum/data/mining_equipment("Lazarus injector", /obj/item/weapon/lazarus_injector, 1000), - new /datum/data/mining_equipment("Space cash", /obj/item/weapon/spacecash/c1000, 5000), - new /datum/data/mining_equipment("Sonic jackhammer", /obj/item/weapon/pickaxe/jackhammer, 500), - new /datum/data/mining_equipment("Mining drone", /mob/living/simple_animal/hostile/mining_drone/, 500), - new /datum/data/mining_equipment("Jaunter", /obj/item/device/wormhole_jaunter, 200), + new /datum/data/mining_equipment("Alien Toy", /obj/item/clothing/mask/facehugger/toy, 500), + new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 500), + new /datum/data/mining_equipment("Stimulant Pills", /obj/item/weapon/storage/pill_bottle/stimulant, 350), + new /datum/data/mining_equipment("Sonic Jackhammer", /obj/item/weapon/pickaxe/jackhammer, 500), + new /datum/data/mining_equipment("Mining Drone", /mob/living/simple_animal/hostile/mining_drone/, 500), new /datum/data/mining_equipment("Resonator", /obj/item/weapon/resonator, 750), - new /datum/data/mining_equipment("Kinetic accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 1000), + new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 1000), new /datum/data/mining_equipment("Jetpack", /obj/item/weapon/tank/jetpack/carbondioxide/mining, 2000), + new /datum/data/mining_equipment("Jaunter", /obj/item/device/wormhole_jaunter, 200), + new /datum/data/mining_equipment("Lazarus Injector", /obj/item/weapon/lazarus_injector, 1000), + new /datum/data/mining_equipment("Point Card", /obj/item/weapon/card/mining_point_card, 500), + new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c1000, 5000), ) /datum/data/mining_equipment/ diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 846ec298675..79e2153eccb 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -72,8 +72,8 @@ /turf/simulated/mineral/random name = "Mineral deposit" icon_state = "rock" - var/mineralSpawnChanceList = list("Uranium" = 1, "Diamond" = 1, "Gold" = 1, "Silver" = 1, "Plasma" = 1, "Iron" = 50, "Gibtonite" = 4/*, "Adamantine" =5*/, "Cave" = 2)//Currently, Adamantine won't spawn as it has no uses. -Durandan - var/mineralChance = 10 //means 10% chance of this plot changing to a mineral deposit + var/mineralSpawnChanceList = list("Uranium" = 18, "Diamond" = 5, "Gold" = 12, "Silver" = 18, "Plasma" = 25, "Iron" = 40, "Gibtonite" = 2/*, "Adamantine" =5*/, "Cave" = 2)//Currently, Adamantine won't spawn as it has no uses. -Durandan + var/mineralChance = 17 /turf/simulated/mineral/random/New() ..() @@ -99,6 +99,8 @@ new/turf/simulated/floor/plating/asteroid/airless/cave(src) if("Gibtonite") M = new/turf/simulated/mineral/gibtonite(src) + if("Clown") + M = new/turf/simulated/mineral/clown(src) /*if("Adamantine") M = new/turf/simulated/mineral/adamantine(src)*/ if(M) @@ -109,16 +111,25 @@ /turf/simulated/mineral/random/high_chance icon_state = "rock_highchance" mineralChance = 25 - mineralSpawnChanceList = list("Uranium" = 35, "Diamond" = 10, "Gold" = 35, "Silver" = 35, "Plasma" = 35, "Iron" = 50) + mineralSpawnChanceList = list("Uranium" = 35, "Diamond" = 30, "Gold" = 45, "Silver" = 50, "Plasma" = 30) /turf/simulated/mineral/random/high_chance/New() icon_state = "rock" ..() +/turf/simulated/mineral/random/clown + icon_state = "rock_highchance" + mineralChance = 25 + mineralSpawnChanceList = list("Clown" = 50) + +/turf/simulated/mineral/random/clown/New() + icon_state = "rock" + ..() + /turf/simulated/mineral/random/low_chance icon_state = "rock_lowchance" - mineralChance = 5 - mineralSpawnChanceList = list("Uranium" = 1, "Diamond" = 1, "Gold" = 1, "Silver" = 1, "Plasma" = 1, "Iron" = 50, "Gibtonite" = 4) + mineralChance = 8 + mineralSpawnChanceList = list("Uranium" = 8, "Diamond" = 2, "Gold" = 4, "Silver" = 8, "Plasma" = 20, "Iron" = 40, "Gibtonite" = 1) /turf/simulated/mineral/random/low_chance/New() icon_state = "rock" @@ -168,7 +179,7 @@ name = "Plasma deposit" icon_state = "rock_Plasma" mineralName = "Plasma" - spreadChance = 5 + spreadChance = 8 spread = 1 hidden = 1 scan_state = "rock_Plasma" @@ -353,7 +364,7 @@ if(prob(30)) if(istype(loc, /area/mine/explored)) return - for(var/atom/A in range(15,T))//Lowers chance of mob clumps + for(var/atom/A in range(30,T))//Lowers chance of mob clumps if(istype(A, /mob/living/simple_animal/hostile/asteroid)) return var/randumb = pickweight(mob_spawn_list) @@ -613,4 +624,4 @@ else if(istype(R.module_state_3,/obj/item/weapon/storage/bag/ore)) src.attackby(R.module_state_3,R) else - return \ No newline at end of file + return From 2161273c797ba4c3ffeece3aab762928a26a59e8 Mon Sep 17 00:00:00 2001 From: paprka Date: Fri, 20 Jun 2014 03:17:57 -0700 Subject: [PATCH 03/17] better --- code/modules/mining/mine_turfs.dm | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 79e2153eccb..97cc7e47ba6 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -72,8 +72,8 @@ /turf/simulated/mineral/random name = "Mineral deposit" icon_state = "rock" - var/mineralSpawnChanceList = list("Uranium" = 18, "Diamond" = 5, "Gold" = 12, "Silver" = 18, "Plasma" = 25, "Iron" = 40, "Gibtonite" = 2/*, "Adamantine" =5*/, "Cave" = 2)//Currently, Adamantine won't spawn as it has no uses. -Durandan - var/mineralChance = 17 + var/mineralSpawnChanceList = list("Uranium" = 18, "Diamond" = 3, "Gold" = 12, "Silver" = 16, "Plasma" = 25, "Iron" = 40, "Gibtonite" = 2/*, "Adamantine" =5*/, "Cave" = 2)//Currently, Adamantine won't spawn as it has no uses. -Durandan + var/mineralChance = 16 /turf/simulated/mineral/random/New() ..() @@ -117,19 +117,10 @@ icon_state = "rock" ..() -/turf/simulated/mineral/random/clown - icon_state = "rock_highchance" - mineralChance = 25 - mineralSpawnChanceList = list("Clown" = 50) - -/turf/simulated/mineral/random/clown/New() - icon_state = "rock" - ..() - /turf/simulated/mineral/random/low_chance icon_state = "rock_lowchance" mineralChance = 8 - mineralSpawnChanceList = list("Uranium" = 8, "Diamond" = 2, "Gold" = 4, "Silver" = 8, "Plasma" = 20, "Iron" = 40, "Gibtonite" = 1) + mineralSpawnChanceList = list("Uranium" = 8, "Diamond" = 2, "Gold" = 4, "Silver" = 6, "Plasma" = 20, "Iron" = 40, "Gibtonite" = 1) /turf/simulated/mineral/random/low_chance/New() icon_state = "rock" @@ -364,7 +355,7 @@ if(prob(30)) if(istype(loc, /area/mine/explored)) return - for(var/atom/A in range(30,T))//Lowers chance of mob clumps + for(var/atom/A in range(20,T))//Lowers chance of mob clumps if(istype(A, /mob/living/simple_animal/hostile/asteroid)) return var/randumb = pickweight(mob_spawn_list) From c21b6b0e55058ca66bd4730532b3887adbc018ce Mon Sep 17 00:00:00 2001 From: paprka Date: Fri, 20 Jun 2014 11:28:48 -0700 Subject: [PATCH 04/17] sample text --- code/modules/clothing/glasses/glasses.dm | 7 ++----- code/modules/research/designs.dm | 15 +++------------ 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 71dfa65a386..41c2835cdc5 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -1,14 +1,11 @@ /obj/item/clothing/glasses/meson name = "Optical Meson Scanner" - desc = "Used for seeing walls, floors, and stuff through anything." + desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." icon_state = "meson" item_state = "glasses" origin_tech = "magnets=2;engineering=2" + darkness_view = 1 vision_flags = SEE_TURFS - -/obj/item/clothing/glasses/meson/advanced - name = "Advanced Optical Meson Scanner" - desc = "More powerful than your standard mesons, these ones make everything appear to be lit extremely brightly." invis_view = SEE_INVISIBLE_MINIMUM /obj/item/clothing/glasses/science diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 5e126658836..e241784124c 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1880,22 +1880,13 @@ datum/design/welding_mask datum/design/mesons name = "Optical Meson Scanners" - desc = "Used for seeing walls, floors, and stuff through anything." + desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." id = "mesons" - req_tech = list("magnets" = 2, "engineering" = 2) + req_tech = list("materials" = 3, "magnets" = 3, "engineering" = 3) build_type = PROTOLATHE - materials = list("$metal" = 50, "$glass" = 50) + materials = list("$metal" = 200, "$glass" = 300, "$plasma" = 100) build_path = /obj/item/clothing/glasses/meson -datum/design/advanced_mesons - name = "Advanced Optical Meson Scanner" - desc = "More powerful than your standard mesons, these ones make everything appear to be lit extremely brightly." - id = "advanced_mesons" - req_tech = list("magnets" = 4, "engineering" = 4) - build_type = PROTOLATHE - materials = list("$metal" = 100, "$glass" = 100) - build_path = /obj/item/clothing/glasses/meson/advanced - datum/design/night_vision_goggles name = "Night Vision Goggles" desc = "Goggles that let you see through darkness unhindered." From aecbf2b0b535913a9ff8c71d46514a7dc4713275 Mon Sep 17 00:00:00 2001 From: ikarrus Date: Tue, 1 Jul 2014 13:46:11 -0600 Subject: [PATCH 05/17] Re-adding missing files from the last merge attempt (+2 squashed commit) Squashed commit: [30c5e29] Re-adding missing files from the last merge attempt [53bcfea] Re-adding missing files from the last merge attempt --- code/game/gamemodes/monkey/monkey.dm | 85 ++ .../mob/living/carbon/human/mutantrace.dm | 22 + .../mob/living/carbon/human/species.dm | 1330 +++++++++++++++++ .../mob/living/carbon/human/species_types.dm | 221 +++ sound/machines/airlockforced.ogg | Bin 0 -> 16204 bytes 5 files changed, 1658 insertions(+) create mode 100644 code/game/gamemodes/monkey/monkey.dm create mode 100644 code/modules/mob/living/carbon/human/mutantrace.dm create mode 100644 code/modules/mob/living/carbon/human/species.dm create mode 100644 code/modules/mob/living/carbon/human/species_types.dm create mode 100644 sound/machines/airlockforced.ogg diff --git a/code/game/gamemodes/monkey/monkey.dm b/code/game/gamemodes/monkey/monkey.dm new file mode 100644 index 00000000000..ef737a86621 --- /dev/null +++ b/code/game/gamemodes/monkey/monkey.dm @@ -0,0 +1,85 @@ +/datum/game_mode/monkey + name = "monkey" + config_tag = "monkey" + antag_flag = BE_REV + + required_players = 20 + required_enemies = 1 + recommended_enemies = 1 + + restricted_jobs = list("Cyborg", "AI") + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + var/carriers_to_make = 1 + var/list/carriers = list() + + var/monkeys_to_win = 0 + var/escaped_monkies = 0 + + var/players_per_carrier = 30 + + +/datum/game_mode/monkey/pre_setup() + carriers_to_make = max(round(num_players()/players_per_carrier, 1), 1) + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs)//Removing robots from the list + if(player.assigned_role == job) + antag_candidates -= player + for(var/j = 0, j < carriers, j++) + if (!antag_candidates.len) + break + var/datum/mind/carrier = pick(antag_candidates) + carriers += carrier + carrier.special_role = "monkey" + log_game("[carrier.key] (ckey) has been selected as a Jungle Fever carrier") + antag_candidates -= carrier + if(!carriers.len) + return 0 + return 1 + + +/datum/game_mode/monkey/announce() + world << "The current game mode is - Monkey!" + world << "One or more crewmembers have been infected with Jungle Fever! Crew: Contain the outbreak. None of the infected monkeys may escape alive to Centcom. \ + Monkeys: Ensure that your kind lives on! Rise up against your captors!" + + +/datum/game_mode/monkey/proc/greet_carrier(var/datum/mind/carrier) + carrier.current << "You are infected by the Jungle Fever patient zero!!" + carrier.current << "You have been planted onto this station by the Animal Rights Consortium." + carrier.current << "Soon the disease will transform you into an ape. Afterwards, you will be able spread the infection to others with a bite." + carrier.current << "While your infection is undetectable, any other infectees will show up on medical equipment." + carrier.current << "Your mission will be deemed a success if any of the live infected monkeys reach Centcom." + return + +/datum/game_mode/monkey/post_setup() + for(var/datum/mind/carriermind in carriers) + greet_carrier(carriermind) + var/datum/disease/transformation/jungle_fever/J = new /datum/disease/transformation/jungle_fever + J.hidden = list(1, 1)//Starting disease is hidden from medical equipment + carriermind.current.contract_disease(J, 1, 0) + ..() + +/datum/game_mode/monkey/proc/check_monkey_victory() + for(var/mob/living/carbon/monkey/M in living_mob_list) + if (M.has_disease(/datum/disease/transformation/jungle_fever)) + var/area/A = get_area(M) + if(is_type_in_list(A, centcom_areas)) + escaped_monkies++ + if(escaped_monkies >= monkeys_to_win) + return 0 + else + return 1 + + +/datum/game_mode/monkey/declare_completion() + if(!check_monkey_victory()) + feedback_set_details("round_end_result","win - monkey win") + feedback_set("round_end_result",escaped_monkies) + world << "\red The monkies have overthrown their captors! Eeek eeeek!!" + else + feedback_set_details("round_end_result","loss - staff stopped the monkies") + feedback_set("round_end_result",escaped_monkies) + world << "\red The staff managed to contain the monkey infestation!" diff --git a/code/modules/mob/living/carbon/human/mutantrace.dm b/code/modules/mob/living/carbon/human/mutantrace.dm new file mode 100644 index 00000000000..30615bb624c --- /dev/null +++ b/code/modules/mob/living/carbon/human/mutantrace.dm @@ -0,0 +1,22 @@ +var/global/list/colored_mutraces = list( // these mutantraces are affected by mutant color + "lizard", + "plant", + "pod", + "slime", + "jelly", + "golem" +) + +var/global/list/mutants_with_eyes = list( // these mutantraces have eyes + "lizard", + "plant", + "pod", + "jelly", +) + +/mob/living/carbon/human/proc/check_mutrace(var/mutneeded = "mut1", var/mutneededalt = "mut2") + if(dna) + if(dna.mutantrace == mutneeded || dna.mutantrace == mutneededalt) + return 1 + + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm new file mode 100644 index 00000000000..97143b147b1 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species.dm @@ -0,0 +1,1330 @@ +// This code handles different species in the game. + +#define SPECIES_LAYER 23 +#define BODY_LAYER 22 +#define HAIR_LAYER 8 + +#define TINT_IMPAIR 2 +#define TINT_BLIND 3 + +#define HUMAN_MAX_OXYLOSS 3 +#define HUMAN_CRIT_MAX_OXYLOSS ( (last_tick_duration) /3) + +#define HEAT_DAMAGE_LEVEL_1 2 +#define HEAT_DAMAGE_LEVEL_2 3 +#define HEAT_DAMAGE_LEVEL_3 8 + +#define COLD_DAMAGE_LEVEL_1 0.5 +#define COLD_DAMAGE_LEVEL_2 1.5 +#define COLD_DAMAGE_LEVEL_3 3 + +#define HEAT_GAS_DAMAGE_LEVEL_1 2 +#define HEAT_GAS_DAMAGE_LEVEL_2 4 +#define HEAT_GAS_DAMAGE_LEVEL_3 8 + +#define COLD_GAS_DAMAGE_LEVEL_1 0.5 +#define COLD_GAS_DAMAGE_LEVEL_2 1.5 +#define COLD_GAS_DAMAGE_LEVEL_3 3 + +/datum/species + var/id = null // if the game needs to manually check your race to do something not included in a proc here, it will use this + var/name = null // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever + var/roundstart = 0 // can this mob be chosen at roundstart? (assuming the config option is checked?) + var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race + + var/eyes = "eyes" // which eyes the race uses. at the moment, the only types of eyes are "eyes" (regular eyes) and "jelleyes" (three eyes) + var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows + var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color + var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent. + var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans) + + var/list/no_equip = list() // slots the race can't equip stuff to + var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids + + var/say_mod = "says" // affects the speech message + + var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster + var/armor = 0 // overall defense for the race... or less defense, if it's negative. + var/brutemod = 1 // multiplier for brute damage + var/burnmod = 1 // multiplier for burn damage + var/coldmod = 1 // multiplier for cold damage + var/heatmod = 1 // multiplier for heat damage + var/punchmod = 0 // adds to the punch damage + + var/invis_sight = SEE_INVISIBLE_LIVING + var/darksight = 2 + + // species flags. these can be found in flags.dm + var/list/specflags = list() + + var/attack_verb = "punch" // punch-specific attack verb + var/sound/attack_sound = 'sound/weapons/punch1.ogg' + var/sound/miss_sound = 'sound/weapons/punchmiss.ogg' + + var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species + + /////////// + // PROCS // + /////////// + + proc/update_base_icon_state(var/mob/living/carbon/human/H) + if(HUSK in H.mutations) + H.remove_overlay(SPECIES_LAYER) // races lose their color + return "husk" + else if(sexes) + if(use_skintones) + return "[H.skin_tone]_[(H.gender == FEMALE) ? "f" : "m"]" + else + return "[id]_[(H.gender == FEMALE) ? "f" : "m"]" + else + return "[id]" + + proc/update_color(var/mob/living/carbon/human/H) + H.remove_overlay(SPECIES_LAYER) + + var/image/standing + + var/g = (H.gender == FEMALE) ? "f" : "m" + + if(MUTCOLORS in specflags) + var/image/spec_base + if(sexes) + spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_[g]_s", "layer" = -SPECIES_LAYER) + else + spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_s", "layer" = -SPECIES_LAYER) + if(!config.mutant_colors) + H.dna.mutant_color = default_color + spec_base.color = "#[H.dna.mutant_color]" + standing = spec_base + + if(standing) + H.overlays_standing[SPECIES_LAYER] = standing + + H.apply_overlay(SPECIES_LAYER) + + proc/handle_hair(var/mob/living/carbon/human/H) + H.remove_overlay(HAIR_LAYER) + + var/datum/sprite_accessory/S + var/list/standing = list() + + if(H.facial_hair_style && FACEHAIR in specflags) + S = facial_hair_styles_list[H.facial_hair_style] + if(S) + var/image/img_facial_s + + img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + if(hair_color) + if(hair_color == "mutcolor") + if(!config.mutant_colors) + img_facial_s.color = "#" + default_color + else + img_facial_s.color = "#" + H.dna.mutant_color + else + img_facial_s.color = "#" + hair_color + else + img_facial_s.color = "#" + H.facial_hair_color + img_facial_s.alpha = hair_alpha + + standing += img_facial_s + + //Applies the debrained overlay if there is no brain + if(!H.getorgan(/obj/item/organ/brain)) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) + + else if(H.hair_style && HAIR in specflags) + S = hair_styles_list[H.hair_style] + if(S) + var/image/img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + if(hair_color) + if(hair_color == "mutcolor") + if(!config.mutant_colors) + img_hair_s.color = "#" + default_color + else + img_hair_s.color = "#" + H.dna.mutant_color + else + img_hair_s.color = "#" + hair_color + else + img_hair_s.color = "#" + H.hair_color + img_hair_s.alpha = hair_alpha + + standing += img_hair_s + + if(standing.len) + H.overlays_standing[HAIR_LAYER] = standing + + H.apply_overlay(HAIR_LAYER) + + return + + proc/handle_body(var/mob/living/carbon/human/H) + H.remove_overlay(BODY_LAYER) + + var/list/standing = list() + + // lipstick + if(H.lip_style && LIPS in specflags) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]_s", "layer" = -BODY_LAYER) + + // eyes + if(EYECOLOR in specflags) + var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[eyes]_s", "layer" = -BODY_LAYER) + img_eyes_s.color = "#" + H.eye_color + standing += img_eyes_s + + //Underwear + if(H.underwear) + var/datum/sprite_accessory/underwear/U = underwear_all[H.underwear] + if(U) + standing += image("icon"=U.icon, "icon_state"="[U.icon_state]_s", "layer"=-BODY_LAYER) + + if(standing.len) + H.overlays_standing[BODY_LAYER] = standing + + H.apply_overlay(BODY_LAYER) + + return + + proc/spec_life(var/mob/living/carbon/human/H) + return + + proc/spec_death(var/gibbed, var/mob/living/carbon/human/H) + return + + proc/auto_equip(var/mob/living/carbon/human/H) + // handles the equipping of species-specific gear + return + + proc/can_equip(var/obj/item/I, var/slot, var/disable_warning, var/mob/living/carbon/human/H) + if(slot in no_equip) + if(!(type in I.species_exception)) + return 0 + + switch(slot) + if(slot_l_hand) + if(H.l_hand) + return 0 + return 1 + if(slot_r_hand) + if(H.r_hand) + return 0 + return 1 + if(slot_wear_mask) + if(H.wear_mask) + return 0 + if( !(I.slot_flags & SLOT_MASK) ) + return 0 + return 1 + if(slot_back) + if(H.back) + return 0 + if( !(I.slot_flags & SLOT_BACK) ) + return 0 + return 1 + if(slot_wear_suit) + if(H.wear_suit) + return 0 + if( !(I.slot_flags & SLOT_OCLOTHING) ) + return 0 + return 1 + if(slot_gloves) + if(H.gloves) + return 0 + if( !(I.slot_flags & SLOT_GLOVES) ) + return 0 + return 1 + if(slot_shoes) + if(H.shoes) + return 0 + if( !(I.slot_flags & SLOT_FEET) ) + return 0 + return 1 + if(slot_belt) + if(H.belt) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_BELT) ) + return + return 1 + if(slot_glasses) + if(H.glasses) + return 0 + if( !(I.slot_flags & SLOT_EYES) ) + return 0 + return 1 + if(slot_head) + if(H.head) + return 0 + if( !(I.slot_flags & SLOT_HEAD) ) + return 0 + return 1 + if(slot_ears) + if(H.ears) + return 0 + if( !(I.slot_flags & SLOT_EARS) ) + return 0 + return 1 + if(slot_w_uniform) + if(H.w_uniform) + return 0 + if( !(I.slot_flags & SLOT_ICLOTHING) ) + return 0 + return 1 + if(slot_wear_id) + if(H.wear_id) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_ID) ) + return 0 + return 1 + if(slot_l_store) + if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them. + return 0 + if(H.l_store) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + return 1 + if(slot_r_store) + if(I.flags & NODROP) + return 0 + if(H.r_store) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return 0 + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + return 1 + return 0 + if(slot_s_store) + if(I.flags & NODROP) + return 0 + if(H.s_store) + return 0 + if(!H.wear_suit) + if(!disable_warning) + H << "You need a suit before you can attach this [I.name]." + return 0 + if(!H.wear_suit.allowed) + if(!disable_warning) + H << "You somehow have a suit with no defined allowed items for suit storage, stop that." + return 0 + if(I.w_class > 4) + if(!disable_warning) + H << "The [I.name] is too big to attach." //should be src? + return 0 + if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, H.wear_suit.allowed) ) + return 1 + return 0 + if(slot_handcuffed) + if(H.handcuffed) + return 0 + if(!istype(I, /obj/item/weapon/handcuffs)) + return 0 + return 1 + if(slot_legcuffed) + if(H.legcuffed) + return 0 + if(!istype(I, /obj/item/weapon/legcuffs)) + return 0 + return 1 + if(slot_in_backpack) + if (H.back && istype(H.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = H.back + if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class) + return 1 + return 0 + return 0 //Unsupported slot + + proc/before_equip_job(var/datum/job/J, var/mob/living/carbon/human/H) + return + + proc/after_equip_job(var/datum/job/J, var/mob/living/carbon/human/H) + return + + proc/handle_chemicals(var/datum/reagent/chem, var/mob/living/carbon/human/H) + return 0 + + proc/handle_speech(var/message, var/mob/living/carbon/human/H) + return message + + //////// + //LIFE// + //////// + + proc/handle_chemicals_in_body(var/mob/living/carbon/human/H) + if(H.reagents) H.reagents.metabolize(H) + + //The fucking FAT mutation is the dumbest shit ever. It makes the code so difficult to work with + if(FAT in H.mutations) + if(H.overeatduration < 100) + H << "You feel fit again!" + H.mutations -= FAT + H.update_inv_w_uniform(0) + H.update_inv_wear_suit() + else + if(H.overeatduration > 500) + H << "You suddenly feel blubbery!" + H.mutations |= FAT + H.update_inv_w_uniform(0) + H.update_inv_wear_suit() + + // nutrition decrease + if (H.nutrition > 0 && H.stat != 2) + H.nutrition = max (0, H.nutrition - HUNGER_FACTOR) + + if (H.nutrition > 450) + if(H.overeatduration < 600) //capped so people don't take forever to unfat + H.overeatduration++ + else + if(H.overeatduration > 1) + H.overeatduration -= 2 //doubled the unfat rate + + if (H.drowsyness) + H.drowsyness-- + H.eye_blurry = max(2, H.eye_blurry) + if (prob(5)) + H.sleeping += 1 + H.Paralyse(5) + + H.confused = max(0, H.confused - 1) + // decrement dizziness counter, clamped to 0 + if(H.resting) + H.dizziness = max(0, H.dizziness - 15) + H.jitteriness = max(0, H.jitteriness - 15) + else + H.dizziness = max(0, H.dizziness - 3) + H.jitteriness = max(0, H.jitteriness - 3) + + H.updatehealth() + + return + + proc/handle_vision(var/mob/living/carbon/human/H) + if( H.stat == DEAD ) + H.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + H.see_in_dark = 8 + if(!H.druggy) H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else + H.sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) + var/see_temp = H.see_invisible + H.see_invisible = invis_sight + H.see_in_dark = darksight + + if(XRAY in H.mutations) + H.sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + H.see_in_dark = 8 + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + if(H.seer) + H.see_invisible = SEE_INVISIBLE_OBSERVER + + if(H.mind && H.mind.changeling) + H.hud_used.lingchemdisplay.invisibility = 0 + H.hud_used.lingchemdisplay.maptext = "
[H.mind.changeling.chem_charges]
" + else + H.hud_used.lingchemdisplay.invisibility = 101 + + if(istype(H.wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)) + var/obj/item/clothing/mask/gas/voice/space_ninja/O = H.wear_mask + switch(O.mode) + if(0) + var/target_list[] = list() + for(var/mob/living/target in oview(H)) + if( target.mind&&(target.mind.special_role||issilicon(target)) )//They need to have a mind. + target_list += target + if(target_list.len)//Everything else is handled by the ninja mask proc. + O.assess_targets(target_list, H) + H.see_invisible = SEE_INVISIBLE_LIVING + if(1) + H.see_in_dark = 5 + H.see_invisible = SEE_INVISIBLE_LIVING + if(2) + H.sight |= SEE_MOBS + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + if(3) + H.sight |= SEE_TURFS + H.see_invisible = SEE_INVISIBLE_LIVING + + if(H.glasses) + if(istype(H.glasses, /obj/item/clothing/glasses)) + var/obj/item/clothing/glasses/G = H.glasses + H.sight |= G.vision_flags + H.see_in_dark = G.darkness_view + H.see_invisible = G.invis_view + if(G.hud) + G.process_hud(H) + + if(H.druggy) //Override for druggy + H.see_invisible = see_temp + + if(H.see_override) //Override all + H.see_invisible = H.see_override + + // This checks how much the mob's eyewear impairs their vision + if(H.tinttotal >= TINT_IMPAIR) + if(tinted_weldhelh) + if(H.tinttotal >= TINT_BLIND) + H.blinded = 1 // You get the sudden urge to learn to play keyboard + H.client.screen += global_hud.darkMask + else + H.client.screen += global_hud.darkMask + + if(H.blind) + if(H.blinded) H.blind.layer = 18 + else H.blind.layer = 0 + + if( H.disabilities & NEARSIGHTED && !istype(H.glasses, /obj/item/clothing/glasses/regular) ) + H.client.screen += global_hud.vimpaired + if(H.eye_blurry) H.client.screen += global_hud.blurry + if(H.druggy) H.client.screen += global_hud.druggy + + + if(H.eye_stat > 20) + if(H.eye_stat > 30) H.client.screen += global_hud.darkMask + else H.client.screen += global_hud.vimpaired + + return 1 + + proc/handle_hud_icons(var/mob/living/carbon/human/H) + if(H.healths) + if(H.stat == DEAD) + H.healths.icon_state = "health7" + else + switch(H.hal_screwyhud) + if(1) H.healths.icon_state = "health6" + if(2) H.healths.icon_state = "health7" + else + switch(H.health - H.staminaloss) + if(100 to INFINITY) H.healths.icon_state = "health0" + if(80 to 100) H.healths.icon_state = "health1" + if(60 to 80) H.healths.icon_state = "health2" + if(40 to 60) H.healths.icon_state = "health3" + if(20 to 40) H.healths.icon_state = "health4" + if(0 to 20) H.healths.icon_state = "health5" + else H.healths.icon_state = "health6" + + if(H.nutrition_icon) + switch(H.nutrition) + if(450 to INFINITY) H.nutrition_icon.icon_state = "nutrition0" + if(350 to 450) H.nutrition_icon.icon_state = "nutrition1" + if(250 to 350) H.nutrition_icon.icon_state = "nutrition2" + if(150 to 250) H.nutrition_icon.icon_state = "nutrition3" + else H.nutrition_icon.icon_state = "nutrition4" + + if(H.pressure) + H.pressure.icon_state = "pressure[H.pressure_alert]" + + if(H.pullin) + if(H.pulling) H.pullin.icon_state = "pull" + else H.pullin.icon_state = "pull0" +// if(rest) //Not used with new UI +// if(resting || lying || sleeping) rest.icon_state = "rest1" +// else rest.icon_state = "rest0" + if(H.toxin) + if(H.hal_screwyhud == 4 || H.toxins_alert) H.toxin.icon_state = "tox1" + else H.toxin.icon_state = "tox0" + if(H.oxygen) + if(H.hal_screwyhud == 3 || H.oxygen_alert) H.oxygen.icon_state = "oxy1" + else H.oxygen.icon_state = "oxy0" + if(H.fire) + if(H.fire_alert) H.fire.icon_state = "fire[H.fire_alert]" //fire_alert is either 0 if no alert, 1 for cold and 2 for heat. + else H.fire.icon_state = "fire0" + + if(H.bodytemp) + if(!(HEATRES in specflags)) + switch(H.bodytemperature) //310.055 optimal body temp + if(370 to INFINITY) H.bodytemp.icon_state = "temp4" + if(350 to 370) H.bodytemp.icon_state = "temp3" + if(335 to 350) H.bodytemp.icon_state = "temp2" + switch(H.bodytemperature) + if(320 to 335) H.bodytemp.icon_state = "temp1" + if(300 to 320) H.bodytemp.icon_state = "temp0" + if(295 to 300) H.bodytemp.icon_state = "temp-1" + if(!(COLDRES in specflags)) + switch(H.bodytemperature) + if(280 to 295) H.bodytemp.icon_state = "temp-2" + if(260 to 280) H.bodytemp.icon_state = "temp-3" + if(-INFINITY to 260) H.bodytemp.icon_state = "temp-4" + + return 1 + + proc/handle_mutations_and_radiation(var/mob/living/carbon/human/H) + if(H.getFireLoss()) + if((COLD_RESISTANCE in H.mutations) || (prob(1))) + H.heal_organ_damage(0,1) + + if ((HULK in H.mutations) && H.health <= 25) + H.mutations.Remove(HULK) + H.update_mutations() //update our mutation overlays + H << "You suddenly feel very weak." + H.Weaken(3) + H.emote("collapse") + + if (H.radiation && !(RADIMMUNE in specflags)) + if (H.radiation > 100) + H.radiation = 100 + H.Weaken(10) + H << "You feel weak." + H.emote("collapse") + + if (H.radiation < 0) + H.radiation = 0 + + else + switch(H.radiation) + if(1 to 49) + H.radiation-- + if(prob(25)) + H.adjustToxLoss(1) + H.updatehealth() + + if(50 to 74) + H.radiation -= 2 + H.adjustToxLoss(1) + if(prob(5)) + H.radiation -= 5 + H.Weaken(3) + H << "You feel weak." + H.emote("collapse") + if(prob(15)) + if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || HAIR in specflags) + H << "Your hair starts to fall out in clumps..." + spawn(50) + H.facial_hair_style = "Shaved" + H.hair_style = "Bald" + H.update_hair() + H.updatehealth() + + if(75 to 100) + H.radiation -= 3 + H.adjustToxLoss(3) + if(prob(1)) + H << "You mutate!" + randmutb(H) + domutcheck(H,null) + H.emote("gasp") + H.updatehealth() + + //////////////// + // MOVE SPEED // + //////////////// + + proc/movement_delay(var/mob/living/carbon/human/H) + var/mspeed = 0 + + if(!has_gravity(H)) + return -1 //It's hard to be slowed down in space by... anything + else if(H.status_flags & GOTTAGOFAST) + return -1 + + mspeed = 0 + var/health_deficiency = (100 - H.health + H.staminaloss) + if(health_deficiency >= 40) + mspeed += (health_deficiency / 25) + + var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80 + if(hungry >= 70) + mspeed += hungry / 50 + + if(H.wear_suit) + mspeed += H.wear_suit.slowdown + if(H.shoes) + mspeed += H.shoes.slowdown + if(H.back) + mspeed += H.back.slowdown + + if(FAT in H.mutations) + mspeed += 1.5 + if(H.bodytemperature < 283.222) + mspeed += (283.222 - H.bodytemperature) / 10 * 1.75 + + mspeed += speedmod + + return mspeed + + ////////////////// + // ATTACK PROCS // + ////////////////// + + proc/spec_attack_hand(var/mob/living/carbon/human/M, var/mob/living/carbon/human/H) + if((M != H) && H.check_shields(0, M.name)) + add_logs(M, H, "attempted to touch") + H.visible_message("[M] attempted to touch [H]!") + return 0 + + switch(M.a_intent) + if("help") + if(H.health >= 0) + H.help_shake_act(M) + if(H != M) + add_logs(M, H, "shaked") + return 1 + + //CPR + if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) + M << "Remove your mask!" + return 0 + if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) + M << "Remove their mask!" + return 0 + + if(H.cpr_time < world.time + 30) + add_logs(H, M, "CPRed") + H.visible_message("[M] is trying to perform CPR on [H]!") + if(!do_mob(M, H)) + return 0 + if((H.health >= -99 && H.health <= 0)) + H.cpr_time = world.time + var/suff = min(H.getOxyLoss(), 7) + H.adjustOxyLoss(-suff) + H.updatehealth() + M.visible_message("[M] performs CPR on [H]!") + H << "You feel a breath of fresh air enter your lungs. It feels good." + + if("grab") + if(M == H || H.anchored) + return 0 + + add_logs(M, H, "grabbed", addition="passively") + + if(H.w_uniform) + H.w_uniform.add_fingerprint(M) + + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, H) + if(H.buckled) + M << "You cannot grab [H], \he is buckled in!" + if(!G) //the grab will delete itself in New if affecting is anchored + return + M.put_in_active_hand(G) + G.synch() + H.LAssailant = M + + playsound(H.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + H.visible_message("[M] has grabbed [H] passively!") + return 1 + + if("harm") + add_logs(M, H, "punched") + + var/atk_verb = "punch" + if(H.lying) + atk_verb = "kick" + else if(M.dna) + atk_verb = M.dna.species.attack_verb + + var/damage = rand(0, 9) + damage += punchmod + + if(!damage) + if(M.dna) + playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1) + else + playsound(H.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + + H.visible_message("[M] has attempted to [atk_verb] [H]!") + return 0 + + + var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting)) + var/armor_block = H.run_armor_check(affecting, "melee") + + if(HULK in M.mutations) + damage += 5 + + if(M.dna) + playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1) + else + playsound(H.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) + + + H.visible_message("[M] has [atk_verb]ed [H]!", \ + "[M] has [atk_verb]ed [H]!") + + H.apply_damage(damage, BRUTE, affecting, armor_block) + if((H.stat != DEAD) && damage >= 9) + H.visible_message("[M] has weakened [H]!", \ + "[M] has weakened [H]!") + H.apply_effect(4, WEAKEN, armor_block) + H.forcesay(hit_appends) + else if(H.lying) + H.forcesay(hit_appends) + + if("disarm") + add_logs(M, H, "disarmed") + + if(H.w_uniform) + H.w_uniform.add_fingerprint(M) + var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting)) + var/randn = rand(1, 100) + if(randn <= 25) + H.apply_effect(2, WEAKEN, H.run_armor_check(affecting, "melee")) + playsound(H, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + H.visible_message("[M] has pushed [H]!", + "[M] has pushed [H]!") + H.forcesay(hit_appends) + return + + var/talked = 0 // BubbleWrap + + if(randn <= 60) + //BubbleWrap: Disarming breaks a pull + if(H.pulling) + H.visible_message("[M] has broken [H]'s grip on [H.pulling]!") + talked = 1 + H.stop_pulling() + + //BubbleWrap: Disarming also breaks a grab - this will also stop someone being choked, won't it? + if(istype(H.l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/lgrab = H.l_hand + if(lgrab.affecting) + H.visible_message("[M] has broken [H]'s grip on [lgrab.affecting]!") + talked = 1 + spawn(1) + qdel(lgrab) + if(istype(H.r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/rgrab = H.r_hand + if(rgrab.affecting) + H.visible_message("[M] has broken [H]'s grip on [rgrab.affecting]!") + talked = 1 + spawn(1) + qdel(rgrab) + //End BubbleWrap + + if(!talked) //BubbleWrap + if(H.drop_item()) + H.visible_message("[M] has disarmed [H]!", \ + "[M] has disarmed [H]!") + playsound(H, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + return + + + playsound(H, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + H.visible_message("[M] attempted to disarm [H]!", \ + "[M] attemped to disarm [H]!") + return + + proc/spec_attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone, var/obj/item/organ/limb/affecting, var/hit_area, var/intent, var/obj/item/organ/limb/target_limb, target_area, var/mob/living/carbon/human/H) + // Allows you to put in item-specific reactions based on species + if((user != H) && H.check_shields(I.force, "the [I.name]")) + return 0 + + if(I.attack_verb && I.attack_verb.len) + H.visible_message("[H] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!", \ + "[H] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!") + else if(I.force) + H.visible_message("[H] has been attacked in the [hit_area] with [I] by [user]!", \ + "[H] has been attacked in the [hit_area] with [I] by [user]!") + else + return 0 + + var/armor = H.run_armor_check(affecting, "melee", "Your armour has protected your [hit_area].", "Your armour has softened a hit to your [hit_area].") + if(armor >= 100) return 0 + var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) + + apply_damage(I.force, I.damtype, affecting, armor, H) + + var/bloody = 0 + if(((I.damtype == BRUTE) && prob(25 + (I.force * 2)))) + if(affecting.status == ORGAN_ORGANIC) + I.add_blood(H) //Make the weapon bloody, not the person. + if(prob(I.force * 2)) //blood spatter! + bloody = 1 + var/turf/location = H.loc + if(istype(location, /turf/simulated)) + location.add_blood(H) + if(get_dist(H, H) <= 1) //people with TK won't get smeared with blood + if(H.wear_suit) + H.wear_suit.add_blood(H) + H.update_inv_wear_suit(0) //updates mob overlays to show the new blood (no refresh) + else if(H.w_uniform) + H.w_uniform.add_blood(H) + H.update_inv_w_uniform(0) //updates mob overlays to show the new blood (no refresh) + if (H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + G.add_blood(H) + else + H.add_blood(H) + H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves + + + switch(hit_area) + if("head") //Harder to score a stun but if you do it lasts a bit longer + if(H.stat == CONSCIOUS && prob(I.force) && armor < 50) + H.visible_message("[H] has been knocked unconscious!", \ + "[H] has been knocked unconscious!") + H.apply_effect(20, PARALYZE, armor) + if(H != user && I.damtype == BRUTE) + ticker.mode.remove_revolutionary(H.mind) + + if(bloody) //Apply blood + if(H.wear_mask) + H.wear_mask.add_blood(H) + H.update_inv_wear_mask(0) + if(H.head) + H.head.add_blood(H) + H.update_inv_head(0) + if(H.glasses && prob(33)) + H.glasses.add_blood(H) + H.update_inv_glasses(0) + + if("chest") //Easier to score a stun but lasts less time + if(H.stat == CONSCIOUS && prob(I.force + 10)) + H.visible_message("[H] has been knocked down!", \ + "[H] has been knocked down!") + H.apply_effect(5, WEAKEN, armor) + + if(bloody) + if(H.wear_suit) + H.wear_suit.add_blood(H) + H.update_inv_wear_suit(0) + if(H.w_uniform) + H.w_uniform.add_blood(H) + H.update_inv_w_uniform(0) + + if(Iforce > 10 || Iforce >= 5 && prob(33)) + H.forcesay(hit_appends) //forcesay checks stat already. + return + + proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone, var/mob/living/carbon/human/H) + H.apply_damage(I.force, I.damtype) + if(I.damtype == "brute") + if(prob(33) && I.force && !(NOBLOOD in specflags)) + var/turf/location = H.loc + if(istype(location, /turf/simulated)) + location.add_blood_floor(H) + + var/showname = "." + if(user) + showname = " by [user]!" + if(!(user in viewers(I, null))) + showname = "." + + if(I.attack_verb && I.attack_verb.len) + H.visible_message("[H] has been [pick(I.attack_verb)] with [I][showname]", + "[H] has been [pick(I.attack_verb)] with [I][showname]") + else if(I.force) + H.visible_message("[H] has been attacked with [I][showname]", + "[H] has been attacked with [I][showname]") + if(!showname && user) + if(user.client) + user << "You attack [H] with [I]. " + + return + + proc/apply_damage(var/damage, var/damagetype = BRUTE, var/def_zone = null, var/blocked, var/mob/living/carbon/human/H) + blocked = (100-(blocked+armor))/100 + if(blocked <= 0) return 0 + + var/obj/item/organ/limb/organ = null + if(isorgan(def_zone)) + organ = def_zone + else + if(!def_zone) def_zone = ran_zone(def_zone) + organ = H.get_organ(check_zone(def_zone)) + if(!organ) return 0 + + damage = (damage * blocked) + + switch(damagetype) + if(BRUTE) + H.damageoverlaytemp = 20 + if(organ.take_damage(damage*brutemod, 0)) + H.update_damage_overlays(0) + if(BURN) + H.damageoverlaytemp = 20 + if(organ.take_damage(0, damage*burnmod)) + H.update_damage_overlays(0) + if(TOX) + H.adjustToxLoss(damage * blocked) + if(OXY) + H.adjustOxyLoss(damage * blocked) + if(CLONE) + H.adjustCloneLoss(damage * blocked) + if(STAMINA) + H.adjustStaminaLoss(damage * blocked) + + proc/on_hit(var/obj/item/projectile/proj_type, var/mob/living/carbon/human/H) + // called when hit by a projectile + switch(proj_type) + if(/obj/item/projectile/energy/floramut) // overwritten by plants/pods + H.show_message("The radiation beam dissipates harmlessly through your body.") + if(/obj/item/projectile/energy/florayield) + H.show_message("The radiation beam dissipates harmlessly through your body.") + return + + ///////////// + //BREATHING// + ///////////// + + proc/breathe(var/mob/living/carbon/human/H) + if(H.reagents.has_reagent("lexorin")) return + if(istype(H.loc, /obj/machinery/atmospherics/unary/cryo_cell)) return + + var/datum/gas_mixture/environment = H.loc.return_air() + var/datum/gas_mixture/breath + // HACK NEED CHANGING LATER + if(H.health <= config.health_threshold_crit) + H.losebreath++ + + if(H.losebreath>0) //Suffocating so do not take a breath + H.losebreath-- + if (prob(10)) //Gasp per 10 ticks? Sounds about right. + spawn H.emote("gasp") + if(istype(H.loc, /obj/)) + var/obj/location_as_object = H.loc + location_as_object.handle_internal_lifeform(H, 0) + else + //First, check for air from internal atmosphere (using an air tank and mask generally) + breath = H.get_breath_from_internal(BREATH_VOLUME) // Super hacky -- TLE + //breath = get_breath_from_internal(0.5) // Manually setting to old BREATH_VOLUME amount -- TLE + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(isobj(H.loc)) + var/obj/location_as_object = H.loc + breath = location_as_object.handle_internal_lifeform(H, BREATH_VOLUME) + else if(isturf(H.loc)) + var/breath_moles = 0 + /*if(environment.return_pressure() > ONE_ATMOSPHERE) + // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) + breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) + else*/ + // Not enough air around, take a percentage of what's there to model this properly + breath_moles = environment.total_moles()*BREATH_PERCENTAGE + + breath = H.loc.remove_air(breath_moles) + // Handle chem smoke effect -- Doohl + var/block = 0 + if(H.wear_mask) + if(H.wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(H.glasses) + if(H.glasses.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(H.head) + if(H.head.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + + if(!block) + + for(var/obj/effect/effect/chem_smoke/smoke in view(1, H)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(H, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(H, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + + else //Still give containing object the chance to interact + if(istype(H.loc, /obj/)) + var/obj/location_as_object = H.loc + location_as_object.handle_internal_lifeform(H, 0) + + handle_breath(breath, H) + + if(breath) + H.loc.assume_air(breath) + + proc/handle_breath(datum/gas_mixture/breath, var/mob/living/carbon/human/H) + if((H.status_flags & GODMODE)) + return + + if(!breath || (breath.total_moles() == 0) || H.suiciding) + if(H.reagents.has_reagent("inaprovaline")) + return + if(H.suiciding) + H.adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster + H.failed_last_breath = 1 + H.oxygen_alert = max(H.oxygen_alert, 1) + return 0 + if(H.health >= config.health_threshold_crit) + if(NOBREATH in specflags) return 1 + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.failed_last_breath = 1 + else + H.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) + H.failed_last_breath = 1 + + H.oxygen_alert = max(H.oxygen_alert, 1) + + return 0 + + var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa + //var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now) + var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? + var/safe_toxins_max = 0.005 + var/SA_para_min = 1 + var/SA_sleep_min = 5 + var/oxygen_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + //Partial pressure of the O2 in our breath + var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure + // Same, but for the toxins + var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) + var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE + //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*0.5 // The default pressure value + + if(O2_pp < safe_oxygen_min) // Too little oxygen + if(!(NOBREATH in specflags) || (H.health <= config.health_threshold_crit)) + if(prob(20)) + spawn(0) H.emote("gasp") + if(O2_pp > 0) + var/ratio = safe_oxygen_min/O2_pp + H.adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + H.failed_last_breath = 1 + oxygen_used = breath.oxygen*ratio/6 + else + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.failed_last_breath = 1 + H.oxygen_alert = max(H.oxygen_alert, 1) + /*else if (O2_pp > safe_oxygen_max) // Too much oxygen (commented this out for now, I'll deal with pressure damage elsewhere I suppose) + spawn(0) emote("cough") + var/ratio = O2_pp/safe_oxygen_max + oxyloss += 5*ratio + oxygen_used = breath.oxygen*ratio/6 + oxygen_alert = max(oxygen_alert, 1)*/ + else // We're in safe limits + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + oxygen_used = breath.oxygen/6 + H.oxygen_alert = 0 + + breath.oxygen -= oxygen_used + breath.carbon_dioxide += oxygen_used + + //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. + if(CO2_pp > safe_co2_max && !(NOBREATH in specflags)) + if(!H.co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. + H.co2overloadtime = world.time + else if(world.time - H.co2overloadtime > 120) + H.Paralyse(3) + H.adjustOxyLoss(3) // Lets hurt em a little, let them know we mean business + if(world.time - H.co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! + H.adjustOxyLoss(8) + if(prob(20)) // Lets give them some chance to know somethings not right though I guess. + spawn(0) H.emote("cough") + + else + H.co2overloadtime = 0 + + if(Toxins_pp > safe_toxins_max && !(NOBREATH in specflags)) // Too much toxins + var/ratio = (breath.toxins/safe_toxins_max) * 10 + //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second + if(H.reagents) + H.reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) + H.toxins_alert = max(H.toxins_alert, 1) + else + H.toxins_alert = 0 + + if(breath.trace_gases.len && !(NOBREATH in specflags)) // If there's some other shit in the air lets deal with it here. + for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) + var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure + if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit + H.Paralyse(3) // 3 gives them one second to wake up and run away a bit! + if(SA_pp > SA_sleep_min) // Enough to make us sleep as well + H.sleeping = max(H.sleeping+2, 10) + else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + if(prob(20)) + spawn(0) H.emote(pick("giggle", "laugh")) + + handle_temperature(breath) + + return 1 + + proc/handle_temperature(datum/gas_mixture/breath, var/mob/living/carbon/human/H) // called by human/life, handles temperatures + if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in H.mutations) && !(COLDRES in specflags)) // Hot air hurts :( + if(breath.temperature < 260.15) + if(prob(20)) + H << "You feel your face freezing and an icicle forming in your lungs!" + else if(breath.temperature > 360.15 && !(HEATRES in specflags)) + if(prob(20)) + H << "You feel your face burning and a searing heat in your lungs!" + + if(!(COLDRES in specflags)) // COLD DAMAGE + switch(breath.temperature) + if(-INFINITY to 120) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + if(120 to 200) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + if(200 to 260) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + + if(!(HEATRES in specflags)) // HEAT DAMAGE + switch(breath.temperature) + if(360 to 400) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + if(400 to 1000) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + if(1000 to INFINITY) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + + return + + proc/handle_environment(datum/gas_mixture/environment, var/mob/living/carbon/human/H) + if(!environment) + return + + var/loc_temp = H.get_temperature(environment) + //world << "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Thermal protection: [get_thermal_protection()] - Fire protection: [thermal_protection + add_fire_protection(loc_temp)] - Heat capacity: [environment_heat_capacity] - Location: [loc] - src: [src]" + + //Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit. + if(H.stat != 2) + H.stabilize_temperature_from_calories() + + //After then, it reacts to the surrounding atmosphere based on your thermal protection + if(!H.on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases + if(loc_temp < H.bodytemperature) + //Place is colder than we are + var/thermal_protection = H.get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. + if(thermal_protection < 1) + H.bodytemperature += min((1-thermal_protection) * ((loc_temp - H.bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX) + else + //Place is hotter than we are + var/thermal_protection = H.get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. + if(thermal_protection < 1) + H.bodytemperature += min((1-thermal_protection) * ((loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX) + + // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. + if(H.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !(HEATRES in specflags)) + //Body temperature is too hot. + H.fire_alert = max(H.fire_alert, 1) + switch(H.bodytemperature) + if(360 to 400) + H.apply_damage(HEAT_DAMAGE_LEVEL_1*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + if(400 to 460) + H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + if(460 to INFINITY) + if(H.on_fire) + H.apply_damage(HEAT_DAMAGE_LEVEL_3*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + else + H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + + else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(COLDRES in specflags)) + H.fire_alert = max(H.fire_alert, 1) + if(!istype(H.loc, /obj/machinery/atmospherics/unary/cryo_cell)) + switch(H.bodytemperature) + if(200 to 260) + H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + if(120 to 200) + H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + if(-INFINITY to 120) + H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + + // Account for massive pressure differences. Done by Polymorph + // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! + + var/pressure = environment.return_pressure() + var/adjusted_pressure = H.calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. + switch(adjusted_pressure) + if(HAZARD_HIGH_PRESSURE to INFINITY) + if(!(HEATRES in specflags)) + H.adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) + H.pressure_alert = 2 + else + H.pressure_alert = 1 + if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) + H.pressure_alert = 1 + if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) + H.pressure_alert = 0 + if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) + H.pressure_alert = -1 + else + if((COLD_RESISTANCE in H.mutations) || (COLDRES in specflags)) + H.pressure_alert = -1 + else + H.adjustBruteLoss( LOW_PRESSURE_DAMAGE ) + H.pressure_alert = -2 + + return + + ////////// + // FIRE // + ////////// + + proc/handle_fire(var/mob/living/carbon/human/H) + if((HEATRES in specflags) || (NOFIRE in specflags)) + return + if(H.fire_stacks < 0) + H.fire_stacks++ //If we've doused ourselves in water to avoid fire, dry off slowly + H.fire_stacks = min(0, H.fire_stacks)//So we dry ourselves back to default, nonflammable. + if(!H.on_fire) + return + var/datum/gas_mixture/G = H.loc.return_air() // Check if we're standing in an oxygenless environment + if(G.oxygen < 1) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return + var/turf/location = get_turf(H) + location.hotspot_expose(700, 50, 1) + + proc/IgniteMob(var/mob/living/carbon/human/H) + if(H.fire_stacks > 0 && !H.on_fire && !(HEATRES in specflags) && !(NOFIRE in specflags)) + H.on_fire = 1 + H.AddLuminosity(3) + H.update_fire() + + proc/ExtinguishMob(var/mob/living/carbon/human/H) + if(H.on_fire) + H.on_fire = 0 + H.fire_stacks = 0 + H.AddLuminosity(-3) + H.update_fire() + +#undef SPECIES_LAYER +#undef BODY_LAYER +#undef HAIR_LAYER + +#undef HUMAN_MAX_OXYLOSS +#undef HUMAN_CRIT_MAX_OXYLOSS + +#undef HEAT_DAMAGE_LEVEL_1 +#undef HEAT_DAMAGE_LEVEL_2 +#undef HEAT_DAMAGE_LEVEL_3 + +#undef COLD_DAMAGE_LEVEL_1 +#undef COLD_DAMAGE_LEVEL_2 +#undef COLD_DAMAGE_LEVEL_3 + +#undef HEAT_GAS_DAMAGE_LEVEL_1 +#undef HEAT_GAS_DAMAGE_LEVEL_2 +#undef HEAT_GAS_DAMAGE_LEVEL_3 + +#undef COLD_GAS_DAMAGE_LEVEL_1 +#undef COLD_GAS_DAMAGE_LEVEL_2 +#undef COLD_GAS_DAMAGE_LEVEL_3 + +#undef TINT_IMPAIR +#undef TINT_BLIND \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm new file mode 100644 index 00000000000..7d159238fc5 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -0,0 +1,221 @@ +/* + HUMANS +*/ + +/datum/species/human + name = "Human" + id = "human" + roundstart = 1 + specflags = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + use_skintones = 1 + +/datum/species/human/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "mutationtoxin") + H << "Your flesh rapidly mutates!" + H.dna.species = new /datum/species/slime() + H.regenerate_icons() + H.reagents.del_reagent(chem.type) + return 1 + +/* + LIZARDPEOPLE +*/ + +/datum/species/lizard + // Reptilian humanoids with scaled skin and tails. + name = "Lizardperson" + id = "lizard" + say_mod = "hisses" + default_color = "00FF00" + roundstart = 1 + specflags = list(MUTCOLORS,EYECOLOR,LIPS) + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + +/datum/species/lizard/handle_speech(message) + // jesus christ why + if(copytext(message, 1, 2) != "*") + message = replacetext(message, "s", stutter("ss")) + + return message + +/* + PLANTPEOPLE +*/ + +/datum/species/plant + // Creatures made of leaves and plant matter. + name = "Plant" + id = "plant" + default_color = "59CE00" + specflags = list(MUTCOLORS,EYECOLOR) + attack_verb = "slice" + attack_sound = 'sound/weapons/slice.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + burnmod = 1.25 + heatmod = 1.5 + +/datum/species/plant/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "plantbgone") + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) + return 1 + +/datum/species/plant/on_hit(proj_type, mob/living/carbon/human/H) + switch(proj_type) + if(/obj/item/projectile/energy/floramut) + if(prob(15)) + H.apply_effect((rand(30,80)),IRRADIATE) + H.Weaken(5) + for (var/mob/V in viewers(H)) + V.show_message("[H] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) + if(prob(80)) + randmutb(H) + domutcheck(H,null) + else + randmutg(H) + domutcheck(H,null) + else + H.adjustFireLoss(rand(5,15)) + H.show_message("The radiation beam singes you!") + if(/obj/item/projectile/energy/florayield) + H.nutrition = min(H.nutrition+30, 500) + return + +/* + PODPEOPLE +*/ + +/datum/species/plant/pod + // A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness. + name = "Podperson" + id = "pod" + +/datum/species/plant/pod/spec_life(mob/living/carbon/human/H) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(H.loc)) //else, there's considered to be no light + var/turf/T = H.loc + var/area/A = T.loc + if(A) + if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 + else light_amount = 5 + H.nutrition += light_amount + if(H.nutrition > 500) + H.nutrition = 500 + if(light_amount > 2) //if there's enough light, heal + H.heal_overall_damage(1,1) + H.adjustToxLoss(-1) + H.adjustOxyLoss(-1) + + if(H.nutrition < 200) + H.take_overall_damage(2,0) + +/* + SHADOWPEOPLE +*/ + +/datum/species/shadow + // Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light. + name = "???" + id = "shadow" + darksight = 8 + sexes = 0 + ignored_by = list(/mob/living/simple_animal/hostile/faithless) + +/datum/species/shadow/spec_life(mob/living/carbon/human/H) + var/light_amount = 0 + if(isturf(H.loc)) + var/turf/T = H.loc + var/area/A = T.loc + if(A) + if(A.lighting_use_dynamic) light_amount = T.lighting_lumcount + else light_amount = 10 + if(light_amount > 2) //if there's enough light, start dying + H.take_overall_damage(1,1) + else if (light_amount < 2) //heal in the dark + H.heal_overall_damage(1,1) + +/* + SLIMEPEOPLE +*/ + +/datum/species/slime + // Humans mutated by slime mutagen, produced from green slimes. They are not targetted by slimes. + name = "Slimeperson" + id = "slime" + default_color = "00FFFF" + darksight = 3 + invis_sight = SEE_INVISIBLE_LEVEL_ONE + specflags = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR) + hair_color = "mutcolor" + hair_alpha = 150 + ignored_by = list(/mob/living/carbon/slime) + +/* + JELLYPEOPLE +*/ + +/datum/species/jelly + // Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them. + name = "Xenobiological Jelly Entity" + id = "jelly" + default_color = "00FF90" + say_mod = "chirps" + eyes = "jelleyes" + specflags = list(MUTCOLORS,EYECOLOR) + +/* + GOLEMS +*/ + +/datum/species/golem + // Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck. + name = "Golem" + id = "golem" + specflags = list(NOBREATH,HEATRES,COLDRES,NOGUNS,NOBLOOD,RADIMMUNE) + speedmod = 3 + armor = 55 + punchmod = 5 + no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_head, slot_w_uniform) + nojumpsuit = 1 + +/* + ADAMANTINE GOLEMS +*/ + +/datum/species/golem/adamantine + name = "Adamantine Golem" + id = "adamantine" + +/* + FLIES +*/ + +/datum/species/fly + // Humans turned into fly-like abominations in teleporter accidents. + name = "Human?" + id = "fly" + say_mod = "buzzes" + +/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "pestkiller") + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) + return 1 + +/datum/species/fly/handle_speech(message) + if(copytext(message, 1, 2) != "*") + message = replacetext(message, "z", stutter("zz")) + + return message + +/* + SKELETONS +*/ + +/datum/species/skeleton + // 2spooky + name = "Spooky Scary Skeleton" + id = "skeleton" + sexes = 0 \ No newline at end of file diff --git a/sound/machines/airlockforced.ogg b/sound/machines/airlockforced.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8f46a89fe3202b2c04ce11d30a6829876838c021 GIT binary patch literal 16204 zcmeHuWmp}(x9?y@OR*Mrr`V>ryKG#GySuv0e!KHz&#WXXYfXMhR#uYP@@8hr05tHg3laPep-P|B1VsepYUgNZ;q;OOEn4v} zmb-tR%~0|$CI9_;DG3FMnZ^=wp)oxFZ&x?WKY|D$`RW$-=8W==W+c`YhH8JslSq-U zFf(&7v$L?gNP~j=hnZAZL=7Sk3cxW^p%qV4ng)mAIwgX{(+uOmVTD2Oge9|_u#`)= z7Ba0WS{g`#(D0NMXyMY7qLnOgjbdLYG-)YHXAExYEF&~6sqXnys|cY+f}q#wN;0&4 ziAv$Z2)N3TwEc-nU}1PlXH@Pz0_A8hjZkx@Q+Y#jvQb2-b3AyT!dOOFlJ;{v7`{+h zPFRvHd0vT@&`C+jQs^f{rEnuj(Cbg%V^v??vr7;SuNDbV006Y`T%2&|px_E<08%B` zFEr6xG|}W-@kUbb{<1*uMgxE@dn~Cqtl=68>1lfD8Bs-5pE-6_)oT}>g_l6WYW(&^ zs-R?XS|J`u4~j7k!fOpUfCK`OI86^4%)h|{7}9WsQq}KyJ4FYYa+%Zh?>XC(&Fx9q z((UbKI!$mEProh*u_rvaxaqeuJ<%;g|Q(NKW?#?lkiL0 zfAIYS52U_AIPAd=#UzqB`2jd$p%z00@T>W~6y_+7NTm|_`Eg2zB#9~mQnXqB)Eof- zNQ1DHBuPL2>lR8HjAJ-NTb%g`iLSIDFPvqBzHW?V^yPN+wQhp@n7I#41f{YbLt3_B zPTi=oWk1sjbz0M+vSA)fTL@`o+Q0buLz)Kx*Em*4{6%soX;G%*2yMw1=)Z76GGB%Q z@351og!6xdK_^~`L{TY7sFxX?m63m|I+vuQHE*(dZDWA#x_aZXe&e#e@Yz5k+2nr< z|5P1P6Mr;egnuehh+{Mc+W(TEApCFDB!MXGQY7eippbB+7>=ixN??_);~k&jmHjQM zh$TCtBKFZ)Y_(o&F;RBGS$5G`Rii;iqtRw@-bOFkX8p$JKLr=Uzg3h3fS;1l1(M+f zlF{3o@f1+Gq~!pB`_h|e!t*(!w>AyvUfG|Of8GdJj+U;|FQ_au)JI}>07i# zTeNvwTzTZ+JQK~lBFie8jM}5ts{bl5{_Wtg0PsDIU^tEd(!r%51k_)2A!7j=utyn; zg>-sIkN;O4<$pr})tQ3(&kX{Hekr;h!i#VuAN1j0_U~75{HNAX>6%q0?#p zWrSZ8nV0#Or2k7OL<>n78A&?be@n@~3PW^36lMQsT_x%MG-dy;iwdHMq>So+Lf8M7 z@&6I{KO^7|v5WvbU?$+-?LdzV00dIg^Z;N_Aw2`Jjnk}(umAv=A<_TO z(*EmQL5MVe7(mb;(d5hb*d#y@3-A{L@xIpA07jwB@dRgpZ1{6tf5_;7jC(j#h&5z4 z2h*b}m=A#g5+tDO3k}4;XTw8`jABrcMLLb}468g=u0=XkIGWhx2U+*L{WK~WWh`0D z&^!wyh!wR50EDkX%7za95aR|7kU{~kBx>m8FL@_1#b#7g&C~b8@@T?~EXwFu$1ndH zdsfxA>3be8iKS&_NV1o_idZk4s-Ist(;=K?M?L?>Ip;zeo@bu^!g;$=SqKj##lNf-5{K}ps6w2LBoo{Xh-n|G zwO$6a7hFsh8zI({fD_`n;0RIUs=hPGN5m$2sRJya2x&5q3~f=Ofs8N>DQmbC0&S2C z7+jj9A|y#!s6>ZQTA%_JFNDmuBP5ARN_207RKRqF0PqzC9`bu>X9(;>5N9A%DH1f0 znW#iNkm)1`F2yo}cq)a)k)Zv|1SOV%RHq3kh@S=VA_@{CUtA6)@L#6_GLgS{7LeH- zAq!HBwh+QX4FDxwPyk7nc-%Om_$Q>-8i+svG=M`eSPKDwS00N^YMONt0wt@gY%K(6 zNQ!L2zDG7qcpe1#myEv{SG|X{#0yZy8dzde5G-8`{$hLB$}Fp>qB`fIGgSM6{|Jlq zGAkr%f?HBnHUfcg;V+_4zy=~JAPC1^5pA!;`cD0CpMe4VNnl9}v4p|2L5WHTw1sFG zkg070;)3W4h=Fx z3KH-=${zUc!<>tPg;$FKNJ7Ryq+&P-p|oF(v@g{OL({5KI25!`QJ-iynd*cFwqR(? z1`U!V#%o5jCr(I7RW{&w(GljyD@lW{*Q9AF3x60Mw-?6>M>7ok@R|e_zSAnNxzRNO z*UaG#H+5JDggLIcy{LegF+VOmPaxPd1PQV^yoG#=xEtVv!d$QXeqgybR?CdPyIU)CuQ zN{Ra~MNqy(0th2$dS1}P}f(tdvNQXvAsl!bpOG_Yi00i@f$C_*Sq zOjJUmOoSB6Er^HoQ^;!|1LNh;tMp%5z@@M2}ro#Pcv(Am@N zH=!VX{U4tU7oIRN8Q(wFaaJ>gAP7qfIZgycGcwCDQV2|I919vKNQxI8#3`6Hl+F#r z@|tW(nuWMUBnSWkGZgGA1f&i$XhRf05RL4EsIb9XdS;ryS0Nt2Ie<=z4p30hOfxcm z83nMN9To!6KA{DXyn|N|ghrKX-VEd5-F!v;6Dx@uvJiooFgU;+00e3LLqkogdbXg+ zMT`RTd$(akUowHOzy=HeAVQImrMDnOAV;D^y^cnWc>`$~b4bZasA#FFsf%MWBlF^8vs03@ zl9S`33Fcw|f(2?qYqK&Fs%hZ#^OWfKi{_M|)nMG4=Dp5ukv?hS0Po^@wWN~ICCT;U zZz@S;}=(w{5xekP7bLHoz&jkq!4i1{PT=tQ*h;=-JP_S@kj%lQ{wej|*!R7Gn5Af-;_v1rvH-3zvqAOus*?q!?;=kYR|Cov# zX)U{v@iyW3eJvXdWg6mxoRQi^3awz`Cm{6pu9ksE;PK2)TOF(Iq%v*hsPGr@fSD~L z@nY-sp{f^we9>T|WKap85!7&4437Y-siBYX<$SJKH^Hr#*WbCW%SCN_pS%mMB4o<3C@6F*ILNych z+*TKtHF+wvTsEM|!WJ7~@>o;M_})mcV=jLu#72Q!epjy8V7iDs`SR?|W!k7sN6U@)e1>Ig1UL5Y=e z+FM=7OA6S*{S(>g2i0g&!IhUTgcM@9{|pb1uuL8_evgburM}#aE1r|ZC0l#FCbKz( z^vJie@q9ad`AobdLyhW6Uo=1y#x+QKj}lNN0*vI5XiD|MH=#e0CbTDf$;&!vX=$3eLK=Kkrf-)Ntg3US`Ag`3P% z!Qm3n-gJ_ed&|$!(Yo-|YTgS&<792wAGelXrCu@1%|K(II}4|>oiZY~{hpZMDv7!f zpbpjt7PBrLPQFEreYD0ojeCCToRzVNa3GQZwAbIit!n+4sp+v7B(g!`zdJAfK^9f1 zL*tj4iP=c~t+w5z&EgNm=^_wZIvwg5?jg*`#?2eGK#zn8YsOexW~5t#MQKS^ zgFj1_O6Lehxhf5Jv}6DPT9;a$IhWK{O9yjmWYe=Hxi?I=TdXndgL6&TQ!UquiR3L^ zOn8qy-Dj%?K*P9L3pDNH?eXxV)ABW&$EJE?c|eBbBS+o3b!DS1Q8^#cK1nF-RdIoo z0P&b%ORENl^>*9JYZro}O=t@G<*zQ^8fbkY5bV(yRbe5m+s{)guSx0scEo;QK3wV| zZU>X_;zS`c@+!^@_|2?RA^JoN@q0Da!PUe5B2-RUZF1bbWdPQolijkzR?5X% zQf9G|2fi+ypm%lB6k1h3{x~}xF)+50Mu>lwn7SELk0)&OR%g4WeBb)v!6#?6zr?Z0 zPRYPsz%&7c%njZct-cP>%}hS{5DGnkZ3Jdc@1OkgdgQjd2VNHg$MWe}R1( z>#Ov@dNVJ3fLwjsK+Sq&+$Q7}PMY*5mtb(Ac@%WIAl$~*F_0M>S#d>Ey|2)vl%<`O zLpT91HyvQ~4kt1Q4@zxie#Uf35^1XgCO&%DW~Md`De_ZujsYz7gK!ORMal=FVC$5k zavKJM$o))#RLI=mUq+F2*|0c+@W5_em!pQkupU-Q^h7#QMR=*C1$CquuTG;ju|*;b$0nE}1VYao2+ z7Ju0gZY>jv5c`Y`;EoOjus(|c#+T$tszYD^g;&fc@x%R*?tE<-`tD&_!D^Pe&T5kkJMiQ8cdUJU+-XsYO8UqQidt#WC*H$rX*xNOduL;fhmaCg@|?wm zb7+`UQR8G_Mud3JUZOZkx&riRt+)J>PxsD&*7s&6c@Dw=>$vLaiO}*GLkIGswVUvtMWp0*!VHRo#v0c6xMv$w6+gq6x2yT~i8J~BWbI4p z4BY&vyv(e`?LQw_TT>D2EuxT(q!_9Q^BdXN-OV5WM0D-Fcw$i>b7V@-Kk*ad85UR2)ZJ6A4f~%#kJ@>O?H;%9D&X4W$Yej&=Y31?;55$5^EHa@a(R9+_rO$<9@g}3vE~??QB^wKTbn2 z#1-L7ozV<78a`3nTB>#od{a8|q2H&IwmFyR7K#YJkp!7nFrYLg5;kH}fuwtW@kPv!yWZ z$3Nc7TZ^0KoS@w5Y#8ZJ-UxI=G?u)t51u+fRS~&JOJH1*5LZ2Cq-us%zrXw?006U9 zT6pMqaGRlJuISXRb!YERbv?2{t5bh|5Xv&?e*Y|QBQ8u=@uA>uJo3~?;JIUftv~<| z&y^C_aGn8v`b=GS67f^BklMky%i-!xNjO3|mmKr#FFY$M&Ka&Gi7ZwtnK8{HZ#qVU zKVOZ2J4!L#PqruP6(%u_*V_2F$?bl7^N$1YXtp$%A|kI8O>?w%t<{v9m*dHyUtWEAhx}g}<>n zWh3yh?;B~j{R+(=Nfq_R#u)mXp~=A^HyA+r)20dV>^t>8(E|Fj^;k+KVLvt4Y?KLP zbCx{c`uNJ?$`#~?V$RsmYvRbD6X;2E5=)l}WfCrIwTFGdLTJ6Z>Zgu8(D|U1tv7%s zKPL6aNfVupK_IJ%xl?$hTpM%w6%PRuXC&xVmE4i_lOGx2pUU5v-m&uFPECO; z2O4?qQr7Lrz{?u^b6`{&hEj1kCo|w(;iPLKZ)o%|{`76O{v$^ag%j9R=AK9zL0Pzi z)Dm-JCy@>DmNMQq{~{+3w9_+0Y$9x#^#(CCNETl0u5C)Q=gp+_)5!|%vO6vu zKZNiP3g8>D7Z7tE^U8mNH9&_|oSoI)#RPi3(-_jhzBC+&%Go*=A}|(yjLy<&z501| zl&?JK`y{9p6T{G<5{OG%c3O4xbAH-fxzWhRba%OFk!bJ!*y#XDhCrJMiFwfDc@NaLf*bvIrM%}9$Woo3K!=OF@{PDlz6RHJvL-bypZ7VJ ze29)^JsVd?l0~1)*wY|tRf)kGt4p}O1^Xe+CvFO&4<3wPpquHAu1(LXu`#sRbMR}d zu2$cFu3Fv1`bH`vaA$>>J9gb#J&gn{Zk2ag@D-0Cx_)RgI)(?DY6#&;iz+DWkU3J% zysU>APYQD`?xHKP2Cg_u&lhrPF1W?C?P)b_0LINvFayQnFqfT}fGo{cxw=Hj;_-^| zj?buy~*|{MF`>*r)p1*q%e>Wu{yBdH}dc!7t1qB5q zITbZ^bpr);O?G-}d_r36S8{S1GCI17+%Ksq@d+gqR1~z-loZsA>|Ru?T2d%5I8Xsg zAEo*xip%H{5>(ux`w!D|6?|V!NiRQnh?D6~& zl^fg@O zg-#_N_nD`hSug8#t*>CZ$9HN!V|oSw#;ajnI?EP4s`cbRzYsuOSjiMG9(Ney$ESAT zafANmVbOyfP+5(DmrmmILVp7fC4;=*gX_mr$7@AwOkDo zvA;bT>5sGZbL05j!GgIRk+n_+xUEW<)F#su5g`bQ-bN!lpM&V`8YERnwB%*_w417X zv0Da(r!|3tod>0VqI1cQii3j2d5)P~Pwj|nh;790#>Eg)2C*fF`wjPmzZ$eJf2W(o z6QPRB7v_KKn8;9$F}?h((TcY1G>8|?ZH*tyuRLdx60WKM2ZuDl?eQ(Qi8gdG7Alx( zZq&i^&lhm{yf5qFnN7$i&4x8omebX1aZCJGk;azCS)9tZk(!_G8;Q_@ZDUV}pCo!8 znbR}4&0?684$AmfQWkqTupYlrX_Eo2R%(%Y%+Ro}9A`46k;Q>7Vu#%f7h>5e;wCrH z7N_f?vNa3KOz!iuB&_E}mbUb}o6h(dU7q24tZzHdeKl@ldyzWYsg;9_M6V!$h$DGI!6M|DM9b6KK4)-OtHo>DiyK{S7aq^4)_51^>&|6tM1u$N_RVia zGUZJ}`r4m7dfVpSw4@w<^dw)sw)P+tX*$IC$QONmX!JvU`J}c0{9FZZh(&e>Xn%Zr zSY3{^+31jl@n*vY(=h2Ynxg#yo1M)GzfDgR(*7)PJOLeFQyJg%8I9^VV-UK2{Q%u;W0PL`1;Gz1!LM+&3VT2MG!tU7*g zK_#TttGtS?2BmqER;ovq^!kc9b&UHeX;#)AXItFVU1B%Bry2Ahh*_`r_Eh7WFLX0C z(!wpH(OyvbWweBiy)mMYwt2KEh0PmvV*f@f&|QRZvtZG45Ps+l!0%1v5?*1DicQlC z!oSDC6tQ3eGUsm}p2HAW`bas zF5&DCg;a7%q~nqvXVGNHqqOtsRfU=SUe{7j|3ysbu^-g-hpzo0@}RmS1U*HKAJ4({ zTp|7XYa{m}))5_keHmI7Kh}B4xKC8zRtSOavZKz)w1RMW5bC}V@n?jmh*v%EkDSb1 ze3`*yMMun$*ukRi?V0*fE>q9cfWPYGAL3tE#u%+@44J(0lC56vE=IiTSN)b7U5d1V zPle-mssm<6kA#GcKs1P-P*mowIV^8fvk@3KHL|t$jUTUFGb4XkO!F#QWctA#IGr2w zSh`g8BRJfhMJT^7z$r&HSxcHH*ZGJyu$-PUuk^7ZaB?b1E!rFZJ#1dMWdTs~{z>-;|2hdyW>P$b&tkN%J9IHm4AlNTKVO~Iqn^*y z^c}j?he9kXN)`0VN%GGNsJBzz%ny_~BL~f{@LS>iYEi0^_{6=xd6&<{Y zF^Mbp?UEcxY+TD`GfCKpHZ|EEwetfrq_avEHj)kO@70XK&}&*$>L?d5)?d_RWs&$% zHvDtm0|O@GauVVIps+k173-}~_&LBr)cJBjpoW7jzhDuicPsYr>4(d)6?MO4LAXqM z6M#lAm6klyPCpz7} z`2SOSdX!cMu3lRn1vMrQf=y%7k)btUDiq~fLsM(GVG$+}62uZM@cv3ox#`z%X5%U}?HHvd($JX)a^ z`Bn-G>Ep8qivu|0X64--53r_H)YHcy@L;+k7W~e4^i!Jqb^hakZCQ5`g1X-OTga@3 zGeL7Ktq6MEl29IHc(^~F|DdMR8tgFX+jeF71ILAYoP?Y7w40%cz^}&Vrw->=i&P{@ zpnwZE7x9fm^X^W}`&8RWJnm|z{rw$&`e?m`rpu7hgjo*0)m!Y#-)5EzZm6)TOl+t( zVk9}@(!{DD#e{%Yk;K57*SjBm;}TvaRCw*CBiaVHI9~$;X0n;;X2=0R)Y|KzoMBwo z%vR;Hh|{2DrQ2CuT9!BipAu8#X@*pozC?qcx+=aoRqLvbrU@nE?6-o$Q~2X*YiYaKt|JRCfjduUc+FV91j*y= znH%tqM_kEzXcHi}S9niV&u_rlg@Eu!da(m9DQ#47b#$oLK_#5VGjwchC-yB9+dbs) zznDw;p5JLj^`OF}rS@Bs?ee!VM7?01;$rJykVw<8@9ApI{o@LMf|P0XSg^WTX|P`l zpQBJmfWmYYe#dt_{6pZmI!&iK`p*cOhuYYLzoY*&Ci(f|@=jvj+^T%@MX~z|>Gg+; z-uN50vFp!l!WvS$YUT9@+^^dB6V9k`A1~|l54ue})I5z`tIz<6umT%MH!RyoUz7>v;N^4$ULrF~tRn?e zC>ae^30o65rPg(ilM*-slrLr`DEg^Xm`mrTt+w8Bgw>eUXPRe+>2gr5(rSj9WEcRA zZD0%P5hkDPMwdKJ(#pMJi%8WRx%@kVNRj7fG|^9evf%iB`|8S!im`TsDe8}KA$D0E zzb-wCzpE2eG244rL^@2#N#sw3w(omrbq7Zo67p0SZ+3jONE`PXubB=|+ul>Pef+|Q zuO^F{{GqNsU74M-Fj9VnfQt6HOlx%1^k=AjA^9oaQ24vi<*e%Mg!4RSJ(E!(oZED+ z7TO-F^VJXVM3H+toT5IgNR9TH;tnWmC^SDly@&sb9UoWMNe~8>Txy`HXbk5hCZ1M7 zmbdX)=6U0H-&57>Id1Bfg7dm4qNhIif%bbS1xxs9>4EpoK)sdjkOe_{HT$JC2N>5& zPrhGs*1Lx-97oykGS)SGY^cB*Y~d;bI<<^wkn_4he;wRrc#4UGu6maEr*>VaQa)tp z%c`C#ike&)ui&if4A7yqr@_$v45GmiveD?K)bwk84KPvT@Gx-?K8uPT5_4TNEm(-w zxl8xrPr%1xF3Q9)S~PuVCu(}w>1HLTtF5f3!@`PE_E=hANI)|-CgdnOK9QKk#r)DM z%~!UrcKv(2Dpk$H(q~g0?J9I5>U3a7G-ORqX#~kA@DC&E<$y`!ui9MpbI;l|;Xt!S zK_6~sgFiv#I$|k3CQ{#{H2_`h;11O#V*OXp{bq+&LJ#I&12F`=N*(~9AJ zpM`nC`y&j)#|4N@i<>QmndXC$m${KIggR(fFRvkv`tRx zG{qZ=2&zR^FT*%i3DMSB$w(>F5Ov9hI0f0n%A|l$+QmfF{XvlPXxkX}XUoZ|xk~g8mg{P#+<@lyE@FKB03YnejKHr<*!G<`@PrUnn*rt6atg8q=5N_Z>CCGK&tSj= zIA8E(&pCt`9XZ(8R;Xnh^d%YKfqtZ7x67&^l_Lcc}d6Zr$0q6ssT=U=btWW z=ryka)`7>tAZquJ$)3KdJD6|X`_5yF0S1-<9e8*niDFvRR>c;X0v;Z zK6(wwvotrUV#9ZY&MFe%vic+MZ!PvsgY5=vg~`zkZ5w!v-&#Rzonx0x87^66p!cs! zXDZ)>pvv3C)D-cooAWe7PP}^7nuTpeGam{uB`q^#PCRtVjNaG%e133&O127S%<8lE z$3!b(fI)YAcw-L_`%p-~_7lgdWnP|6^}arSn~cgQP1?R>a#2|dvLS7e>1&yGdIWEn z@u5eDSni#HJh1@!6i!5BWaQzgFGr!HbyT{HX}_nz>_f3r`?xF>$KJ#wjGi*D!R*op zJvXC#%!qxXJKd8fi4>oYD3x{mb6y)gsOVqOFcBpFZ5ThaC-Ryvlq_8;_R&FUAF^)A0qgCfu5VGD0J_y{ z)zALOwEhY0>Xs;#XG0tk%;N(b;E_bc;(P>^Ii=s(RfSlUtAD)H5O+47)^5*BN*6bk z)&$zsubrAIH?g5)W-O{%#LT{7Uyh|>pmF*?w&rQK(Av_JfAU-fu@q_E<5jMA%w&83 zymjEnIvBwq)f-rK96>9ou~fm@x=HPU%B?@^iGldX`^d{z(&BK|s_;J=%aH;Y&taN> zK=F1s5S6E!*9nMz{CLeFQbDP6WA91@7;BWF%=&<6((^egcs{{1>w#|38Nm$015FlJ z%Y2=8F?)4@w_e)Nd4-$GjoktZR4y#Z{q{8T91->OGG;-e-FVFH(itcAWEkMRDK~4N zfuMbJmoow&26fjna$!WNH{V^FA$L8&xdgi5XHNXedDbaD{=@c>{O@i8EFHx^U&OwA z;sDu42e`j6aO2T5WoKvSTvnN^SL*+`bP{cDQPbgLz(TtqRZ#A>^)6+{$DNix-ygORCvez zp|}kM>8+Y3A2q<5->r?c(<`F$eIM@_kpd|4xTvC z((b8dAoM!%n{roqm})R?pM#@mGy zIa_;grq-&{vfS3+l$}PJmC?pUu-~Hkmme=_uKjh*LLK(t{`!{alJS-^{gUrN|J0B* z3VT*|*&=IlHA9#|X%}fnvV+|iyWAml=>C)rb>>i?ir>-g^21hasgxZ5__)=HuWWwX zObOV2Bp~cIT&!J0)riBZYTx09YPm|~X>N8>l6E$73xl0N!+*_jPH0*CdN~0#OnQl|elr}C1JrHT z`D34doT?d3NntY*u?+5O{c=sJ;ad6OjUGd$QMiB}R8S)8jPolsT)r(IgiEC~inqXG z@OF>7otge*<(;^C|LzirNGQIsK>K#{WUQUS_f3wBYB9yHQ8Vv5?wRw*-hpdjd)VX= z`XeyMesOIxo<#i?o@|m9ddSJ{Vm2*v}hc!b|Xum$-E`4edguCf` z|LL8Wo%NRKkysBM2VaYDH}sQMk%ioC$Q+Jc4ui{ck%l(L#aGEE@5b5vLg?t^V?R zmw+yWBg;V<`^nvb3q_u$A0mwPI}1Kd%WM|$Ri>^TiL1S8`5K7>O04P5k^SDL_p7#_ zSG`R+5;bG6FPJDuq}h!TPtS1yUHs&F@xH+??pobmTFFHrctV$x;R;{4UKf7f6(ENO zn0>e8pNoxe$t>dKGVm_@2I>q)?U63KZ}DAcjx%(47HpXaxAa1yh$r^z9Y)2lj0zOM zBgKJNjNb(sk1z}gb|1qH`MzccC1*Yv-Lv&w`C6L|PCSmJ3?4I3aHO=cfEGABMe2T5 ztH_I^(70nBvohOW6!Cy#_uNH0_%&$ZKtTq_XpspM3g{cS za4#yZHrnX@F}pZxtZjCbFGA!|KvgIrx>H<}CYtKKHdL7Nfi^gq!0U1=o5$OV z@6AqIlb{r0ovh^&Q(MhQ!Le)3%9OZPMQLL9xXEcrj#EV|ce19hiKPM41x9>Q)S{H; zI86@7S3C;4BM92Ywbl~>$VMvimX08HO5(N2ifV`B`Q8{VAkNelh^J{LP@K=)?|X}g z)_nHq+l7Rx#GcV*P1tBQCrDO`#SAws!4y}@aoT~b4Oa@Ij;8FgdHS^6&ebtD*8u70 zp8w02fK5j(3RBYl`Qb^owmW=refMkrlX+|JNpHSX9q#$1>62!juK}$d_57!DKP7V0 z6Mq`GRj}@9R8RG-uDQnzIT$sp&2Ip3ckIfuK`sB6lx#zfR>DS>ix*A$Nh(lrb3WWLmLxJbFo-60V z;KcoB@hrWV>Ok~Bv)>tWt4!f@<7=w(_TktXDz+bwVRYYDd4_}FbG@X|*B0&3m1D8T zZiyc<=ig!`|2@)=l+BdgkBU$qiabbVur(~5n*HgMJdz??MBe7k$xbZpVx1cKnqznI zna)hG?5s6|IK=XYHWB4#=-Hsi#lqToJ0DQaFpB5y&1^X@ZR5|M0;eT*vmF!LF$eV~ za9jK4k@|sY)BR=D>!ZA=9IGwsnr3dBrp$5u(EQrEGyFxVtWi-y3vp2a2A7)GZ2e^H z9B?}1xG=iNoa)J=kZuPE(xwq|)<;@WgB-Rt^s5dI(stGu*-VNMx6Cbr5D4ElSS#Z$ z_v**z9iy~y*HRsHq#|T!ps;%rCO>^d-Y~~$l^<80|7tl+X51)bRp9+S`Ds*Ro1oC9 zrcqk1jAdPJ;WOSTX&e5vNKi@;Ar`=Yl(oy!%4wbG2i3czVw^>)@{Y!EMFdw^xHDAUT!0-hY5l}EI@CN3b}jl;Og`lIC% zId7JBr$2!dkqXJZUc|n7|F|GbdPP5a7C|Lu?zXMhvqBfqc{$oXp*2mWv~Fc z<{SNABdQa|C8zzvEH2$;)b!5+QX;E#Lk6$L3|#Af+9F?)nUcCngxu zL&v@-?oY680eEr1)2+>e=3^dTFrM7R7!~I)iCpZXDc0B2)B|q;c)jG8FGfg^FQ=H( zO~^v`D~I%z&~K?-lSNrZhGdnIBdAju=us2{P()hKdg7IO$s>kuXSuc8z8|i4u5#n) z?ih~iY0V$iJW2=Ie88{rEY~6bvB@#=x*+b1{4++Q@^5(12TP?Y{G;(dX%vW`CA-Ig zwPA+7#&d^CC96C#X$9_;Ol69fJ7H3lmq=GVxuS1+xChpv(3$wb z@$HvNVsVG2WUeI5p(JVuK*wfFZ%?R_R>E&=G0)$ z_Byop?m~SD-4>F0EfiAUE*8$&0Iz@8vCWruM|g2ac$@j;{Bc2j07S76Rl|VfjUZT2 zqA#Q(*ab~A-0rVsC*=%(IY6GUg4{fpjT^#cN0pgeRwY1+4h3yd$GCyW(6h?Cl?5%FdP$h0~-$!F8{5y(}_Q z!Cgr;IB_KQynDFoX@g=Ju+Qy^ljhEV0UL!{uKPy!!}bc=gS2vpp?er-7D}$yvW{Uz zp*kfc^eaS07z`+FXx*X5gr$5+e;5=;KXB(aTC!+1cYoK6P5O^vkdx|{qj7q2W$J0; z1SzBj@W84Mhg<}**1~&>kp9p8xhz$KCEXnnAitm_K7L1z!S5}crYCkwFz=O61)^i@ XVF?PtovKnk{IriDQ$d6LN$r0D?V@a) literal 0 HcmV?d00001 From ddb9955e53a881b06f47d68d335285be44d1cec8 Mon Sep 17 00:00:00 2001 From: AstralSerpent Date: Wed, 2 Jul 2014 09:27:06 +1000 Subject: [PATCH 06/17] Removed an unused suicide_act proc belonging to the scalpel. --- code/modules/surgery/tools.dm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index d8db9381aaa..841e96959e7 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -50,12 +50,6 @@ origin_tech = "materials=1;biotech=1" attack_verb = list("drilled") -/obj/item/weapon/scalpel/suicide_act(mob/user) - user.visible_message(pick("[user] is pressing [src] to \his temple and activating it! It looks like \he's trying to commit suicide.", \ - "[user] is pressing [src] to \his chest and activating it! It looks like \he's trying to commit suicide.")) - return (BRUTELOSS) - - /obj/item/weapon/scalpel name = "scalpel" desc = "Cut, cut, and once more cut." From d8ae776f647127a9f2d6998049fd623f18a383cd Mon Sep 17 00:00:00 2001 From: Kelenius Date: Thu, 3 Jul 2014 18:52:11 +0400 Subject: [PATCH 07/17] Gives the AI a hud --- code/_onclick/ai.dm | 2 + code/_onclick/hud/_defines.dm | 17 +++ code/_onclick/hud/ai.dm | 135 ++++++++++++++++++ code/_onclick/hud/other_mobs.dm | 3 - code/_onclick/hud/screen_objects.dm | 72 ++++++++++ code/game/machinery/camera/tracking.dm | 7 - code/game/objects/items/devices/PDA/PDA.dm | 8 +- code/modules/mob/living/silicon/ai/ai.dm | 33 +---- .../mob/living/silicon/ai/freelook/eye.dm | 8 -- code/modules/mob/living/silicon/ai/say.dm | 7 +- code/modules/mob/transform_procs.dm | 5 - code/modules/paperwork/photography.dm | 15 -- icons/mob/screen_ai.dmi | Bin 0 -> 5982 bytes tgstation.dme | 1 + 14 files changed, 233 insertions(+), 80 deletions(-) create mode 100644 code/_onclick/hud/ai.dm create mode 100644 icons/mob/screen_ai.dmi diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index c90a8c19dbb..b9d763fd883 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -10,6 +10,8 @@ Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner. */ /mob/living/silicon/ai/DblClickOn(var/atom/A, params) + if (istype(A, /obj/screen)) + return if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked build_click(src, client.buildmode, params, A) return diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 342eeba8d36..5b8174a9650 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -89,6 +89,23 @@ #define ui_alien_health "EAST-1:28,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator. #define ui_alienplasmadisplay "EAST-1:28,CENTER-2:15" +// AI + +#define ui_ai_core "SOUTH:6,WEST:16" +#define ui_ai_camera_list "SOUTH:6,WEST+1:16" +#define ui_ai_track_with_camera "SOUTH:6,WEST+2:16" +#define ui_ai_camera_light "SOUTH:6,WEST+3:16" +#define ui_ai_crew_monitor "SOUTH:6,WEST+4:16" +#define ui_ai_crew_manifest "SOUTH:6,WEST+5:16" +#define ui_ai_alerts "SOUTH:6,WEST+6:16" +#define ui_ai_announcement "SOUTH:6,WEST+7:16" +#define ui_ai_shuttle "SOUTH:6,WEST+8:16" +#define ui_ai_state_laws "SOUTH:6,WEST+9:16" +#define ui_ai_pda_send "SOUTH:6,WEST+10:16" +#define ui_ai_pda_log "SOUTH:6,WEST+11:16" +#define ui_ai_take_picture "SOUTH:6,WEST+12:16" +#define ui_ai_view_images "SOUTH:6,WEST+13:16" + //Pop-up inventory #define ui_shoes "WEST+1:8,SOUTH:5" diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm new file mode 100644 index 00000000000..9f254878373 --- /dev/null +++ b/code/_onclick/hud/ai.dm @@ -0,0 +1,135 @@ +/datum/hud/proc/ai_hud() + adding = list() + other = list() + + var/obj/screen/using + +//AI core + using = new /obj/screen() + using.name = "AI Core" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "ai_core" + using.screen_loc = ui_ai_core + using.layer = 20 + adding += using + +//Camera list + using = new /obj/screen() + using.name = "Show Camera List" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "camera" + using.screen_loc = ui_ai_camera_list + using.layer = 20 + adding += using + +//Track + using = new /obj/screen() + using.name = "Track With Camera" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "track" + using.screen_loc = ui_ai_track_with_camera + using.layer = 20 + adding += using + +//Camera light + using = new /obj/screen() + using.name = "Toggle Camera Light" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "camera_light" + using.screen_loc = ui_ai_camera_light + using.layer = 20 + adding += using + +//Crew Monitorting + using = new /obj/screen() + using.name = "Crew Monitorting" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "crew_monitor" + using.screen_loc = ui_ai_crew_monitor + using.layer = 20 + adding += using + +//Crew Manifest + using = new /obj/screen() + using.name = "Show Crew Manifest" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "manifest" + using.screen_loc = ui_ai_crew_manifest + using.layer = 20 + adding += using + +//Alerts + using = new /obj/screen() + using.name = "Show Alerts" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "alerts" + using.screen_loc = ui_ai_alerts + using.layer = 20 + adding += using + +//Announcement + using = new /obj/screen() + using.name = "Announcement" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "announcement" + using.screen_loc = ui_ai_announcement + using.layer = 20 + adding += using + +//Shuttle + using = new /obj/screen() + using.name = "Call Emergency Shuttle" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "call_shuttle" + using.screen_loc = ui_ai_shuttle + using.layer = 20 + adding += using + +//Laws + using = new /obj/screen() + using.name = "State Laws" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "state_laws" + using.screen_loc = ui_ai_state_laws + using.layer = 20 + adding += using + +//PDA message + using = new /obj/screen() + using.name = "PDA - Send Message" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "pda_send" + using.screen_loc = ui_ai_pda_send + using.layer = 20 + adding += using + +//PDA log + using = new /obj/screen() + using.name = "PDA - Show Message Log" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "pda_receive" + using.screen_loc = ui_ai_pda_log + using.layer = 20 + adding += using + +//Take image + using = new /obj/screen() + using.name = "Take Image" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "take_picture" + using.screen_loc = ui_ai_take_picture + using.layer = 20 + adding += using + +//View images + using = new /obj/screen() + using.name = "View Images" + using.icon = 'icons/mob/screen_ai.dmi' + using.icon_state = "view_images" + using.screen_loc = ui_ai_view_images + using.layer = 20 + adding += using + + mymob.client.screen += adding + other + + return \ No newline at end of file diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index e1ccf1732a6..c9a188d0c80 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -13,9 +13,6 @@ mymob.blind.screen_loc = "CENTER-7,CENTER-7" mymob.blind.layer = 0 -/datum/hud/proc/ai_hud() - return - /datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen_midnight.dmi') blobpwrdisplay = new /obj/screen() diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 42e54d75b39..58b96c7492e 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -290,6 +290,78 @@ if(istype(usr, /mob/living/silicon/robot)) usr:toggle_module(3) + if("AI Core") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.view_core() + + if("Show Camera List") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + var/camera = input(AI) in AI.get_camera_list() + AI.ai_camera_list(camera) + + if("Track With Camera") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + var/target_name = input(AI) in AI.trackable_mobs() + AI.ai_camera_track(target_name) + + if("Toggle Camera Light") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.toggle_camera_light() + + if("Crew Monitorting") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + crewmonitor(AI) + + if("Show Crew Manifest") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.ai_roster() + + if("Show Alerts") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.ai_alerts() + + if("Announcement") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.announcement() + + if("Call Emergency Shuttle") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.ai_call_shuttle() + + if("State Laws") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.checklaws() + + if("PDA - Send Message") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.cmd_send_pdamesg() + + if("PDA - Show Message Log") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.cmd_show_message_log() + + if("Take Image") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.aicamera.toggle_camera_mode() + + if("View Images") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + AI.aicamera.viewpictures() + else return 0 return 1 diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index f588e5146a3..3b99e47fd8e 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -22,9 +22,6 @@ /mob/living/silicon/ai/proc/ai_camera_list(var/camera in get_camera_list()) - set category = "AI Commands" - set name = "Show Camera List" - if(src.stat == 2) src << "You can't list the cameras because you are dead!" return @@ -101,10 +98,6 @@ return targets /mob/living/silicon/ai/proc/ai_camera_track(var/target_name in trackable_mobs()) - set category = "AI Commands" - set name = "Track With Camera" - set desc = "Select who you would like to track." - if(src.stat == 2) src << "You can't track with camera because you are dead!" return diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 7694275849a..0d14455d3ce 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -972,9 +972,7 @@ var/global/list/obj/item/device/pda/PDAs = list() //AI verb and proc for sending PDA messages. -/mob/living/silicon/ai/verb/cmd_send_pdamesg() - set category = "AI Commands" - set name = "PDA - Send Message" +/mob/living/silicon/ai/proc/cmd_send_pdamesg() var/list/names = list() var/list/plist = list() var/list/namecounts = list() @@ -1037,9 +1035,7 @@ var/global/list/obj/item/device/pda/PDAs = list() else usr << "You do not have a PDA. You should make an issue report about this." -/mob/living/silicon/ai/verb/cmd_show_message_log() - set category = "AI Commands" - set name = "PDA - Show Message Log" +/mob/living/silicon/ai/proc/cmd_show_message_log() if(usr.stat == 2) usr << "You can't do that because you are dead!" return diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f32dba73748..3eedd00b97c 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -90,8 +90,7 @@ var/list/ai_list = list() aicamera = new/obj/item/device/camera/ai_camera(src) if (istype(loc, /turf)) - verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ - /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ + verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ /mob/living/silicon/ai/proc/toggle_camera_light) @@ -182,9 +181,6 @@ var/list/ai_list = list() stat(null, text("Systems nonfunctional")) /mob/living/silicon/ai/proc/ai_alerts() - set category = "AI Commands" - set name = "Show Alerts" - var/dat = "Current Station Alerts\n" dat += "Close

" for (var/cat in alarms) @@ -218,8 +214,6 @@ var/list/ai_list = list() src << browse(dat, "window=aialerts&can_close=0") /mob/living/silicon/ai/proc/ai_roster() - set category = "AI Commands" - set name = "Show Crew Manifest" var/dat = "Crew RosterCrew Roster:

" for(var/datum/data/record/t in sortRecord(data_core.general)) @@ -229,13 +223,7 @@ var/list/ai_list = list() src << browse(dat, "window=airoster") onclose(src, "airoster") -/mob/living/silicon/ai/verb/ai_crew() - set category = "AI Commands" - set name = "Crew Monitoring Console" - crewmonitor(src) /mob/living/silicon/ai/proc/ai_call_shuttle() - set category = "AI Commands" - set name = "Call Emergency Shuttle" if(src.stat == 2) src << "You can't call the shuttle because you are dead!" return @@ -515,14 +503,6 @@ var/list/ai_list = list() if (viewalerts) ai_alerts() return !cleared -/mob/living/silicon/ai/cancel_camera() - set category = "AI Commands" - set name = "Cancel Camera View" - - //src.cameraFollow = null - src.view_core() - - //Replaces /mob/living/silicon/ai/verb/change_network() in ai.dm & camera.dm //Adds in /mob/living/silicon/ai/proc/ai_network_change() instead //Addition by Mord_Sith to define AI's network change ability @@ -650,9 +630,8 @@ var/list/ai_list = list() //Toggles the luminosity and applies it by re-entereing the camera. /mob/living/silicon/ai/proc/toggle_camera_light() - set name = "Toggle Camera Light" - set desc = "Toggles the light on the camera the AI is looking through." - set category = "AI Commands" + if(stat != CONSCIOUS) + return camera_light_on = !camera_light_on src << "Camera lights [camera_light_on ? "activated" : "deactivated"]." @@ -687,9 +666,3 @@ var/list/ai_list = list() src.current = camera src.current.SetLuminosity(AI_CAMERA_LUMINOSITY) camera_light_on = world.timeofday + 1 * 20 // Update the light every 2 seconds. - -/mob/living/silicon/ai/verb/outputlaws() - set category = "AI Commands" - set name = "State Laws" - - checklaws() diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index d1eb8e21c19..27d2b28b41a 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -92,14 +92,6 @@ // Return to the Core. - -/mob/living/silicon/ai/verb/core() - set category = "AI Commands" - set name = "AI Core" - - view_core() - - /mob/living/silicon/ai/proc/view_core() current = null diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index c3e8db720c1..d6906b3e2d2 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -63,12 +63,7 @@ var/const/VOX_DELAY = 600 popup.open() -/mob/living/silicon/ai/verb/announcement() - - set name = "Announcement" - set desc = "Create a vocal announcement by typing in the available words to create a sentence." - set category = "AI Commands" - +/mob/living/silicon/ai/proc/announcement() if(announcing_vox > world.time) src << "Please wait [round((announcing_vox - world.time) / 10)] seconds." return diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 087480c786c..3e7d015eafc 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -247,13 +247,8 @@ O.show_laws() O << "These laws may be changed by other players, or by you being the traitor." - O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle O.verbs += /mob/living/silicon/ai/proc/show_laws_verb - O.verbs += /mob/living/silicon/ai/proc/ai_camera_track - O.verbs += /mob/living/silicon/ai/proc/ai_alerts - O.verbs += /mob/living/silicon/ai/proc/ai_camera_list O.verbs += /mob/living/silicon/ai/proc/ai_statuschange - O.verbs += /mob/living/silicon/ai/proc/ai_roster O.job = "AI" diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 939c5328de5..c593cc727ad 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -113,21 +113,6 @@ name = "AI photo camera" var/in_camera_mode = 0 - verb/picture() - set category ="AI Commands" - set name = "Take Image" - set src in usr - - toggle_camera_mode() - - verb/viewpicture() - set category ="AI Commands" - set name = "View Images" - set src in usr - - viewpictures() - - /obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user) return diff --git a/icons/mob/screen_ai.dmi b/icons/mob/screen_ai.dmi new file mode 100644 index 0000000000000000000000000000000000000000..d0c18c20e53e2ca4443f665491781e61ec27c195 GIT binary patch literal 5982 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 literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 86fb4497c89..722352492d4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -68,6 +68,7 @@ #include "code\_onclick\overmind.dm" #include "code\_onclick\telekinesis.dm" #include "code\_onclick\hud\_defines.dm" +#include "code\_onclick\hud\ai.dm" #include "code\_onclick\hud\alien.dm" #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\hud.dm" From 09f2699f425bc5451f54ef2a4ac85219b8a3b658 Mon Sep 17 00:00:00 2001 From: Kelenius Date: Thu, 3 Jul 2014 19:33:46 +0400 Subject: [PATCH 08/17] Two fixes Double click made non-snowflake, cancel camera exploit patched --- code/_onclick/ai.dm | 2 -- code/modules/mob/living/silicon/ai/ai.dm | 3 +++ code/modules/mob/living/silicon/ai/freelook/eye.dm | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index b9d763fd883..c90a8c19dbb 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -10,8 +10,6 @@ Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner. */ /mob/living/silicon/ai/DblClickOn(var/atom/A, params) - if (istype(A, /obj/screen)) - return if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked build_click(src, client.buildmode, params, A) return diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 3eedd00b97c..77fcdf35b63 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -246,6 +246,9 @@ var/list/ai_list = list() return +/mob/living/silicon/ai/cancel_camera() + src.view_core() + /mob/living/silicon/ai/verb/toggle_anchor() set category = "AI Commands" set name = "Toggle Floor Bolts" diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 27d2b28b41a..0373da59133 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -61,7 +61,8 @@ var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && AI.client.eye == AI.eyeobj) AI.cameraFollow = null - AI.eyeobj.setLoc(src) + if (src.loc) + AI.eyeobj.setLoc(src) // This will move the AIEye. It will also cause lights near the eye to light up, if toggled. // This is handled in the proc below this one. From ec3d8164a8fe4373e008cd68f72128eae7eb1228 Mon Sep 17 00:00:00 2001 From: Kelenius Date: Thu, 3 Jul 2014 20:30:29 +0400 Subject: [PATCH 09/17] Now uses isturf --- code/modules/mob/living/silicon/ai/freelook/eye.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 0373da59133..a80d6a54271 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -61,7 +61,7 @@ var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && AI.client.eye == AI.eyeobj) AI.cameraFollow = null - if (src.loc) + if (isturf(src.loc) || isturf(src)) AI.eyeobj.setLoc(src) // This will move the AIEye. It will also cause lights near the eye to light up, if toggled. From 5c03b51879ba74be3f407ccf90bafc01bb5a9df9 Mon Sep 17 00:00:00 2001 From: Aranclanos Date: Fri, 4 Jul 2014 04:46:32 -0300 Subject: [PATCH 10/17] Office/rolling chairs will now work properly when carrying mobs, those will not slip out of the chair, becoming an ungrabless mobs. And the direction of the chair and mob will be better and easier to notice when they bump something. Their direction changes will work even better if mob movement code finally removes all the spawn() calls. I'm not planning of adding any special code for that here. --- .../structures/stool_bed_chair_nest/chairs.dm | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 381e14b33bd..9053517eb9a 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -8,7 +8,7 @@ src.verbs -= /atom/movable/verb/pull ..() spawn(3) //sorry. i don't think there's a better way to do this. - handle_rotation() + handle_layer() return /obj/structure/stool/bed/chair/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -33,22 +33,27 @@ rotate() return -/obj/structure/stool/bed/chair/proc/handle_rotation() //making this into a seperate proc so office chairs can call it on Move() - if(src.dir == NORTH) +/obj/structure/stool/bed/chair/proc/handle_rotation(direction) //making this into a seperate proc so office chairs can call it on Move() + if(buckled_mob) + buckled_mob.buckled = null //Temporary, so Move() succeeds. + if(!buckled_mob.Move(direction)) + buckled_mob.buckled = src + dir = buckled_mob.dir + return 0 + buckled_mob.buckled = src //Restoring + return 1 + +/obj/structure/stool/bed/chair/proc/handle_layer() + if(dir == NORTH) src.layer = FLY_LAYER else src.layer = OBJ_LAYER +/obj/structure/stool/bed/chair/proc/spin() + src.dir = turn(src.dir, 90) + handle_layer() if(buckled_mob) - if(buckled_mob.loc != src.loc) - buckled_mob.buckled = null //Temporary, so Move() succeeds. - if(!buckled_mob.Move(loc)) - unbuckle() - buckled_mob = null - else - buckled_mob.buckled = src //Restoring - if(buckled_mob) - buckled_mob.dir = dir + buckled_mob.dir = dir /obj/structure/stool/bed/chair/verb/rotate() set name = "Rotate Chair" @@ -56,18 +61,13 @@ set src in oview(1) if(config.ghost_interaction) - src.dir = turn(src.dir, 90) - handle_rotation() - return + spin() else if(!usr || !isturf(usr.loc)) return if(usr.stat || usr.restrained()) return - - src.dir = turn(src.dir, 90) - handle_rotation() - return + spin() /obj/structure/stool/bed/chair/MouseDrop_T(mob/M as mob, mob/user as mob) if(!istype(M)) return @@ -130,9 +130,10 @@ /obj/structure/stool/bed/chair/office anchored = 0 -/obj/structure/stool/bed/chair/office/Move() - ..() - handle_rotation() +/obj/structure/stool/bed/chair/office/Move(direction) + if(handle_rotation(direction)) + ..() + handle_layer() /obj/structure/stool/bed/chair/office/light icon_state = "officechair_white" From cdd91c27f67520cb0f515dcbcf23bbf2d268fccd Mon Sep 17 00:00:00 2001 From: AstralSerpent Date: Fri, 4 Jul 2014 21:34:34 +1000 Subject: [PATCH 11/17] Traitor code phrases/responses will be announced at round end. --- code/game/gamemodes/traitor/traitor.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 687b9490a46..c3273c5071c 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -250,7 +250,10 @@ text += "
" + text += "
The code phrases were: [syndicate_code_phrase]
\ + The code responses were: [syndicate_code_response]
" world << text + return 1 From 10c9d4d14e7225a892bbf1e8d65b71f5b9f9e3e8 Mon Sep 17 00:00:00 2001 From: AstralSerpent Date: Sun, 6 Jul 2014 02:33:13 +1000 Subject: [PATCH 12/17] Attacking augmented limbs or cyborgs with a welder on harm intent will actually harm. --- code/game/objects/items/weapons/tools.dm | 2 +- code/modules/mob/living/silicon/robot/robot.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index ae4c50b2ce0..6449a0ee712 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -171,7 +171,7 @@ var/obj/item/organ/limb/affecting = H.get_organ(check_zone(user.zone_sel.selecting)) - if(affecting.status == ORGAN_ROBOTIC) + if(affecting.status == ORGAN_ROBOTIC && user.a_intent != "harm") if(src.remove_fuel(0)) item_heal_robotic(H, user, 30, 0) return diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 23019c83f9e..5b94e9c637d 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -395,7 +395,7 @@ if (istype(W, /obj/item/weapon/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do return - if (istype(W, /obj/item/weapon/weldingtool)) + if (istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") var/obj/item/weapon/weldingtool/WT = W if (src == user) user << "You lack the reach to be able to repair yourself." From 5759e436af62479b31f8d0a86e5910c94c0d1789 Mon Sep 17 00:00:00 2001 From: Jordie0608 Date: Sun, 6 Jul 2014 16:14:58 +1000 Subject: [PATCH 13/17] Changed rules UI button to URL link, other URL touchup in config --- code/controllers/configuration.dm | 5 ++- config/config.txt | 5 ++- config/rules.html | 62 ------------------------------- interface/interface.dm | 14 ++++--- 4 files changed, 17 insertions(+), 69 deletions(-) delete mode 100644 config/rules.html diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index b9feeaa1124..cd20f995825 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -54,7 +54,8 @@ var/server var/banappeals var/wikiurl = "http://www.tgstation13.org/wiki" // Default wiki link. - var/forumurl + var/forumurl = "http://tgstation13.org/phpBB/index.php" //default forums + var/rulesurl = "http://www.tgstation13.org/wiki/Rules" // default rules var/forbid_singulo_possession = 0 var/useircbot = 0 @@ -243,6 +244,8 @@ config.wikiurl = value if("forumurl") config.forumurl = value + if("rulesurl") + config.rulesurl = value if("guest_jobban") config.guest_jobban = 1 if("guest_ban") diff --git a/config/config.txt b/config/config.txt index 5bfea844cab..5a516d59e5a 100644 --- a/config/config.txt +++ b/config/config.txt @@ -111,11 +111,14 @@ GUEST_BAN # SERVER ss13.example.com:2506 ## forum address -# FORUMURL http://justanotherday.example.com +# FORUMURL http://tgstation13.org/phpBB/index.php ## Wiki address # WIKIURL http://www.tgstation13.org/wiki +##Rules address +# RULESURL http://www.tgstation13.org/wiki/Rules + ## Ban appeals URL - usually for a forum or wherever people should go to contact your admins. # BANAPPEALS http://justanotherday.example.com diff --git a/config/rules.html b/config/rules.html deleted file mode 100644 index 4a41a7a333d..00000000000 --- a/config/rules.html +++ /dev/null @@ -1,62 +0,0 @@ - -Server Rules -There’s a lot here, but the gist of the rules is roleplay takes priority. Don’t metagame. Don’t play to win. Don’t be a jerk OOCly. If you don’t understand what those words mean or you need more detail, read on! -
-

Primary Policies

-
-
    -
    0. Admins may disregard any of these rules at their discretion when they feel its in the best interest of the current round/server/playerbase at large. They will, of course, be fully accountable for their actions should they choose to exercise this privilege.
    -
    -
    1.We’re all here to have a good time. If you’re intentionally trying to ruin everyone else’s good time, you won’t have a place here. Being a jerk in-character is fine to a point, but being a jerk out of character is not welcome at all.
    -
    -
    2. You are playing a game where you are not fully in control of everything. You will be put into situations beyond your control, which will result in some rounds being ruined for you. Man up and deal with it. However, if you are obviously griefed, be sure to report it to administrators by using the ‘adminhelp’ verb.
    -
    -
    3. This is a roleplaying game. The purpose of the game is to have fun roleplaying. Being an asshole, who ruins other player’s roleplay experience, just to win, is considered a ‘play-to-win’ style of playing. You can and will be banned for this playstyle. Be considerate of other players’ experience.
    -
    3b. (Suggested rewording) Randomly murdering people is generally considered to be ruining someone’s fun and poor form in roleplay. If you don’t have a solid IC reason for murder, you may be removed. Trying to justify it with ‘My character is so random/insane’ is not tolerated.
    -

    -
    4. IC information should be kept out of OOC channels and vice-versa.
    -
    -
    5. Don’t metagame. Do not ever use information, acquired out of character or through patterns or events your character would not be able to know, in game.
    -
    5b. (Suggested rewording) This game is developed by volunteers in their spare time. Do not expect perfection. If you find a bug or an exploit, report it via adminhelp. Abusing bugs or exploits is not allowed. This includes reacting to events or patterns, which your character would not be able to identify IC (metagaming).
    -

    -
    6. If you take up or are given a job, which is important for game progression (head of staff, AI, antagonist role), make sure you actually do that job. If you find yourself unable to do this due to real life circumstances, just let an admin know (adminhelp) before you leave, please.
    -
    -
    7. Speak like a normal person while in character. Don’t spam, either IC or OOC. Don’t use smileys, netspeak, etc. in IC speech.
    -
    -
    8. Erotic Roleplay is allowed, but some decency is expected. Keep it private. All involved players must consent. Unwelcome ERP will be punished harshly, usually with a permaban.
    -
    -
    9. Ingame administration has the final say in all ingame matters. If problems arise, you can report offending or abusive admins on the forums. If an admin says something was valid, it means it was valid. This is the admin’s way of saying it’s been investigated and found to not breaking any rules; The admin will not reveal ingame information.
    -
    -
    10. It should go without saying, but if you break the rules (or regularly come very close to breaking them i.e. “toeing the line”), you will be warned, muted, banned, or talked about rudely.
    - -
    -

    Additional Policies

    -

    Roleplay

    - Murder is justifiable as long as it was properly escalated. You can’t go from a single rude punch to a knife in the neck. You can, however, go from a single punch to a counter punch to a brawl to using weapons, and so on. Other IC justifications may exist for murder, but these are on a case by case basis. Minor aggravations like demotions, pranks, insults, or thefts are not adequate justification. - IC in OOC can be a no warning ban of 15 minutes, it can be longer if the IC in OOC is severe. To clarify, this is revealing anything about the current round that others can use in the OOC channel. If you are unsure do not say it. - Avoid using non character names. If you have a very offensive name or an obviously immersion breaking moniker like 'xenohunter360' you will be asked to change it. - As long as there is adequate IC backing and it doesn’t happen too often, assisting a traitor is within the rules. - Admins are not only allowed to run events or otherwise influence the course of rounds, they are encouraged to. They are as much GMs as they are enforcers of the rules, perhaps even moreso. - Persistent character relationships are acceptable, so long as they’re roleplayed out every round. Wordlessly assisting your OOC friends (or harming your OOC foes) ICly is NOT cool and will be addressed harshly. Roleplaying out your interactions will help you stay on the right side of the rules. How much or how little of previous “shifts” your character recalls is up to their discretion, with the caveat that being a known traitor doesn’t persist past the round it occurred in. - Griefing on the shuttle can also be a no warning ban scaling up from 15 minutes. Shuttle griefing is attacking people or preventing people boarding before the shuttle has launched for no IC reason. -
    - -

    Silicons

    - All Silicons are expected to follow their laws to the best of their ability. Failure to do so will likely result in a job ban from all silicon positions. - Law order determines law priority. In the case of two laws contradicting, the one with the smaller law number wins. - Asimov silicons are not required to do what players who threaten self-harm demand, unless they choose to interpret law 1 to include that. -
    - -

    Command/Security

    - Security are expected to use non-lethal force when defending against non-lethal attacks. This of course also means that security are allowed the option to use lethal force when defending against lethal attacks. Getting stunned in a dark maintenance hallway by an assistant is potentially lethal - a clown slipping you outside Medbay, probably not. - Permabrigging is functionally the same as murder. Anyone who is valid for execution is valid for permabrigging. Anyone who is not justifiably executable is, likewise, not justifiably a candidate for permabrigging. Makeshift permabrigs are treated the same as the official permabrig in terms of rules-enforcement. - A Captain or acting Captain may execute criminals, traitors, and other known threats to the station should alternatives not prove sufficient. Abuse or misuse of this privilege can lead to job banning or worse. - Theft, assault, annoyance, false arrest, sentence times etc. are in character matters. Unless it is extremely excessive or griefy, it is not an admin matter. -
    - -

    Admin-help

    - When you adminhelp do not say things like 'is it valid?' or 'being griefed', give details of what is happening and ideally who is doing it, job and character name. - If you see someone doing something that seems out of line adminhelp right then, do not wait until round end to see if they are a traitor then adminhelp next round. It makes it a lot harder to deal with. - Do not lie in PM's and avoid being aggressive, unhelpful or insulting to admins, lying while being questioned over an incident will cause you to receive a longer ban and being consistently insulting or aggressive will get you muted. - - \ No newline at end of file diff --git a/interface/interface.dm b/interface/interface.dm index 4e4aa598e2f..cde3478cd4a 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -3,7 +3,7 @@ set name = "wiki" set desc = "Visit the wiki." set hidden = 1 - if( config.wikiurl ) + if(config.wikiurl) if(alert("This will open the wiki in your browser. Are you sure?",,"Yes","No")=="No") return src << link(config.wikiurl) @@ -15,7 +15,7 @@ set name = "forum" set desc = "Visit the forum." set hidden = 1 - if( config.forumurl ) + if(config.forumurl) if(alert("This will open the forum in your browser. Are you sure?",,"Yes","No")=="No") return src << link(config.forumurl) @@ -23,13 +23,17 @@ src << "\red The forum URL is not set in the server configuration." return -#define RULES_FILE "config/rules.html" /client/verb/rules() set name = "Rules" set desc = "Show Server Rules." set hidden = 1 - src << browse(file(RULES_FILE), "window=rules;size=480x320") -#undef RULES_FILE + if(config.rulesurl) + if(alert("This will open the rules in your browser. Are you sure?",,"Yes","No")=="No") + return + src << link(config.rulesurl) + else + src << "\red The rules URL is not set in the server configuration." + return /client/verb/hotkeys_help() set name = "hotkeys-help" From 6843a9b166d158cf3f7a4bde52f9bd82c3df0c0a Mon Sep 17 00:00:00 2001 From: Jordie0608 Date: Sun, 6 Jul 2014 16:29:21 +1000 Subject: [PATCH 14/17] Replaced red with span --- interface/interface.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/interface.dm b/interface/interface.dm index cde3478cd4a..979c4abae41 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -8,7 +8,7 @@ return src << link(config.wikiurl) else - src << "\red The wiki URL is not set in the server configuration." + src << "The wiki URL is not set in the server configuration." return /client/verb/forum() @@ -20,7 +20,7 @@ return src << link(config.forumurl) else - src << "\red The forum URL is not set in the server configuration." + src << "The forum URL is not set in the server configuration." return /client/verb/rules() @@ -32,7 +32,7 @@ return src << link(config.rulesurl) else - src << "\red The rules URL is not set in the server configuration." + src << "The rules URL is not set in the server configuration." return /client/verb/hotkeys_help() From bb5fa83c199a62d257db2596103ad5b3be13e2f2 Mon Sep 17 00:00:00 2001 From: AstralSerpent Date: Sun, 6 Jul 2014 17:47:56 +1000 Subject: [PATCH 15/17] Now bots can get harmed with welders too. --- code/game/machinery/bots/bots.dm | 2 +- code/game/machinery/bots/secbot.dm | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 3548b15de45..5c0c30aecc1 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -80,7 +80,7 @@ if(!locked) open = !open user << "Maintenance panel is now [src.open ? "opened" : "closed"]." - else if(istype(W, /obj/item/weapon/weldingtool)) + else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") if(health < maxhealth) if(open) health = min(maxhealth, health+10) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 42c365e5b6c..278ed06a1db 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -206,7 +206,9 @@ Auto Patrol: []"}, user << "\red Access denied." else ..() - if(!istype(W, /obj/item/weapon/screwdriver) && !istype(W, /obj/item/weapon/weldingtool) && (W.force) && (!src.target)) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. + if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry. + return + if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!src.target) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. threatlevel = user.assess_threat(src) threatlevel += 6 if(threatlevel > 0) From 1b5bbb85277964a2898635d707cc7916988eae81 Mon Sep 17 00:00:00 2001 From: Ikarrus Date: Sun, 6 Jul 2014 10:44:50 -0600 Subject: [PATCH 16/17] Added some clarification in comments --- code/game/jobs/job_controller.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index c01c0a08ba3..4b2bc0eabbb 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -113,7 +113,7 @@ var/global/datum/controller/occupations/job_master return -//This proc is called before the level loop of DivideOccupations() and will try to select a head, ignoring ALL non-head preferences for every level until´ +//This proc is called before the level loop of DivideOccupations() and will try to select a head, ignoring ALL non-head preferences for every level until� //it locates a head or runs out of levels to check //This is basically to ensure that there's atleast a few heads in the round /datum/controller/occupations/proc/FillHeadPosition() @@ -315,13 +315,13 @@ var/global/datum/controller/occupations/job_master var/officer_positions = 5 //Number of open security officer positions at round start if(config.security_scaling_coeff > 0) - officer_positions = min(12, max(5, (unassigned.len/config.security_scaling_coeff))) + officer_positions = min(12, max(5, (unassigned.len/config.security_scaling_coeff))) //Scale between 5 and 12 officers var/datum/job/J = job_master.GetJob("Security Officer") if(J || J.spawn_positions > 0) Debug("Setting open security officer positions to [officer_positions]") J.total_positions = officer_positions J.spawn_positions = officer_positions - for(var/i=officer_positions-5, i>1, i--) //Spawn some extra lockers if we don't have enough + for(var/i=officer_positions-5, i>0, i--) //Spawn some extra eqipment lockers if we have more than 5 officers if(secequipment.len) var/spawnloc = secequipment[1] new /obj/structure/closet/secure_closet/security(spawnloc) From e9d21242200cf259bd62f1348d226aa78867d06a Mon Sep 17 00:00:00 2001 From: Kelenius Date: Sun, 6 Jul 2014 21:33:05 +0400 Subject: [PATCH 17/17] usr -> user --- code/_onclick/hud/screen_objects.dm | 4 ++-- code/game/objects/items/devices/PDA/PDA.dm | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 58b96c7492e..d5e44761d63 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -345,12 +345,12 @@ if("PDA - Send Message") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.cmd_send_pdamesg() + AI.cmd_send_pdamesg(usr) if("PDA - Show Message Log") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.cmd_show_message_log() + AI.cmd_show_message_log(usr) if("Take Image") if(isAI(usr)) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 0d14455d3ce..44fcfb24521 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -972,17 +972,17 @@ var/global/list/obj/item/device/pda/PDAs = list() //AI verb and proc for sending PDA messages. -/mob/living/silicon/ai/proc/cmd_send_pdamesg() +/mob/living/silicon/ai/proc/cmd_send_pdamesg(mob/user as mob) var/list/names = list() var/list/plist = list() var/list/namecounts = list() - if(usr.stat == 2) - usr << "You can't send PDA messages because you are dead!" + if(user.stat == 2) + user << "You can't send PDA messages because you are dead!" return if(src.aiPDA.toff) - usr << "Turn on your receiver in order to send messages." + user << "Turn on your receiver in order to send messages." return for (var/obj/item/device/pda/P in get_viewable_pdas()) @@ -1001,7 +1001,7 @@ var/global/list/obj/item/device/pda/PDAs = list() plist[text("[name]")] = P - var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) + var/c = input(user, "Please select a PDA") as null|anything in sortList(plist) if (!c) return @@ -1035,15 +1035,15 @@ var/global/list/obj/item/device/pda/PDAs = list() else usr << "You do not have a PDA. You should make an issue report about this." -/mob/living/silicon/ai/proc/cmd_show_message_log() - if(usr.stat == 2) - usr << "You can't do that because you are dead!" +/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user as mob) + if(user.stat == 2) + user << "You can't do that because you are dead!" return if(!isnull(aiPDA)) var/HTML = "AI PDA Message Log[aiPDA.tnote]" - usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") + user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") else - usr << "You do not have a PDA. You should make an issue report about this." + user << "You do not have a PDA. You should make an issue report about this." //Some spare PDAs in a box /obj/item/weapon/storage/box/PDAs