From 810ca147d071992a61e5b3cc627ba8b1de7f1b38 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 12 Sep 2015 19:34:43 -0400 Subject: [PATCH 001/207] Fixes #10710 --- code/modules/lighting/light_source.dm | 48 ++++++++++++++++----------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/code/modules/lighting/light_source.dm b/code/modules/lighting/light_source.dm index 2acddb4d298..3675cd945c3 100644 --- a/code/modules/lighting/light_source.dm +++ b/code/modules/lighting/light_source.dm @@ -1,3 +1,5 @@ +//So much copypasta in this file, supposedly in the name of performance. If you change anything make sure to consider other places where the code may have been copied. + /datum/light_source var/atom/top_atom var/atom/source_atom @@ -11,9 +13,10 @@ var/lum_g var/lum_b - var/tmp/old_lum_r - var/tmp/old_lum_g - var/tmp/old_lum_b + //hold onto the actual applied lum values so we can undo them when the lighting changes + var/tmp/applied_lum_r + var/tmp/applied_lum_g + var/tmp/applied_lum_b var/list/effect_str var/list/effect_turf @@ -107,11 +110,6 @@ if(light_range && light_power && !applied) . = 1 - if(. || source_atom.light_color != light_color)//Save the old lumcounts if we need to update, if the colour changed DO IT BEFORE we parse the colour and LOSE the old lumcounts! - old_lum_r = lum_r - old_lum_g = lum_g - old_lum_b = lum_b - if(source_atom.light_color != light_color) light_color = source_atom.light_color parse_light_color() @@ -149,6 +147,12 @@ /datum/light_source/proc/apply_lum() applied = 1 + + //Keep track of the last applied lum values so that the lighting can be reversed + applied_lum_r = lum_r + applied_lum_g = lum_g + applied_lum_b = lum_b + if(istype(source_turf)) FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING) if(T.lighting_overlay) @@ -164,9 +168,9 @@ effect_str += strength T.lighting_overlay.update_lumcount( - lum_r * strength, - lum_g * strength, - lum_b * strength + applied_lum_r * strength, + applied_lum_g * strength, + applied_lum_b * strength ) else @@ -188,7 +192,11 @@ if(T.lighting_overlay) var/str = effect_str[i] - T.lighting_overlay.update_lumcount(-str * old_lum_r, -str * old_lum_g, -str * old_lum_b) + T.lighting_overlay.update_lumcount( + -str * applied_lum_r, + -str * applied_lum_g, + -str * applied_lum_b + ) i++ @@ -218,9 +226,9 @@ effect_str += . T.lighting_overlay.update_lumcount( - lum_r * ., - lum_g * ., - lum_b * . + applied_lum_r * ., + applied_lum_g * ., + applied_lum_b * . ) else @@ -241,7 +249,7 @@ if(T.lighting_overlay) var/str = effect_str[idx] - T.lighting_overlay.update_lumcount(-str * lum_r, -str * lum_g, -str * lum_b) + T.lighting_overlay.update_lumcount(-str * applied_lum_r, -str * applied_lum_g, -str * applied_lum_b) effect_turf.Cut(idx, idx + 1) effect_str.Cut(idx, idx + 1) @@ -279,10 +287,12 @@ effect_str[idx] = . + //Since the applied_lum values are what are (later) removed by remove_lum. + //Anything we apply to the lighting overlays HAS to match what remove_lum uses. T.lighting_overlay.update_lumcount( - lum_r * ., - lum_g * ., - lum_b * . + applied_lum_r * ., + applied_lum_g * ., + applied_lum_b * . ) #undef LUM_FALLOFF From a938c7b64846f40c5c0e6e381424d6fcd1fefbbf Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Sun, 13 Sep 2015 11:21:44 +0200 Subject: [PATCH 002/207] Prevents observer mice from spawning on the admin Z-level. --- code/modules/mob/dead/observer/observer.dm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 2b4a290e2bf..e58df4f1f93 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -422,6 +422,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!MayRespawn(1)) return + var/turf/T = get_turf(src) + if(!T || (T.z in config.admin_levels)) + src << "You may not spawn as a mouse on this Z-level." + return + var/timedifference = world.time - client.time_died_as_mouse if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600) var/timedifference_text @@ -437,8 +442,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/mob/living/simple_animal/mouse/host var/obj/machinery/atmospherics/unary/vent_pump/vent_found var/list/found_vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/v in world) - if(!v.welded && v.z == src.z) + for(var/obj/machinery/atmospherics/unary/vent_pump/v in machines) + if(!v.welded && v.z == T.z) found_vents.Add(v) if(found_vents.len) vent_found = pick(found_vents) From eef1013db2fea16fda2e3d14550c3bf3d623314b Mon Sep 17 00:00:00 2001 From: Kelenius Date: Mon, 14 Sep 2015 16:54:24 +0300 Subject: [PATCH 003/207] Fixes #10925 Makes psilocybin less robust, also cuts down emote spam --- .../Chemistry-Reagents-Toxins.dm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index fcf2f658a0a..7b604158a51 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -416,21 +416,21 @@ if(dose < 1) M.stuttering = max(M.stuttering, 3) M.make_dizzy(5) - if(prob(10)) + if(prob(5)) M.emote(pick("twitch", "giggle")) else if(dose < 2) M.stuttering = max(M.stuttering, 3) - M.make_jittery(10) - M.make_dizzy(10) + M.make_jittery(5) + M.make_dizzy(5) M.druggy = max(M.druggy, 35) - if(prob(20)) - M.emote(pick("twitch","giggle")) + if(prob(10)) + M.emote(pick("twitch", "giggle")) else M.stuttering = max(M.stuttering, 3) - M.make_jittery(20) - M.make_dizzy(20) + M.make_jittery(10) + M.make_dizzy(10) M.druggy = max(M.druggy, 40) - if(prob(30)) + if(prob(15)) M.emote(pick("twitch", "giggle")) /datum/reagent/nicotine From 52b51a6be47208cd80027e7ea5d4f23bc159b886 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Tue, 15 Sep 2015 13:24:11 +0100 Subject: [PATCH 004/207] fix #11061 --- code/game/atoms.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 83a5657f1cf..2cf913f7a95 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -413,7 +413,7 @@ its easier to just keep the beam vertical. return src.germ_level = 0 if(istype(blood_DNA, /list)) - blood_DNA.Cut() + blood_DNA = null return 1 From f65649c8ba2d2bad88c07f97dd842a7ef2c9d085 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 17 Sep 2015 09:40:19 +0200 Subject: [PATCH 005/207] Fixes Pun-Pun (and other monkeys) pushing people around. At some point a return had snuck in before the mob-push/swap flag settings. I blame a merge. Relocated that code to handle_post_spawn() to hopefully ensure it'll always fire when appropriate. --- code/modules/mob/living/carbon/human/human.dm | 4 ---- code/modules/mob/living/carbon/human/species/species.dm | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index cbc8faabd7b..1ebbd792c6e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1165,10 +1165,6 @@ else return 0 - mob_bump_flag = species.bump_flag - mob_swap_flags = species.swap_flags - mob_push_flags = species.push_flags - /mob/living/carbon/human/proc/bloody_doodle() set category = "IC" set name = "Write in blood" diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 9f171054b98..313fa2e1c77 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -255,6 +255,9 @@ /datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. add_inherent_verbs(H) + H.mob_bump_flag = bump_flag + H.mob_swap_flags = swap_flags + H.mob_push_flags = push_flags /datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). return From 54bfad99b8e7b45e496e9070c85a8b7b2ee5a723 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Fri, 18 Sep 2015 16:05:51 +0200 Subject: [PATCH 006/207] Removes excess holopad. Fixes #11131. --- maps/exodus-1.dmm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index 27239f6e4e5..53b559a5b06 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -6617,7 +6617,7 @@ "cxm" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 8},/obj/structure/sign/deathsposal{pixel_x = 0; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor{icon_state = "whitehall"; dir = 1},/area/rnd/xenobiology) "cxn" = (/obj/structure/table/standard,/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped,/obj/item/weapon/reagent_containers/spray/cleaner,/obj/item/clothing/gloves/latex,/obj/item/device/slime_scanner,/obj/item/device/slime_scanner,/obj/item/weapon/hand_labeler,/turf/simulated/floor{icon_state = "white"},/area/rnd/xenobiology) "cxo" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/visible,/turf/simulated/floor,/area/engineering/atmos) -"cxp" = (/obj/machinery/atmospherics/unary/freezer{dir = 2; icon_state = "freezer"},/obj/machinery/hologram/holopad,/turf/simulated/floor{icon_state = "bot"; dir = 1},/area/engineering/atmos) +"cxp" = (/obj/machinery/atmospherics/unary/freezer{dir = 2; icon_state = "freezer"},/turf/simulated/floor{icon_state = "bot"; dir = 1},/area/engineering/atmos) "cxq" = (/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/engineering/atmos) "cxr" = (/obj/structure/disposalpipe/sortjunction/flipped{dir = 8; sortType = "Drone Fabrication"; name = "Drone Fabrication"},/turf/simulated/floor,/area/engineering/atmos) "cxs" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/firedoor/border_only{dir = 1; name = "Engineering Firelock"},/obj/machinery/door/airlock/glass_atmos{name = "Atmospherics"; req_access = list(24)},/turf/simulated/floor,/area/engineering/atmos) From 924359d858593be4a8a98e62e1a42588a9b9261d Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 19 Sep 2015 09:30:08 +0200 Subject: [PATCH 007/207] Backports map merge fix. --- tools/mapmerge/mapmerge.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mapmerge/mapmerge.sh b/tools/mapmerge/mapmerge.sh index 145537f7ca7..9e347ceaa2a 100755 --- a/tools/mapmerge/mapmerge.sh +++ b/tools/mapmerge/mapmerge.sh @@ -4,6 +4,6 @@ then echo "Unable to automatically resolve map conflicts, please merge manually." exit 1 fi -java -jar tools/mapmerge/MapPatcher.jar -clean $1 $2 $2 +java -jar tools/mapmerge/MapPatcher.jar -clean $3 $2 $2 exit 0 From 4eef7ab65da4ba431de203b01bcb39fe84139fc3 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Sat, 19 Sep 2015 15:27:24 +0200 Subject: [PATCH 008/207] Fixes beds occasionally buckling in odd directions --- code/game/objects/buckling.dm | 3 ++- code/game/objects/structures/stool_bed_chair_nest/bed.dm | 1 + code/game/objects/structures/stool_bed_chair_nest/chairs.dm | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 6b79db8f5b4..93c2fd57bbb 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -1,6 +1,7 @@ /obj var/can_buckle = 0 var/buckle_movable = 0 + var/buckle_dir = 0 var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1 var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes var/mob/living/buckled_mob = null @@ -31,7 +32,7 @@ M.buckled = src M.facing_dir = null - M.set_dir(dir) + M.set_dir(buckle_dir ? buckle_dir : dir) M.update_canmove() buckled_mob = M post_buckle_mob(M) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 3067b70d361..c6bdfaf05fa 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -15,6 +15,7 @@ pressure_resistance = 15 anchored = 1 can_buckle = 1 + buckle_dir = SOUTH buckle_lying = 1 var/material/material var/material/padding_material 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 1d6ae5ed583..ae4fe4d7401 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -4,6 +4,7 @@ icon_state = "chair_preview" color = "#666666" base_icon = "chair" + buckle_dir = 0 buckle_lying = 0 //force people to sit up in chairs when buckled var/propelled = 0 // Check for fire-extinguisher-driven chairs From 9b6d2d6e970e4396827f139821f1ce30a7d77b55 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 21 Sep 2015 12:08:54 +0200 Subject: [PATCH 009/207] Map tweaks. Restores chemistry windoor access. Fixes #11160. Makes xenobiology nanomed dispenser all access. Fixes #11163. --- maps/exodus-1.dmm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index 53b559a5b06..c755ae460ff 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -3519,7 +3519,7 @@ "bpI" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "bpJ" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "bpK" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor,/area/hallway/secondary/entry/aft) -"bpL" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/blast/shutters{density = 0; dir = 4; icon_state = "shutter0"; id = "chemcounter"; name = "Pharmacy Counter Shutters"; opacity = 0},/obj/structure/table/reinforced,/obj/machinery/door/window/westright{name = "Chemistry Desk"},/turf/simulated/floor{icon_state = "yellowfull"; dir = 8},/area/medical/chemistry) +"bpL" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/blast/shutters{density = 0; dir = 4; icon_state = "shutter0"; id = "chemcounter"; name = "Pharmacy Counter Shutters"; opacity = 0},/obj/structure/table/reinforced,/obj/machinery/door/window/westright{name = "Chemistry Desk"; req_access = list(33)},/obj/machinery/door/window/westright{name = "Chemistry Desk"; req_access = list(33)},/turf/simulated/floor{icon_state = "yellowfull"; dir = 8},/area/medical/chemistry) "bpM" = (/obj/item/weapon/stool/padded,/turf/simulated/floor{tag = "icon-whiteblue (EAST)"; icon_state = "whiteblue"; dir = 4},/area/medical/reception) "bpN" = (/obj/structure/table/standard,/obj/item/weapon/autopsy_scanner,/obj/item/weapon/scalpel,/turf/simulated/floor{icon_state = "blue"; dir = 8},/area/medical/morgue) "bpO" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/cable/cyan,/turf/simulated/floor/plating,/area/turret_protected/ai_upload) @@ -6690,7 +6690,7 @@ "cyH" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera/network/medbay{c_tag = "Virology Starboard"; dir = 8},/turf/simulated/floor{icon_state = "white"},/area/medical/virology) "cyI" = (/obj/machinery/space_heater,/turf/simulated/floor,/area/engineering/atmos/storage) "cyJ" = (/obj/structure/table/standard,/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/storage/box/monkeycubes,/turf/simulated/floor{icon_state = "white"},/area/medical/virology) -"cyK" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/vending/wallmed1{name = "Emergency NanoMed"; pixel_x = -7; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/obj/structure/extinguisher_cabinet{pixel_x = 7; pixel_y = -32},/turf/simulated/floor,/area/rnd/xenobiology) +"cyK" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/vending/wallmed1{name = "Emergency NanoMed"; pixel_x = -7; pixel_y = -32; req_access = newlist()},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/obj/structure/extinguisher_cabinet{pixel_x = 7; pixel_y = -32},/turf/simulated/floor,/area/rnd/xenobiology) "cyL" = (/obj/structure/table/standard,/obj/item/weapon/circular_saw,/obj/item/weapon/scalpel{pixel_y = 12},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 8},/turf/simulated/floor,/area/rnd/xenobiology) "cyM" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/visible/green,/turf/simulated/floor,/area/engineering/atmos) "cyN" = (/obj/machinery/atmospherics/trinary/mixer,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) From ebaa452c4c2492b2228b4d2dfb54719f72f7a361 Mon Sep 17 00:00:00 2001 From: Daranz Date: Mon, 21 Sep 2015 15:37:22 +0200 Subject: [PATCH 010/207] Fix spelling: 'its' in place of 'it's' --- code/game/gamemodes/malfunction/malf_hardware.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/malfunction/malf_hardware.dm b/code/game/gamemodes/malfunction/malf_hardware.dm index fab329ff583..b33a5e49d8d 100644 --- a/code/game/gamemodes/malfunction/malf_hardware.dm +++ b/code/game/gamemodes/malfunction/malf_hardware.dm @@ -34,7 +34,7 @@ desc = "Secondary coprocessor that increases amount of generated CPU power by 50%" /datum/malf_hardware/dual_cpu/get_examine_desc() - return "It seems to have an additional CPU connected to it's core." + return "It seems to have an additional CPU connected to its core." /datum/malf_hardware/dual_ram name = "Secondary Memory Bank" From 280c932add6460991e514abec535699f3417ce00 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 23 Sep 2015 12:26:53 +0100 Subject: [PATCH 011/207] fix traitor AIs not getting a law zero --- code/game/antagonist/station/traitor.dm | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm index d00668753ec..de5a12b01d2 100644 --- a/code/game/antagonist/station/traitor.dm +++ b/code/game/antagonist/station/traitor.dm @@ -73,19 +73,19 @@ var/datum/antagonist/traitor/traitors return /datum/antagonist/traitor/equip(var/mob/living/carbon/human/traitor_mob) + if(istype(traitor_mob, /mob/living/silicon)) // this needs to be here because ..() returns false if the mob isn't human + add_law_zero(traitor_mob) + return 1 if(!..()) return 0 - if(istype(traitor_mob, /mob/living/silicon)) - add_law_zero(traitor_mob) - else - spawn_uplink(traitor_mob) - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && M != traitor_mob) - traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." - traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + spawn_uplink(traitor_mob) + // Tell them about people they might want to contact. + var/mob/living/carbon/human/M = get_nt_opposed() + if(M && M != traitor_mob) + traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." + traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") //Begin code phrase. give_codewords(traitor_mob) @@ -169,4 +169,4 @@ var/datum/antagonist/traitor/traitors var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws." killer << "Your laws have been changed!" killer.set_zeroth_law(law, law_borg) - killer << "New law: 0. [law]" \ No newline at end of file + killer << "New law: 0. [law]" From c707519d1f21c604822b0d0cf5525d6815a383d6 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 23 Sep 2015 12:56:39 +0100 Subject: [PATCH 012/207] Add specific color for expired bans in ban panel, fix some formatting and a runtime --- code/modules/admin/DB ban/functions.dm | 24 +++++++++++++++++++----- code/modules/admin/topic.dm | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index cc26d7153de..d07386c4472 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -349,6 +349,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/bdcolor = "#ffdddd" //banned dark var/ulcolor = "#eeffee" //unbanned light var/udcolor = "#ddffdd" //unbanned dark + var/alcolor = "#eeeeff" // auto-unbanned light + var/adcolor = "#ddddff" // auto-unbanned dark output += "" output += "" @@ -400,6 +402,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM erro_ban WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100") select_query.Execute() + var/now = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") // MUST BE the same format as SQL gives us the dates in, and MUST be least to most specific (i.e. year, month, day not day, month, year) + while(select_query.NextRow()) var/banid = select_query.item[1] var/bantime = select_query.item[2] @@ -417,36 +421,42 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/ip = select_query.item[14] var/cid = select_query.item[15] + // true if this ban has expired + var/auto = now > expiration // oh how I love ISO 8601 (ish) date strings + var/lcolor = blcolor var/dcolor = bdcolor if(unbanned) lcolor = ulcolor dcolor = udcolor + else if(auto) + lcolor = alcolor + dcolor = adcolor var/typedesc ="" switch(bantype) if("PERMABAN") typedesc = "PERMABAN" if("TEMPBAN") - typedesc = "TEMPBAN
([duration] minutes [(unbanned) ? "" : "(Edit))"]
Expires [expiration]
" + typedesc = "TEMPBAN
([duration] minutes) [(unbanned || auto) ? "" : "(Edit)"]
Expires [expiration]
" if("JOB_PERMABAN") typedesc = "JOBBAN
([job])" if("JOB_TEMPBAN") - typedesc = "TEMP JOBBAN
([job])
([duration] minutes
Expires [expiration]" + typedesc = "TEMP JOBBAN
([job])
([duration] minutes)
Expires [expiration]" output += "
" output += "" output += "" output += "" output += "" - output += "" + output += "" output += "" output += "" output += "" output += "" output += "" output += "" - output += "" + output += "" output += "" if(edits) output += "" @@ -459,10 +469,14 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" output += "" output += "" + if(auto) + output += "" + output += "" + output += "" output += "" output += "" output += "" output += "
[typedesc][ckey][bantime][ackey][(unbanned) ? "" : "Unban"][(unbanned || auto) ? "" : "Unban"]
IP: [ip]CIP: [cid]
Reason: [(unbanned) ? "" : "(Edit)"] \"[reason]\"Reason: [(unbanned || auto) ? "" : "(Edit)"] \"[reason]\"
UNBANNED by admin [unbanckey] on [unbantime]
EXPIRED at [expiration]
 
" - usr << browse(output,"window=lookupbans;size=900x700") \ No newline at end of file + usr << browse(output,"window=lookupbans;size=900x700") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index e60a830086a..983292ebc36 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -85,7 +85,7 @@ banreason = "[banreason] (CUSTOM CID)" else message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom ip and computer id fields replaced with the ip and computer id from the located mob") - notes_add(playermob.ckey,banreason,usr) + notes_add(banckey,banreason,usr) DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid ) From 9be47c6374310f177d79610394b1fbbd965367d8 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 23 Sep 2015 13:03:11 +0100 Subject: [PATCH 013/207] Permabans do not expire, and we don't need to show expired when it's been manually lifted --- code/modules/admin/DB ban/functions.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index d07386c4472..8e1ad3aa798 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -422,7 +422,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/cid = select_query.item[15] // true if this ban has expired - var/auto = now > expiration // oh how I love ISO 8601 (ish) date strings + var/auto = (bantype in list("TEMPBAN", "JOB_TEMPBAN")) && now > expiration // oh how I love ISO 8601 (ish) date strings var/lcolor = blcolor var/dcolor = bdcolor @@ -469,7 +469,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" output += "UNBANNED by admin [unbanckey] on [unbantime]" output += "" - if(auto) + else if(auto) output += "" output += "EXPIRED at [expiration]" output += "" From 8ed4faf7b2c17f45af5c60ddef6be59625c4aa3d Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 23 Sep 2015 13:29:54 +0100 Subject: [PATCH 014/207] Add proc/crash_with, fix two incorrect qdel calls --- code/__HELPERS/unsorted.dm | 4 ++++ code/controllers/Processes/garbage.dm | 1 + code/game/atoms_movable.dm | 6 +----- code/modules/admin/player_notes.dm | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 8b58d5edde7..7122d32f852 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1309,3 +1309,7 @@ var/mob/dview/dview_mob = new /mob/dview/New() // do nothing. we don't want to be in any mob lists; we're a dummy not a mob. + +// call to generate a stack trace and print to runtime logs +/proc/crash_with(msg) + CRASH(msg) diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm index b3f1917f6b2..b2349213b72 100644 --- a/code/controllers/Processes/garbage.dm +++ b/code/controllers/Processes/garbage.dm @@ -91,6 +91,7 @@ var/list/delayed_garbage = list() return if(!istype(A)) warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.") + crash_with("qdel() passed object of type [A.type]. qdel() can only handle /datum types.") del(A) if(garbage_collector) garbage_collector.dels++ diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index c339459fe56..8fd660ec521 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -21,14 +21,10 @@ if(auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING) initialize() -/proc/generate_debug_runtime() // Guaranteed to runtime and print a stack trace to the runtime log - var/t = 0 // BYOND won't let us do var/t = 1/0 directly, but it's fine with this. - t = 1 / t - /atom/movable/Del() if(isnull(gcDestroyed) && loc) testing("GC: -- [type] was deleted via del() rather than qdel() --") - generate_debug_runtime() // stick a stack trace in the runtime logs + crash_with("GC: -- [type] was deleted via del() rather than qdel() --") // stick a stack trace in the runtime logs // else if(isnull(gcDestroyed)) // testing("GC: [type] was deleted via GC without qdel()") //Not really a huge issue but from now on, please qdel() // else diff --git a/code/modules/admin/player_notes.dm b/code/modules/admin/player_notes.dm index 4a28ece9151..b6293e7941d 100644 --- a/code/modules/admin/player_notes.dm +++ b/code/modules/admin/player_notes.dm @@ -106,7 +106,7 @@ datum/admins/proc/notes_gethtml(var/ckey) message_admins("\blue [key_name_admin(user)] has edited [key]'s notes.") log_admin("[key_name(user)] has edited [key]'s notes.") - qdel(info) + del(info) // savefile, so NOT qdel //Updating list of keys with notes on them var/savefile/note_list = new("data/player_notes.sav") @@ -115,7 +115,7 @@ datum/admins/proc/notes_gethtml(var/ckey) if(!note_keys) note_keys = list() if(!note_keys.Find(key)) note_keys += key note_list << note_keys - qdel(note_list) + del(note_list) // savefile, so NOT qdel /proc/notes_del(var/key, var/index) From 76f06e6e9b1a920ff5a0e8a8922a3cd95036acc0 Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Wed, 23 Sep 2015 13:29:54 +0100 Subject: [PATCH 015/207] Gave Asset Protection their proper rig Fairly self explanatory. --- code/game/antagonist/outsider/deathsquad.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index 2740adf8ae2..cbb57abe1ab 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -47,7 +47,7 @@ var/datum/antagonist/deathsquad/deathsquad player.equip_to_slot_or_del(new /obj/item/weapon/plastique(player), slot_l_store) player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(player), slot_belt) player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand) - player.equip_to_slot_or_del(new /obj/item/weapon/rig/combat(player), slot_back) + player.equip_to_slot_or_del(new /obj/item/weapon/rig/ert/assetprotection(player), slot_back) player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store) player.implant_loyalty(player) From f0481b551e8ae66c725e2a0c0a1ea68cf813cedc Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Fri, 25 Sep 2015 21:49:39 +0200 Subject: [PATCH 016/207] Fixes grab-buckling overwriting pixelshift --- .../structures/stool_bed_chair_nest/bed.dm | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index c6bdfaf05fa..6c3db50c877 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -132,14 +132,18 @@ remove_padding() else if(istype(W, /obj/item/weapon/grab)) - user.visible_message("[user] attempts to buckle [W:affecting] into \the [src]!") + var/obj/item/weapon/grab/G = W + var/mob/living/affecting = G.affecting + user.visible_message("[user] attempts to buckle [affecting] into \the [src]!") if(do_after(user, 20)) - W:affecting.loc = loc - if(buckle_mob(W:affecting)) - W:affecting.visible_message(\ - "[W:affecting.name] is buckled to [src] by [user.name]!",\ - "You are buckled to [src] by [user.name]!",\ - "You hear metal clanking.") + affecting.loc = loc + spawn(0) + if(buckle_mob(affecting)) + affecting.visible_message(\ + "[affecting.name] is buckled to [src] by [user.name]!",\ + "You are buckled to [src] by [user.name]!",\ + "You hear metal clanking.") + qdel(W) else ..() From 592c824837fd6a5be89f21260dbc6bf55056c922 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sat, 26 Sep 2015 20:26:37 -0500 Subject: [PATCH 017/207] Changes paper and paper bundle gender, plus rename --- code/modules/paperwork/paper.dm | 6 +++--- code/modules/paperwork/paper_bundle.dm | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 3485e4ed1e8..14079c8a7d2 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -4,13 +4,13 @@ */ /obj/item/weapon/paper - name = "paper" - gender = PLURAL + name = "sheet of paper" + gender = NEUTER icon = 'icons/obj/bureaucracy.dmi' icon_state = "paper" item_state = "paper" throwforce = 0 - w_class = 1.0 + w_class = 1 throw_range = 1 throw_speed = 1 layer = 4 diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index c99edc57b9d..7da55f1f056 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -1,6 +1,6 @@ /obj/item/weapon/paper_bundle name = "paper bundle" - gender = PLURAL + gender = NEUTER icon = 'icons/obj/bureaucracy.dmi' icon_state = "paper" item_state = "paper" From 380b89fcc034ca844fb3aed5f840d866a9b35b9e Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sat, 26 Sep 2015 20:48:13 -0500 Subject: [PATCH 018/207] Fixes #11130, renames aghosted var because it is no longer used solely for aghosting. --- code/modules/admin/admin_verbs.dm | 2 +- code/modules/mob/dead/observer/observer.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 2 +- code/modules/mob/living/carbon/human/life.dm | 2 +- code/modules/mob/mob_defines.dm | 5 +++-- code/modules/spells/artifacts.dm | 6 ++++-- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d628a7bef36..2c58b2dc828 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -401,7 +401,7 @@ var/list/admin_verbs_mentor = list( var/mob/dead/observer/ghost = body.ghostize(1) ghost.admin_ghosted = 1 if(body) - body.aghosted = ghost + body.teleop = ghost if(!body.key) body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus feedback_add_details("admin_verb","O") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index e58df4f1f93..80a5bdd5572 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -217,7 +217,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return mind.current.ajourn=0 mind.current.key = key - mind.current.aghosted = null + mind.current.teleop = null if(!admin_ghosted) announce_ghost_joinleave(mind, 0, "They now occupy their body again.") return 1 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 1a7085d61a5..0ab0b872d97 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -260,7 +260,7 @@ var/show_ssd var/mob/living/carbon/human/H = src if(istype(H)) show_ssd = H.species.show_ssd - if(show_ssd && !client && !aghosted) + if(show_ssd && !client && !teleop) M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ "You shake [src], but they do not respond... Maybe they have S.S.D?") else if(lying || src.sleeping) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b9f5b513e81..efb450db44e 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -941,7 +941,7 @@ if(status_flags & GODMODE) return 0 //SSD check, if a logged player is awake put them back to sleep! - if(species.show_ssd && !client && !aghosted) + if(species.show_ssd && !client && !teleop) Sleeping(2) if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 89a4957e3fb..85d8c78464b 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -214,8 +214,9 @@ var/stance_damage = 0 //Whether this mob's ability to stand has been affected - //Indicates if a clientless mob is actually an admin aghosting - var/mob/dead/observer/aghosted = null + //If set, indicates that the client "belonging" to this (clientless) mob is currently controlling some other mob + //so don't treat them as being SSD even though their client var is null. + var/mob/teleop = null var/turf/listed_turf = null //the current turf being examined in the stat panel var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes diff --git a/code/modules/spells/artifacts.dm b/code/modules/spells/artifacts.dm index 0a96b6aa2ea..02508d536d5 100644 --- a/code/modules/spells/artifacts.dm +++ b/code/modules/spells/artifacts.dm @@ -14,6 +14,8 @@ /obj/item/weapon/scrying/attack_self(mob/user as mob) user << "You can see... everything!" - visible_message("[usr] stares into [src], their eyes glazing over.") - announce_ghost_joinleave(user.ghostize(1), 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.") + visible_message("[user] stares into [src], their eyes glazing over.") + + user.teleop = user.ghostize(1) + announce_ghost_joinleave(user.teleop, 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.") return From eb28b1f3044ed1e5b7c92728c4b93b081a7584b5 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 28 Sep 2015 12:01:25 +0200 Subject: [PATCH 019/207] Removes double-layered Chemistry windoor. Seems a bit excessive to have two windoors on the same location. --- maps/exodus-1.dmm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index c755ae460ff..b512e9296fa 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -3519,7 +3519,7 @@ "bpI" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "bpJ" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "bpK" = (/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor,/area/hallway/secondary/entry/aft) -"bpL" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/blast/shutters{density = 0; dir = 4; icon_state = "shutter0"; id = "chemcounter"; name = "Pharmacy Counter Shutters"; opacity = 0},/obj/structure/table/reinforced,/obj/machinery/door/window/westright{name = "Chemistry Desk"; req_access = list(33)},/obj/machinery/door/window/westright{name = "Chemistry Desk"; req_access = list(33)},/turf/simulated/floor{icon_state = "yellowfull"; dir = 8},/area/medical/chemistry) +"bpL" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/door/blast/shutters{density = 0; dir = 4; icon_state = "shutter0"; id = "chemcounter"; name = "Pharmacy Counter Shutters"; opacity = 0},/obj/structure/table/reinforced,/obj/machinery/door/window/westright{name = "Chemistry Desk"; req_access = list(33)},/turf/simulated/floor{icon_state = "yellowfull"; dir = 8},/area/medical/chemistry) "bpM" = (/obj/item/weapon/stool/padded,/turf/simulated/floor{tag = "icon-whiteblue (EAST)"; icon_state = "whiteblue"; dir = 4},/area/medical/reception) "bpN" = (/obj/structure/table/standard,/obj/item/weapon/autopsy_scanner,/obj/item/weapon/scalpel,/turf/simulated/floor{icon_state = "blue"; dir = 8},/area/medical/morgue) "bpO" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/cable/cyan,/turf/simulated/floor/plating,/area/turret_protected/ai_upload) From a65daf42fb5293fd5cd6698e92757e0347364291 Mon Sep 17 00:00:00 2001 From: Dibasic Date: Mon, 28 Sep 2015 10:47:00 -0500 Subject: [PATCH 020/207] changelog.css readability and redundancy Removed redundant CSS lines, fixed "Baystation 12 Credit List" font, and added line breaks and indentation to blocks with more than one line. --- html/changelog.css | 65 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/html/changelog.css b/html/changelog.css index 9d43ecc076c..d5155db7261 100644 --- a/html/changelog.css +++ b/html/changelog.css @@ -1,5 +1,5 @@ -.top{font-family:Tahoma,sans-serif;font-size:12px;} -h2{font-family:Tahoma,sans-serif;} +body{font-family:Tahoma,sans-serif;} +.top{font-size:12px;} a img {border:none;} .bgimages16 li { padding:2px 10px 2px 30px; @@ -21,16 +21,57 @@ a img {border:none;} .spellcheck {background-image:url(spell-check.png)} .experiment {background-image:url(burn-exclamation.png)} .maptweak {background-image:url(map-pencil.png)} -.sansserif {font-family:Tahoma,sans-serif;font-size:12px;} -.commit {margin-bottom:20px;font-size:100%;font-weight:normal;} -.changes {list-style:none;margin:5px 0;padding:0 0 0 25px;font-size:0.8em;} -.date {margin:10px 0;color:blue;border-bottom:2px solid #00f;width:60%;padding:2px 0;font-size:1em;font-weight:bold;} -.author {padding-left:10px;margin:0;font-weight:bold;font-size:0.9em;} -.drop {cursor:pointer;border:1px solid #999;display:inline;font-size:0.9em;padding:1px 20px 1px 5px;line-height:16px;} +.sansserif {font-size:12px;} +.commit { + margin-bottom:20px; + font-size:100%;font-weight:normal; +} +.changes { + list-style:none; + margin:5px 0; + padding:0 0 0 25px; + font-size:0.8em; +} +.date { + margin:10px 0; + color:blue; + border-bottom:2px solid #00f; + width:60%; + padding:2px 0; + font-size:1em; + font-weight:bold; +} +.author { + padding-left:10px; + margin:0; + font-weight:bold; + font-size:0.9em; + } +.drop { + cursor:pointer; + border:1px solid #999; + display:inline; + font-size:0.9em; + padding:1px 20px 1px 5px; + line-height:16px; +} .hidden {display:none;} -.indrop {margin:2px 0 0 0;clear:both;background:#fff;border:1px solid #ddd;padding:5px 10px;} -.indrop p {margin:0;font-size:0.8em;line-height:16px;margin:1px 0;} -.indrop img {margin-right:5px;vertical-align:middle;} +.indrop { + margin:2px 0 0 0; + clear:both; + background:#fff; + border:1px solid #ddd; + padding:5px 10px; + } +.indrop p { + margin:0; + font-size:0.8em; + line-height:16px; + margin:1px 0; +} +.indrop img { + margin-right:5px; + vertical-align:middle;} .closed {background:url(chevron-expand.png) right center no-repeat;} .open {background:url(chevron.png) right center no-repeat;} -.lic {font-size:9px;} \ No newline at end of file +.lic {font-size:9px;} From d77bcd79379e40f5d9f6d065a0fecdede38bc0a5 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 28 Sep 2015 12:15:16 +0200 Subject: [PATCH 021/207] The silicon law manager now only requires the host to be conscious. This should mean that the law manager is available even for carded AIs, even with the wireless interface disabled. Fixes #11139. --- baystation12.dme | 1 + code/modules/mob/living/silicon/subystems.dm | 2 +- code/modules/nano/interaction/base.dm | 2 +- code/modules/nano/interaction/conscious.dm | 7 +++++++ 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 code/modules/nano/interaction/conscious.dm diff --git a/baystation12.dme b/baystation12.dme index 38b9f77d966..2566203ca05 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1338,6 +1338,7 @@ #include "code\modules\nano\nanoui.dm" #include "code\modules\nano\interaction\admin.dm" #include "code\modules\nano\interaction\base.dm" +#include "code\modules\nano\interaction\conscious.dm" #include "code\modules\nano\interaction\contained.dm" #include "code\modules\nano\interaction\default.dm" #include "code\modules\nano\interaction\inventory.dm" diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm index e8909b0b509..21ce3dd31f8 100644 --- a/code/modules/mob/living/silicon/subystems.dm +++ b/code/modules/mob/living/silicon/subystems.dm @@ -76,7 +76,7 @@ set name = "Law Manager" set category = "Subystems" - law_manager.ui_interact(usr, state = self_state) + law_manager.ui_interact(usr, state = conscious_state) /******************** * Power Monitor * diff --git a/code/modules/nano/interaction/base.dm b/code/modules/nano/interaction/base.dm index 602185bb8ab..99f9e490bef 100644 --- a/code/modules/nano/interaction/base.dm +++ b/code/modules/nano/interaction/base.dm @@ -14,7 +14,7 @@ /mob/proc/shared_nano_interaction() if (src.stat || !client) return STATUS_CLOSE // no updates, close the interface - else if (restrained() || lying || stat || stunned || weakened) + else if (restrained() || lying || stat || stunned || weakened) // TODO: Change to incapaciated() on merge return STATUS_UPDATE // update only (orange visibility) return STATUS_INTERACTIVE diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm new file mode 100644 index 00000000000..143bc24956f --- /dev/null +++ b/code/modules/nano/interaction/conscious.dm @@ -0,0 +1,7 @@ +/* + This state only checks if user is conscious. +*/ +/var/global/datum/topic_state/conscious_state/conscious_state = new() + +/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user) + return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE From 11141462a056ab9999bc1fe0fabf3be2ba2f18d7 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 30 Sep 2015 00:00:36 +0100 Subject: [PATCH 022/207] fix #11222 also fixes the name and adds feedback to adding items --- .../research/xenoarchaeology/machinery/geosample_scanner.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm b/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm index 378848e26ea..ed23b965dfe 100644 --- a/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm +++ b/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm @@ -1,6 +1,6 @@ /obj/machinery/radiocarbon_spectrometer - name = "Radiocarbon spectrometer" + name = "radiocarbon spectrometer" desc = "A specialised, complex scanner for gleaning information on all manner of small things." anchored = 1 density = 1 @@ -91,9 +91,13 @@ user << "You remove [amount_transferred]u of coolant from [src]." update_coolant() return + if(scanned_item) + user << "\The [src] already has \a [scanned_item] inside!" + return user.drop_item() I.loc = src scanned_item = I + user << "You put \the [I] into \the [src]." /obj/machinery/radiocarbon_spectrometer/proc/update_coolant() var/total_purity = 0 From 4fdf4afa08c719cbfd2e7b54cf1d7e3f4d289057 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Fri, 2 Oct 2015 08:56:34 +0200 Subject: [PATCH 023/207] Adds on-mob NVG sprites. Fixes #10965. --- icons/mob/eyes.dmi | Bin 6804 -> 7356 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 486e578cb6dac728cae0c1781a3e888319736838..b68ccd373c51314ec6920588282b4535c70cf643 100644 GIT binary patch literal 7356 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 Jzi#vJzW|c3_JaTb literal 6804 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 UncLtBiXs4FXlhV;**W6B06KCs>i_@% From 5ef5f40cbe2d5e086a8357792aff91457062459f Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Fri, 2 Oct 2015 12:45:19 +0100 Subject: [PATCH 024/207] add 'info' topic command to get information on a character --- code/world.dm | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/code/world.dm b/code/world.dm index ac17aa21c07..3a5f0a5f83b 100644 --- a/code/world.dm +++ b/code/world.dm @@ -184,6 +184,69 @@ var/world_topic_spam_protect_time = world.timeofday return list2params(positions) + else if(copytext(T,1,5) == "info") + var/input[] = params2list(T) + if(input["key"] != config.comms_password) + if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50) + + spawn(50) + world_topic_spam_protect_time = world.time + return "Bad Key (Throttled)" + + world_topic_spam_protect_time = world.time + world_topic_spam_protect_ip = addr + + return "Bad Key" + + var/search = input["info"] + var/ckey = ckey(search) + + var/list/match = list() + + for(var/mob/M in mob_list) + if(findtext(M.name, search)) + match += M + else if(M.ckey == ckey) + match += M + else if(M.mind && findtext(M.mind.assigned_role, search)) + match += M + + if(!match.len) + return "No matches" + else if(match.len == 1) + var/mob/M = match[1] + var/info = list() + info["key"] = M.key + info["name"] = M.name == M.real_name ? M.name : "[M.name] ([M.real_name])" + info["role"] = M.mind ? (M.mind.assigned_role ? M.mind.assigned_role : "No role") : "No mind" + var/turf/MT = get_turf(M) + info["loc"] = M.loc ? "[M.loc]" : "null" + info["turf"] = MT ? "[MT] @ [MT.x], [MT.y], [MT.z]" : "null" + info["area"] = MT ? "[MT.loc]" : "null" + info["antag"] = M.mind ? (M.mind.special_role ? M.mind.special_role : "Not antag") : "No mind" + info["hasbeenrev"] = M.mind ? M.mind.has_been_rev : "No mind" + info["stat"] = M.stat + info["type"] = M.type + if(isliving(M)) + var/mob/living/L = M + info["damage"] = list2params(list( + oxy = L.getOxyLoss(), + tox = L.getToxLoss(), + fire = L.getFireLoss(), + brute = L.getBruteLoss(), + clone = L.getCloneLoss(), + brain = L.getBrainLoss() + )) + else + info["damage"] = "non-living" + info["gender"] = M.gender + return list2params(info) + else + var/list/ret = list() + for(var/mob/M in match) + ret[M.key] = M.name + return list2params(ret) + else if(copytext(T,1,9) == "adminmsg") /* We got an adminmsg from IRC bot lets split the input then validate the input. From 485541820d351c4cd1d4fcea18f61a91b75a10d9 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 5 Oct 2015 09:44:05 +0200 Subject: [PATCH 025/207] Updates intent macros. Fixes #11234. --- interface/skin.dmf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/skin.dmf b/interface/skin.dmf index c0db1c1b6e3..d9f0f48c0ff 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -71,6 +71,14 @@ macro "borghotkeymode" name = "SOUTH+REP" command = ".south" is-disabled = false + elem + name = "INSERT" + command = "a-intent right" + is-disabled = false + elem + name = "DELETE" + command = "delete-key-pressed" + is-disabled = false elem name = "1" command = "toggle-module 1" @@ -103,14 +111,6 @@ macro "borghotkeymode" name = "CTRL+4" command = "a-intent left" is-disabled = false - elem - name = "INSERT" - command = "a-intent right" - is-disabled = false - elem - name = "DELETE" - command = "delete-key-pressed" - is-disabled = false elem name = "5" command = ".me" @@ -359,7 +359,7 @@ macro "macro" is-disabled = false elem name = "CTRL+4" - command = "a-intent hurt" + command = "a-intent harm" is-disabled = false elem name = "CTRL+A+REP" From 91faf8555f7a752977616157ce64d361cc590a35 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 5 Oct 2015 10:13:05 +0200 Subject: [PATCH 026/207] Antag placement now favors mobless turfs. If one such turf is available, otherwise picks a random populated turf. Fixes #11237. --- code/__HELPERS/turfs.dm | 15 +++++++++++++++ code/game/antagonist/alien/borer.dm | 4 ++-- code/game/antagonist/alien/xenomorph.dm | 2 +- code/game/antagonist/antagonist_place.dm | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm index 3ee4e26a7a8..85836281143 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/__HELPERS/turfs.dm @@ -17,3 +17,18 @@ if(A.simulated) return 0 return 1 + +// Picks a turf without a mob from the given list of turfs, if one exists. +// If no such turf exists, picks any random turf from the given list of turfs. +/proc/pick_mobless_turf_if_exists(var/list/start_turfs) + if(!start_turfs.len) + return null + + var/list/available_turfs = list() + for(var/start_turf in start_turfs) + var/mob/M = locate() in start_turf + if(!M) + available_turfs += start_turf + if(!available_turfs.len) + available_turfs = start_turfs + return pick(available_turfs) diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm index f43550dc6ad..8fa028453f2 100644 --- a/code/game/antagonist/alien/borer.dm +++ b/code/game/antagonist/alien/borer.dm @@ -36,7 +36,7 @@ var/datum/antagonist/xenos/borer/borers if(istype(borer)) var/mob/living/carbon/human/host for(var/mob/living/carbon/human/H in mob_list) - if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms()) + if(H.stat != DEAD && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms()) host = H break if(istype(host)) @@ -44,7 +44,7 @@ var/datum/antagonist/xenos/borer/borers if(head) borer.host = host head.implants += borer - borer.loc = head + borer.forceMove(head) if(!borer.host_brain) borer.host_brain = new(borer) borer.host_brain.name = host.name diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm index 4603fc5d1c0..08cbeebca9e 100644 --- a/code/game/antagonist/alien/xenomorph.dm +++ b/code/game/antagonist/alien/xenomorph.dm @@ -44,4 +44,4 @@ var/datum/antagonist/xenos/xenomorphs player.objectives += new /datum/objective/escape() /datum/antagonist/xenos/place_mob(var/mob/living/player) - player.loc = get_turf(pick(get_vents())) + player.forceMove(get_turf(pick(get_vents()))) diff --git a/code/game/antagonist/antagonist_place.dm b/code/game/antagonist/antagonist_place.dm index db8c74a14f6..b5f62868dc5 100644 --- a/code/game/antagonist/antagonist_place.dm +++ b/code/game/antagonist/antagonist_place.dm @@ -23,4 +23,5 @@ /datum/antagonist/proc/place_mob(var/mob/living/mob) if(!starting_locations || !starting_locations.len) return - mob.loc = pick(starting_locations) \ No newline at end of file + var/turf/T = pick_mobless_turf_if_exists(mob) + mob.forceMove(T) From f3effa8df79d8e9fda9fa93f2257e6ff1a53b1b6 Mon Sep 17 00:00:00 2001 From: Kelenius Date: Mon, 5 Oct 2015 11:40:19 +0300 Subject: [PATCH 027/207] Basic encryption hack popup only shows suitable APCs --- .../malfunction/newmalf_ability_trees/HELPERS.dm | 8 +++++--- .../malfunction/newmalf_ability_trees/tree_networking.dm | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm index 69794c9af33..0d9519504f1 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm @@ -163,12 +163,14 @@ command_announcement.Announce(fulltext) -// Proc: get_all_apcs() +// Proc: get_unhacked_apcs() // Parameters: None -// Description: Returns a list of all APCs -/proc/get_all_apcs() +// Description: Returns a list of all unhacked APCs +/proc/get_unhacked_apcs(var/mob/living/silicon/ai/user) var/list/H = list() for(var/obj/machinery/power/apc/A in machines) + if(A.hacker && A.hacker == user) + continue H.Add(A) return H diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm index f1bad288ad0..4a163884c48 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm @@ -38,7 +38,7 @@ // END RESEARCH DATUMS // BEGIN ABILITY VERBS -/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_all_apcs()) +/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs(src)) set category = "Software" set name = "Basic Encryption Hack" set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station." From bbcadcc08071d1eb2e567e0e0d8c66823170db06 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 5 Oct 2015 11:12:26 +0200 Subject: [PATCH 028/207] Makes silicon language handling more robust. Also fixes an issue with lists being targets for qdel(). Fixes #11221. --- code/modules/mob/language/language.dm | 2 +- .../mob/living/silicon/robot/robot_modules.dm | 28 +++++++++++++------ code/modules/mob/living/silicon/silicon.dm | 18 ++++++++---- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 03ab8ea2970..8c6b92c5557 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -123,7 +123,7 @@ var/datum/language/new_language = all_languages[language] - if(!istype(new_language) || new_language in languages) + if(!istype(new_language) || (new_language in languages)) return 0 languages.Add(new_language) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 819fbf4561e..d5a2edf3e13 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -34,7 +34,7 @@ var/global/list/robot_modules = list( var/list/obj/item/borg/upgrade/supported_upgrades = list() // Bookkeeping - var/list/added_languages = list() + var/list/original_languages = list() var/list/added_networks = list() /obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R) @@ -63,12 +63,14 @@ var/global/list/robot_modules = list( qdel(src) /obj/item/weapon/robot_module/Destroy() - qdel(modules) - qdel(synths) + for(var/obj/O in modules) + qdel(O) + modules.Cut() + for(var/datum/matter_synth/S in synths) + qdel(S) + synths.Cut() qdel(emag) qdel(jetpack) - modules = null - synths = null emag = null jetpack = null return ..() @@ -100,14 +102,22 @@ var/global/list/robot_modules = list( modules += O /obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R) + // Stores the languages as they were before receiving the module, and whether they could be synthezized. + for(var/datum/language/language_datum in R.languages) + original_languages[language_datum] = (language_datum in R.speech_synthesizer_langs) + for(var/language in languages) - if(R.add_language(language, languages[language])) - added_languages |= language + R.add_language(language, languages[language]) /obj/item/weapon/robot_module/proc/remove_languages(var/mob/living/silicon/robot/R) - for(var/language in added_languages) + // Clear all added languages, whether or not we originally had them. + for(var/language in languages) R.remove_language(language) - added_languages.Cut() + + // Then add back all the original languages, and the relevant synthezising ability + for(var/original_language in original_languages) + R.add_language(original_language, original_languages[original_language]) + original_languages.Cut() /obj/item/weapon/robot_module/proc/add_camera_networks(var/mob/living/silicon/robot/R) if(R.camera && (NETWORK_ROBOTS in R.camera.network)) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index d6fc2e4aa92..5186a7f6b85 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -188,16 +188,22 @@ return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language /mob/living/silicon/add_language(var/language, var/can_speak=1) - if (..(language) && can_speak) - speech_synthesizer_langs.Add(all_languages[language]) + var/var/datum/language/added_language = all_languages[language] + if(!added_language) + return + + . = ..(language) + if (can_speak && (added_language in languages) && !(added_language in speech_synthesizer_langs)) + speech_synthesizer_langs += added_language return 1 /mob/living/silicon/remove_language(var/rem_language) - ..(rem_language) + var/var/datum/language/removed_language = all_languages[rem_language] + if(!removed_language) + return - for (var/datum/language/L in speech_synthesizer_langs) - if (L.name == rem_language) - speech_synthesizer_langs -= L + ..(rem_language) + speech_synthesizer_langs -= removed_language /mob/living/silicon/check_languages() set name = "Check Known Languages" From 74950268d752254a048d95664cfd64abcba4e9b1 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Mon, 5 Oct 2015 19:23:51 -0400 Subject: [PATCH 029/207] Fixes fire_stacks update logic --- code/modules/mob/living/living_defense.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index c1295cc3626..93faa0e8b02 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -219,7 +219,7 @@ /mob/living/proc/handle_fire() if(fire_stacks < 0) - fire_stacks = max(0, fire_stacks++) //If we've doused ourselves in water to avoid fire, dry off slowly + fire_stacks = min(0, ++fire_stacks) //If we've doused ourselves in water to avoid fire, dry off slowly if(!on_fire) return 1 From ec097d928ae18a5b25c4aef94b6e64aa562d4bee Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 6 Oct 2015 09:19:40 +0200 Subject: [PATCH 030/207] Antagonist summary printout now prefers assignment over special role. As antags are listed under relevant headings, i.e. "The traitors were", this seems more reasonable. Fixes #10817. --- code/game/antagonist/antagonist_print.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm index 0ca4015200b..31a5b96b2ce 100644 --- a/code/game/antagonist/antagonist_print.dm +++ b/code/game/antagonist/antagonist_print.dm @@ -45,7 +45,7 @@ return text /datum/antagonist/proc/print_player_lite(var/datum/mind/ply) - var/role = ply.special_role ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]" + var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]" var/text = "
[ply.name] ([ply.key]) as \a [role] (" if(ply.current) if(ply.current.stat == DEAD) From bd7c475fccb014e5747507a81b7b3c1c31e71425 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 8 Oct 2015 20:29:39 +0200 Subject: [PATCH 031/207] Stack material use now depends on charge costs. This ensures one does not have to remember to set uses_charge equal to the length of the charge_cost list. Fixes #10943. --- code/game/objects/items/stacks/stack.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 94b6db4f958..8c5ac01c7a5 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -191,7 +191,7 @@ else if(get_amount() < used) return 0 - for(var/i = 1 to uses_charge) + for(var/i = 1 to charge_costs.len) var/datum/matter_synth/S = synths[i] S.use_charge(charge_costs[i] * used) // Doesn't need to be deleted return 1 @@ -264,8 +264,8 @@ return 0 var/datum/matter_synth/S = synths[1] . = round(S.get_charge() / charge_costs[1]) - if(uses_charge > 1) - for(var/i = 2 to uses_charge) + if(charge_costs.len > 1) + for(var/i = 2 to charge_costs.len) S = synths[i] . = min(., round(S.get_charge() / charge_costs[i])) return From 40ab99b354b412092ff9b1b9191d0a9aec6eeea1 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Thu, 8 Oct 2015 16:36:51 -0400 Subject: [PATCH 032/207] Rubber bullets and beanbags now check melee armour instead of bullet armour --- .../modules/projectiles/projectile/bullets.dm | 4 +++- html/changelogs/HarpyEagle-rubberbullets.yml | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 html/changelogs/HarpyEagle-rubberbullets.yml diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index f2c10fd8a90..12fae31e4ee 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -110,6 +110,7 @@ /obj/item/projectile/bullet/pistol/rubber //"rubber" bullets name = "rubber bullet" + check_armour = "melee" damage = 10 agony = 40 embed = 0 @@ -123,6 +124,7 @@ /obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets name = "beanbag" + check_armour = "melee" damage = 20 agony = 60 embed = 0 @@ -196,4 +198,4 @@ /obj/item/projectile/bullet/shotgun/practice name = "practice" - damage = 5 + damage = 5 diff --git a/html/changelogs/HarpyEagle-rubberbullets.yml b/html/changelogs/HarpyEagle-rubberbullets.yml new file mode 100644 index 00000000000..841373a9f9a --- /dev/null +++ b/html/changelogs/HarpyEagle-rubberbullets.yml @@ -0,0 +1,20 @@ +################################ +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +author: HarpyEagle +delete-after: True +changes: + - tweak: "Rubber bullets and beanbags now are now resisted by melee armour." From fa661f998f8307a40ab8084e601efae3345a5300 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Thu, 8 Oct 2015 23:26:05 -0400 Subject: [PATCH 033/207] TTV Refactor Ensures TTV icon update occurs properly and removes the need for sleep() by updating tank Destroy() to account for TTVs. Collects duplicated code into a transfer_valve/remove_tank() proc. --- .../objects/items/devices/transfer_valve.dm | 49 +++++++++++-------- .../game/objects/items/weapons/tanks/tanks.dm | 14 +++++- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 36c3b3d11f2..e44f7595470 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -99,17 +99,9 @@ if (src.loc != usr) return 0 if(tank_one && href_list["tankone"]) - split_gases() - valve_open = 0 - tank_one.loc = get_turf(src) - tank_one = null - update_icon() + remove_tank(tank_one) else if(tank_two && href_list["tanktwo"]) - split_gases() - valve_open = 0 - tank_two.loc = get_turf(src) - tank_two = null - update_icon() + remove_tank(tank_two) else if(href_list["open"]) toggle_valve() else if(attached_device) @@ -148,20 +140,43 @@ if(attached_device) overlays += "device" +/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T) + if(tank_one == T) + split_gases() + tank_one = null + else if(tank_two == T) + split_gases() + tank_two = null + else + return + + T.loc = get_turf(src) + update_icon() + /obj/item/device/transfer_valve/proc/merge_gases() + if(valve_open) + return tank_two.air_contents.volume += tank_one.air_contents.volume var/datum/gas_mixture/temp temp = tank_one.air_contents.remove_ratio(1) tank_two.air_contents.merge(temp) + valve_open = 1 /obj/item/device/transfer_valve/proc/split_gases() - if (!valve_open || !tank_one || !tank_two) + if(!valve_open) return + + valve_open = 0 + + if(deleted(tank_one) || deleted(tank_two)) + return + var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume var/datum/gas_mixture/temp temp = tank_two.air_contents.remove_ratio(ratio1) tank_one.air_contents.merge(temp) tank_two.air_contents.volume -= tank_one.air_contents.volume + /* Exadv1: I know this isn't how it's going to work, but this was just to check @@ -169,8 +184,7 @@ */ /obj/item/device/transfer_valve/proc/toggle_valve() - if(valve_open==0 && (tank_one && tank_two)) - valve_open = 1 + if(!valve_open && (tank_one && tank_two)) var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) @@ -196,16 +210,11 @@ message_admins(log_str, 0, 1) log_game(log_str) merge_gases() - spawn(20) // In case one tank bursts - for (var/i=0,i<5,i++) - src.update_icon() - sleep(10) - src.update_icon() else if(valve_open==1 && (tank_one && tank_two)) split_gases() - valve_open = 0 - src.update_icon() + + src.update_icon() // this doesn't do anything but the timer etc. expects it to be here // eventually maybe have it update icon to show state (timer, prox etc.) like old bombs diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 59627bad116..1d1b2ea1038 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -36,6 +36,10 @@ qdel(air_contents) processing_objects.Remove(src) + + if(istype(loc, /obj/item/device/transfer_valve)) + var/obj/item/device/transfer_valve/TTV = loc + TTV.remove_tank(src) ..() @@ -280,7 +284,10 @@ qdel(src) else if(pressure > TANK_RUPTURE_PRESSURE) - //world << "\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]" + #ifdef FIREDBG + log_debug("\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]") + #endif + if(integrity <= 0) var/turf/simulated/T = get_turf(src) if(!T) @@ -292,7 +299,10 @@ integrity-- else if(pressure > TANK_LEAK_PRESSURE) - //world << "\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]" + #ifdef FIREDBG + log_debug("\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]") + #endif + if(integrity <= 0) var/turf/simulated/T = get_turf(src) if(!T) From 9639d608a6875b7f82ad2e109328cd63c3da69f7 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Thu, 8 Oct 2015 23:29:37 -0400 Subject: [PATCH 034/207] Fixes calculate_firelevel() not counting oxidizer Fixes calculate_firelevel() not counting oxidizer when determining the ratio of reactants to other gases. As well firelevel calculation is now done separately for burning gas and burning liquid. Adjusted FIRE_LIQUID_BURNRATE_MULT so that liquid burn rate is unaffected by this fix, which will result in generally higher firelevels and thus faster burn rates. --- code/ZAS/Fire.dm | 44 ++++++++++++++++++++++---------------------- code/setup.dm | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 501c49ae556..dba966e9fb9 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -1,13 +1,9 @@ /* Making Bombs with ZAS: -Make burny fire with lots of burning -Draw off 5000K gas from burny fire -Separate gas into oxygen and phoron components -Obtain phoron and oxygen tanks filled up about 50-75% with normal-temp gas -Fill rest with super hot gas from separated canisters, they should be about 125C now. -Attach to transfer valve and open. BOOM. - +Get gas to react in an air tank so that it gains pressure. If it gains enough pressure, it goes boom. +The more pressure, the more boom. +If it gains pressure too slowly, it may leak or just rupture instead of exploding. */ //#define FIREDBG @@ -268,16 +264,16 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) //determine how far the reaction can progress var/reaction_limit = min(total_oxidizers*(FIRE_REACTION_FUEL_AMOUNT/FIRE_REACTION_OXIDIZER_AMOUNT), total_fuel) //stoichiometric limit - //calculate the firelevel. - var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit) - var/firelevel_ratio = firelevel / vsc.fire_firelevel_multiplier - //vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).) + var/gas_firelevel = calculate_firelevel(gas_fuel, total_oxidizers, reaction_limit, volume*group_multiplier) / vsc.fire_firelevel_multiplier var/min_burn = 0.30*volume*group_multiplier/CELL_VOLUME //in moles - so that fires with very small gas concentrations burn out fast - var/gas_reaction_progress = min(max(min_burn, firelevel_ratio*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel) + var/gas_reaction_progress = min(max(min_burn, gas_firelevel*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel) //liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning. Limit the burn rate to a certain amount per area. - var/liquid_reaction_progress = min((firelevel_ratio*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel) + var/liquid_firelevel = calculate_firelevel(liquid_fuel, total_oxidizers, reaction_limit, 0) / vsc.fire_firelevel_multiplier + var/liquid_reaction_progress = min((liquid_firelevel*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel) + + var/firelevel = (gas_fuel*gas_firelevel + liquid_fuel*liquid_firelevel)/total_fuel var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress var/used_fuel = min(total_reaction_progress, reaction_limit) @@ -286,7 +282,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) #ifdef FIREDBG log_debug("gas_fuel = [gas_fuel], liquid_fuel = [liquid_fuel], total_oxidizers = [total_oxidizers]") log_debug("fuel_area = [fuel_area], total_fuel = [total_fuel], reaction_limit = [reaction_limit]") - log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]") + log_debug("firelevel -> [firelevel] (gas: [gas_firelevel], liquid: [liquid_firelevel])") log_debug("liquid_reaction_progress = [liquid_reaction_progress]") log_debug("gas_reaction_progress = [gas_reaction_progress]") log_debug("total_reaction_progress = [total_reaction_progress]") @@ -315,13 +311,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) //calculate the energy produced by the reaction and then set the new temperature of the mix temperature = (starting_energy + vsc.fire_fuel_energy_release * (used_gas_fuel + used_liquid_fuel)) / heat_capacity() + update_values() #ifdef FIREDBG log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_fuel]") - log_debug("new temperature = [temperature]") + log_debug("new temperature = [temperature]; new pressure = [return_pressure()]") #endif - - update_values() + return firelevel datum/gas_mixture/proc/check_recombustability(list/fuel_objs) @@ -363,27 +359,31 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs) break //returns a value between 0 and vsc.fire_firelevel_multiplier -/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit) +/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume) //Calculates the firelevel based on one equation instead of having to do this multiple times in different areas. var/firelevel = 0 var/total_combustables = (total_fuel + total_oxidizers) + var/active_combustables = (FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT + 1)*reaction_limit if(total_combustables > 0) //slows down the burning when the concentration of the reactants is low - var/dampening_multiplier = min(1, reaction_limit / (total_moles/group_multiplier)) + var/damping_multiplier = min(1, active_combustables / (total_moles/group_multiplier)) + + //weight the damping mult so that it only really brings down the firelevel when the ratio is closer to 0 + damping_multiplier = 2*damping_multiplier - (damping_multiplier*damping_multiplier) //calculates how close the mixture of the reactants is to the optimum - //fires burn better when there is more oxidizer -- too much fuel will choke them out a bit, reducing firelevel. + //fires burn better when there is more oxidizer -- too much fuel will choke the fire out a bit, reducing firelevel. var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2))) #ifdef FIREDBG - ASSERT(dampening_multiplier <= 1) + ASSERT(damping_multiplier <= 1) ASSERT(mix_multiplier <= 1) #endif //toss everything together -- should produce a value between 0 and fire_firelevel_multiplier - firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier + firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * damping_multiplier return max( 0, firelevel) diff --git a/code/setup.dm b/code/setup.dm index be0989b1910..7473822cc68 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -142,7 +142,7 @@ //These control the speed at which fire burns #define FIRE_GAS_BURNRATE_MULT 1 -#define FIRE_LIQUID_BURNRATE_MULT 1 +#define FIRE_LIQUID_BURNRATE_MULT 0.4 //If the fire is burning slower than this rate then the reaction is going too slow to be self sustaining and the fire burns itself out. //This ensures that fires don't grind to a near-halt while still remaining active forever. From 1cf6ace74e55e3b05bf9893cc3d2e057cf2aec1f Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Fri, 9 Oct 2015 01:04:57 -0400 Subject: [PATCH 035/207] Fixes #11071, #10936 Adjusts fire_fuel_energy_release to compensate for fixed fire heat release. Adjusts liquid fire burn parameters so that liquid fuel fire heat release and burn duration is unaffected. --- code/ZAS/Gas.dm | 3 +++ code/ZAS/Variable Settings.dm | 3 ++- code/setup.dm | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/code/ZAS/Gas.dm b/code/ZAS/Gas.dm index 0f3faa09b49..20dd67bf342 100644 --- a/code/ZAS/Gas.dm +++ b/code/ZAS/Gas.dm @@ -21,6 +21,9 @@ /xgm_gas/phoron id = "phoron" name = "Phoron" + + //Note that this has a significant impact on TTV yield. + //Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure. specific_heat = 200 // J/(mol*K) //Hypothetical group 14 (same as carbon), period 8 element. diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm index c152159b7ac..7700fee2bb2 100644 --- a/code/ZAS/Variable Settings.dm +++ b/code/ZAS/Variable Settings.dm @@ -9,7 +9,8 @@ var/global/vs_control/vsc = new var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant" var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires." - var/fire_fuel_energy_release = 397000 + //Note that this parameter and the phoron heat capacity have a significant impact on TTV yield. + var/fire_fuel_energy_release = 866000 //J/mol. Adjusted to compensate for fire energy release being fixed, was 397000 var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release" var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance" diff --git a/code/setup.dm b/code/setup.dm index 7473822cc68..8371ca3cdd3 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -142,15 +142,15 @@ //These control the speed at which fire burns #define FIRE_GAS_BURNRATE_MULT 1 -#define FIRE_LIQUID_BURNRATE_MULT 0.4 +#define FIRE_LIQUID_BURNRATE_MULT 0.225 //If the fire is burning slower than this rate then the reaction is going too slow to be self sustaining and the fire burns itself out. //This ensures that fires don't grind to a near-halt while still remaining active forever. #define FIRE_GAS_MIN_BURNRATE 0.01 -#define FIRE_LIQUD_MIN_BURNRATE 0.01 +#define FIRE_LIQUD_MIN_BURNRATE 0.0025 //How many moles of fuel are contained within one solid/liquid fuel volume unit -#define LIQUIDFUEL_AMOUNT_TO_MOL 1 //mol/volume unit +#define LIQUIDFUEL_AMOUNT_TO_MOL 0.45 //mol/volume unit #define T0C 273.15 // 0.0 degrees celcius #define T20C 293.15 // 20.0 degrees celcius From 63838b01d422d115c342b598883be9fdd11f6759 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Fri, 9 Oct 2015 11:18:12 -0400 Subject: [PATCH 036/207] Updates preset TTV bombs, adds debug verb --- .../objects/effects/spawners/bombspawner.dm | 83 ++++++++++++------- code/modules/admin/verbs/mapping.dm | 1 + 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index 547931a5118..05d1a41bf25 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -105,27 +105,61 @@ qdel(src) */ +/client/proc/spawn_tanktransferbomb() + set category = "Debug" + set desc = "Spawn a tank transfer valve bomb" + set name = "Instant TTV" + + if(!check_rights(R_SPAWN)) return + + var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom + + var/p = input("Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt)) as num|null + if(p == null) return + + var/o = input("Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt)) as num|null + if(o == null) return + + var/c = input("Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt)) as num|null + if(c == null) return + + new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c) + /obj/effect/spawner/newbomb - name = "bomb" + name = "TTV bomb" icon = 'icons/mob/screen1.dmi' icon_state = "x" - var/btype = 0 // 0=radio, 1=prox, 2=time + + var/assembly_type = /obj/item/device/assembly/signaler + + //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa is 16.44 mol. + var/phoron_amt = 10.96 + var/oxygen_amt = 16.44 + var/carbon_amt = 0.0 - timer - btype = 2 +/obj/effect/spawner/newbomb/timer + name = "TTV bomb - timer" + assembly_type = /obj/item/device/assembly/timer - syndicate +/obj/effect/spawner/newbomb/timer/syndicate + name = "TTV bomb - merc" + //High yield bombs. Yes, it is possible to make these with toxins + phoron_amt = 15.66 + oxygen_amt = 24.66 - proximity - btype = 1 +/obj/effect/spawner/newbomb/proximity + name = "TTV bomb - proximity" + assembly_type = /obj/item/device/assembly/prox_sensor - radio - btype = 0 - - -/obj/effect/spawner/newbomb/New() +/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co) + if(ph != null) phoron_amt = ph + if(ox != null) oxygen_amt = ox + if(co != null) carbon_amt = co ..() +/obj/effect/spawner/newbomb/New(newloc) + ..(newloc) + var/obj/item/device/transfer_valve/V = new(src.loc) var/obj/item/weapon/tank/phoron/PT = new(V) var/obj/item/weapon/tank/oxygen/OT = new(V) @@ -137,28 +171,15 @@ OT.master = V PT.air_contents.temperature = PHORON_FLASHPOINT - PT.air_contents.adjust_multi("phoron", 12, "carbon_dioxide", 8) + PT.air_contents.gas["phoron"] = phoron_amt + PT.air_contents.gas["carbon_dioxide"] = carbon_amt + PT.air_contents.update_values() OT.air_contents.temperature = PHORON_FLASHPOINT - OT.air_contents.adjust_gas("oxygen", 20) + OT.air_contents.gas["oxygen"] = oxygen_amt + OT.air_contents.update_values() - var/obj/item/device/assembly/S - - switch (src.btype) - // radio - if (0) - - S = new/obj/item/device/assembly/signaler(V) - - // proximity - if (1) - - S = new/obj/item/device/assembly/prox_sensor(V) - - // timer - if (2) - - S = new/obj/item/device/assembly/timer(V) + var/obj/item/device/assembly/S = new assembly_type(V) V.attached_device = S diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index bd3c4be0d92..29d2b95d88e 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -162,6 +162,7 @@ var/list/debug_verbs = list ( ,/client/proc/testZAScolors_remove ,/client/proc/setup_supermatter_engine ,/client/proc/atmos_toggle_debug + ,/client/proc/spawn_tanktransferbomb ) From 6c3bbb9ee82f36e35f1503a16a301d9604bbdff9 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Fri, 9 Oct 2015 11:21:12 -0400 Subject: [PATCH 037/207] Updates changelog, fixes comment --- .../objects/effects/spawners/bombspawner.dm | 2 +- html/changelogs/HarpyEagle-ttv.yml | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 html/changelogs/HarpyEagle-ttv.yml diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index 05d1a41bf25..fb4716043f1 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -132,7 +132,7 @@ var/assembly_type = /obj/item/device/assembly/signaler - //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa is 16.44 mol. + //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol. var/phoron_amt = 10.96 var/oxygen_amt = 16.44 var/carbon_amt = 0.0 diff --git a/html/changelogs/HarpyEagle-ttv.yml b/html/changelogs/HarpyEagle-ttv.yml new file mode 100644 index 00000000000..67d426e234e --- /dev/null +++ b/html/changelogs/HarpyEagle-ttv.yml @@ -0,0 +1,21 @@ +################################ +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +author: HarpyEagle +delete-after: True +changes: + - bugfix: "Fixed a couple of bugs causing phoron gas fires to burn cooler and slower than they were supposed to." + - bugfix: "Merc bombs are now appropriately explosive again. Same goes for bombs made by toxins." From 80cc83dbf8cc39aebec64f240c1a68bdef15ec05 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Fri, 9 Oct 2015 17:44:30 +0200 Subject: [PATCH 038/207] Fixes backup power test light --- code/datums/wires/airlock.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index a0f1f9c7f1c..b204dc4eb0e 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -41,7 +41,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 (A.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"), ((haspower) ? "The test light is on." : "The test light is off!"), - ((A.backupPowerCablesCut()) ? "The backup power light is off!" : "The backup power light is on."), + ((A.backup_power_lost_until) ? "The backup power light is off!" : "The backup power light is on."), ((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), ((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."), ((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."), From 5684befee2da7cc29d4d6b20b8adc4e06cda0211 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Fri, 9 Oct 2015 18:24:19 -0400 Subject: [PATCH 039/207] Fixes #11262 --- code/modules/mob/living/carbon/breathe.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 2 +- code/modules/mob/living/carbon/human/life.dm | 6 ++++++ code/modules/organs/organ.dm | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index b467b88cd2e..2746e0c82e9 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -49,7 +49,7 @@ breath = environment.remove_volume(volume_needed) handle_chemical_smoke(environment) //handle chemical smoke while we're at it - if(breath) + if(breath && breath.total_moles) //handle mask filtering if(istype(wear_mask, /obj/item/clothing/mask) && breath) var/obj/item/clothing/mask/M = wear_mask diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 1ebbd792c6e..9987f7509e5 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -967,7 +967,7 @@ if(L && !L.is_bruised()) src.custom_pain("You feel a stabbing pain in your chest!", 1) - L.damage = L.min_bruised_damage + L.bruise() /* /mob/living/carbon/human/verb/simulate() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index efb450db44e..cbec800efd5 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -370,6 +370,12 @@ if(status_flags & GODMODE) return + //exposure to extreme pressures can rupture lungs + if(breath && (breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)) + if(!is_lung_ruptured() && prob(5)) + rupture_lung() + + //check if we actually need to process breath if(!breath || (breath.total_moles == 0) || suiciding) failed_last_breath = 1 if(suiciding) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index fd17fc2f9fe..0e628fa7124 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -206,6 +206,9 @@ var/list/organ_cache = list() if(parent && !silent) owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1) +/obj/item/organ/proc/bruise() + damage = max(damage, min_bruised_damage) + /obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc robotic = 2 src.status &= ~ORGAN_BROKEN From fa86509daf0d0e8088104679846114c3bc9e302a Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Fri, 9 Oct 2015 18:25:10 -0400 Subject: [PATCH 040/207] Readds organ damage from failing to mend ribs --- code/modules/surgery/encased.dm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index 8e1a5163842..93a1bbf0e5c 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -172,10 +172,12 @@ affected.createwound(BRUISE, 20) affected.fracture() - - /*if (prob(40)) //TODO: ORGAN REMOVAL UPDATE. - user.visible_message("\red A rib pierces the lung!") - target.rupture_lung()*/ + + if(affected.internal_organs && affected.internal_organs.len) + if(prob(40)) + var/obj/item/organ/O = pick(affected.internal_organs) //TODO weight by organ size + user.visible_message("A wayward piece of [target]'s [affected.encased] pierces \his [O.name]!") + O.bruise() /datum/surgery_step/open_encased/mend allowed_tools = list( From 2daa53ba4fba195b95aeb46c7198601231f94842 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 10 Oct 2015 08:37:16 +0200 Subject: [PATCH 041/207] Fixes #11266. Rotates the connector properly. --- maps/exodus-1.dmm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index b512e9296fa..3f64986e67a 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -6644,7 +6644,7 @@ "cxN" = (/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) "cxO" = (/obj/machinery/atmospherics/binary/pump{dir = 1},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) "cxP" = (/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = 28},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) -"cxQ" = (/obj/machinery/atmospherics/portables_connector,/obj/machinery/portable_atmospherics/canister/air/airlock,/turf/simulated/floor/plating{dir = 2; icon_state = "warnplatecorner"},/area/maintenance/medbay) +"cxQ" = (/obj/machinery/portable_atmospherics/canister/air/airlock,/obj/machinery/atmospherics/portables_connector{dir = 4},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplatecorner"},/area/maintenance/medbay) "cxR" = (/obj/machinery/door/airlock{name = "Starboard Emergency Storage"; req_one_access = list(12,47)},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/storage/emergency) "cxS" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/structure/closet/secure_closet/personal/patient,/turf/simulated/floor{dir = 8; icon_state = "greencorner"},/area/medical/virology) "cxT" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8},/turf/simulated/floor{dir = 2; icon_state = "green"},/area/medical/virology) From fd3370c01fdcda632f951a655dcd3b2c172c8f68 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 10 Oct 2015 08:48:37 +0200 Subject: [PATCH 042/207] Fixes #11263. Now possible to use items other than emags on holodeck computers Blobs no longer make computers lose their density state. Holodeck computers can now be repaired (and built, but since they cannot be configured they'll be useless). Fixes #11263. --- baystation12.dme | 1 + code/game/machinery/computer/computer.dm | 19 ++--- .../circuitboards/computer/holodeckcontrol.dm | 31 +++++++ code/modules/holodeck/HolodeckControl.dm | 80 +++++++++++++------ maps/exodus-1.dmm | 2 +- 5 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm diff --git a/baystation12.dme b/baystation12.dme index 2566203ca05..a79cce10948 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -657,6 +657,7 @@ #include "code\game\objects\items\weapons\circuitboards\computer\air_management.dm" #include "code\game\objects\items\weapons\circuitboards\computer\camera_monitor.dm" #include "code\game\objects\items\weapons\circuitboards\computer\computer.dm" +#include "code\game\objects\items\weapons\circuitboards\computer\holodeckcontrol.dm" #include "code\game\objects\items\weapons\circuitboards\computer\research.dm" #include "code\game\objects\items\weapons\circuitboards\computer\supply.dm" #include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm" diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index baa75fed05f..1e9409437af 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -12,6 +12,11 @@ var/light_range_on = 3 var/light_power_on = 1 +/obj/machinery/computer/Destroy() + qdel(circuit) + circuit = null + return ..() + /obj/machinery/computer/initialize() power_change() @@ -70,7 +75,6 @@ for(var/x in verbs) verbs -= x set_broken() - density = 0 /obj/machinery/computer/update_icon() ..() @@ -124,22 +128,15 @@ for (var/obj/C in src) C.loc = src.loc if (src.stat & BROKEN) - user << "\blue The broken glass falls out." + user << "The broken glass falls out." new /obj/item/weapon/material/shard( src.loc ) A.state = 3 A.icon_state = "3" else - user << "\blue You disconnect the monitor." + user << "You disconnect the monitor." A.state = 4 A.icon_state = "4" M.deconstruct(src) qdel(src) else - src.attack_hand(user) - return - - - - - - + ..() diff --git a/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm new file mode 100644 index 00000000000..db11c4de502 --- /dev/null +++ b/code/game/objects/items/weapons/circuitboards/computer/holodeckcontrol.dm @@ -0,0 +1,31 @@ +#ifndef T_BOARD +#error T_BOARD macro is not defined but we need it! +#endif + +/obj/item/weapon/circuitboard/holodeckcontrol + name = T_BOARD("holodeck control console") + build_path = /obj/machinery/computer/HolodeckControl + origin_tech = "programming=2;bluespace=2" + var/last_to_emag + var/linkedholodeck_area + var/list/supported_programs + var/list/restricted_programs + +/obj/item/weapon/circuitboard/holodeckcontrol/construct(var/obj/machinery/computer/HolodeckControl/HC) + if (..(HC)) + HC.supported_programs = supported_programs.Copy() + HC.restricted_programs = restricted_programs.Copy() + if(linkedholodeck_area) + HC.linkedholodeck = locate(linkedholodeck_area) + if(last_to_emag) + HC.last_to_emag = last_to_emag + HC.emagged = 1 + HC.safety_disabled = 1 + +/obj/item/weapon/circuitboard/holodeckcontrol/deconstruct(var/obj/machinery/computer/HolodeckControl/HC) + if (..(HC)) + linkedholodeck_area = HC.linkedholodeck_area + supported_programs = HC.supported_programs.Copy() + restricted_programs = HC.restricted_programs.Copy() + last_to_emag = HC.last_to_emag + HC.emergencyShutdown() diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm index 0509bf3d86a..87c0b7e4450 100644 --- a/code/modules/holodeck/HolodeckControl.dm +++ b/code/modules/holodeck/HolodeckControl.dm @@ -5,10 +5,13 @@ use_power = 1 active_power_usage = 8000 //8kW for the scenery + 500W per holoitem + + circuit = /obj/item/weapon/circuitboard/holodeckcontrol + var/item_power_usage = 500 var/area/linkedholodeck = null - var/area/target = null + var/linkedholodeck_area var/active = 0 var/list/holographic_objs = list() var/list/holographic_mobs = list() @@ -17,34 +20,39 @@ var/mob/last_to_emag = null var/last_change = 0 var/last_gravity_change = 0 - var/list/supported_programs = list( \ - "Empty Court" = "emptycourt", \ - "Basketball Court" = "basketball", \ - "Thunderdome Court" = "thunderdomecourt", \ - "Boxing Ring"="boxingcourt", \ - "Beach" = "beach", \ - "Desert" = "desert", \ - "Space" = "space", \ - "Picnic Area" = "picnicarea", \ - "Snow Field" = "snowfield", \ - "Theatre" = "theatre", \ - "Meeting Hall" = "meetinghall", \ - "Courtroom" = "courtroom" \ - ) - var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp") + var/list/supported_programs + var/list/restricted_programs + +/obj/machinery/computer/HolodeckControl/New() + ..() + linkedholodeck = locate(linkedholodeck_area) + supported_programs = list() + restricted_programs = list() /obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob) return src.attack_hand(user) /obj/machinery/computer/HolodeckControl/attack_hand(var/mob/user as mob) - if(..()) - return + return 1 user.set_machine(src) var/dat dat += "Holodeck Control System
" dat += "
Current Loaded Programs:
" + + if(!linkedholodeck) + dat += "Warning: Unable to locate holodeck.
" + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + + if(!supported_programs.len) + dat += "Warning: No supported holo-programs loaded.
" + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + for(var/prog in supported_programs) dat += "
([prog])
" @@ -82,10 +90,8 @@ user << browse(dat, "window=computer;size=400x500") onclose(user, "computer") - return - /obj/machinery/computer/HolodeckControl/Topic(href, href_list) if(..()) return 1 @@ -131,8 +137,9 @@ user << "You vastly increase projector power and override the safety and security protocols." user << "Warning. Automatic shutoff and derezing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator." log_game("[key_name(usr)] emagged the Holodeck Control Computer") - src.updateUsrDialog() - return + src.updateUsrDialog() + else + ..() /obj/machinery/computer/HolodeckControl/proc/update_projections() if (safety_disabled) @@ -149,10 +156,6 @@ if (last_to_emag) C.friends = list(last_to_emag) -/obj/machinery/computer/HolodeckControl/New() - ..() - linkedholodeck = locate(/area/holodeck/alphadeck) - //This could all be done better, but it works for now. /obj/machinery/computer/HolodeckControl/Destroy() emergencyShutdown() @@ -345,3 +348,28 @@ active = 0 use_power = 1 + +/obj/machinery/computer/HolodeckControl/Exodus + linkedholodeck_area = /area/holodeck/alphadeck + +/obj/machinery/computer/HolodeckControl/Exodus/New() + ..() + supported_programs = list( + "Empty Court" = "emptycourt", + "Basketball Court" = "basketball", + "Thunderdome Court" = "thunderdomecourt", + "Boxing Ring" = "boxingcourt", + "Beach" = "beach", + "Desert" = "desert", + "Space" = "space", + "Picnic Area" = "picnicarea", + "Snow Field" = "snowfield", + "Theatre" = "theatre", + "Meeting Hall" = "meetinghall", + "Courtroom" = "courtroom" + ) + + restricted_programs = list( + "Atmospheric Burn Simulation" = "burntest", + "Wildlife Simulation" = "wildlifecarp" + ) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index b512e9296fa..ea5d8de765a 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -1360,7 +1360,7 @@ "aAh" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/sleep/bedrooms) "aAi" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/maintenance/dormitory) "aAj" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/atmospherics/binary/pump/on{dir = 1; target_pressure = 200},/turf/simulated/floor/plating,/area/maintenance/evahallway) -"aAk" = (/obj/machinery/computer/HolodeckControl,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor,/area/crew_quarters/fitness) +"aAk" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/computer/HolodeckControl/Exodus,/turf/simulated/floor,/area/crew_quarters/fitness) "aAl" = (/obj/machinery/light,/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -27},/turf/simulated/floor{icon_state = "neutral"},/area/crew_quarters/sleep) "aAm" = (/turf/simulated/floor{icon_state = "neutral"},/area/crew_quarters/sleep) "aAn" = (/turf/simulated/floor{icon_state = "neutral"; dir = 6},/area/crew_quarters/sleep) From 92ea0f6e9ace4acfb90f03bb9a4d2d3ea8044e31 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 10 Oct 2015 10:15:14 +0200 Subject: [PATCH 043/207] Updates changelog. --- html/changelog.html | 8 ++++++++ html/changelogs/.all_changelog.yml | 7 +++++++ html/changelogs/HarpyEagle-rubberbullets.yml | 20 ------------------- html/changelogs/HarpyEagle-ttv.yml | 21 -------------------- 4 files changed, 15 insertions(+), 41 deletions(-) delete mode 100644 html/changelogs/HarpyEagle-rubberbullets.yml delete mode 100644 html/changelogs/HarpyEagle-ttv.yml diff --git a/html/changelog.html b/html/changelog.html index 5c6a149e932..64639f2244a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,14 @@ -->
+

10 October 2015

+

HarpyEagle updated:

+
    +
  • Rubber bullets and beanbags now are now resisted by melee armour.
  • +
  • Fixed a couple of bugs causing phoron gas fires to burn cooler and slower than they were supposed to.
  • +
  • Merc bombs are now appropriately explosive again. Same goes for bombs made by toxins.
  • +
+

11 September 2015

HarpyEagle updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 4c024323f5a..2db1c6ec288 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2017,3 +2017,10 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2015-09-11: HarpyEagle: - tweak: Made flares brighter. +2015-10-10: + HarpyEagle: + - tweak: Rubber bullets and beanbags now are now resisted by melee armour. + - bugfix: Fixed a couple of bugs causing phoron gas fires to burn cooler and slower + than they were supposed to. + - bugfix: Merc bombs are now appropriately explosive again. Same goes for bombs + made by toxins. diff --git a/html/changelogs/HarpyEagle-rubberbullets.yml b/html/changelogs/HarpyEagle-rubberbullets.yml deleted file mode 100644 index 841373a9f9a..00000000000 --- a/html/changelogs/HarpyEagle-rubberbullets.yml +++ /dev/null @@ -1,20 +0,0 @@ -################################ -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -author: HarpyEagle -delete-after: True -changes: - - tweak: "Rubber bullets and beanbags now are now resisted by melee armour." diff --git a/html/changelogs/HarpyEagle-ttv.yml b/html/changelogs/HarpyEagle-ttv.yml deleted file mode 100644 index 67d426e234e..00000000000 --- a/html/changelogs/HarpyEagle-ttv.yml +++ /dev/null @@ -1,21 +0,0 @@ -################################ -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -author: HarpyEagle -delete-after: True -changes: - - bugfix: "Fixed a couple of bugs causing phoron gas fires to burn cooler and slower than they were supposed to." - - bugfix: "Merc bombs are now appropriately explosive again. Same goes for bombs made by toxins." From d3572bf4cb5dcaa0e4b0d874d8fd345d629d52ce Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Sat, 10 Oct 2015 15:55:25 +0200 Subject: [PATCH 044/207] Fixes empty flavor text drawing two spaces --- code/modules/mob/living/carbon/human/human.dm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9987f7509e5..308f2359e1f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1269,11 +1269,10 @@ if(C.body_parts_covered & FEET) feet_exposed = 0 - flavor_text = flavor_texts["general"] - flavor_text += "\n\n" + flavor_text = "" for (var/T in flavor_texts) if(flavor_texts[T] && flavor_texts[T] != "") - if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed)) + if((T == "general") || (T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed)) flavor_text += flavor_texts[T] flavor_text += "\n\n" if(!shrink) From cd182a3e1c131ff3d419b40b423fb4a0d0292620 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Sat, 10 Oct 2015 15:59:47 +0200 Subject: [PATCH 045/207] Updates Changelog --- html/changelogs/Hubblenaut-master.yml | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 html/changelogs/Hubblenaut-master.yml diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-master.yml new file mode 100644 index 00000000000..783ec67eead --- /dev/null +++ b/html/changelogs/Hubblenaut-master.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Hubblenaut + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Airlock backup power test light properly offline when backup power down." + - bugfix: "Empty flavor texts no longer draw an empty line on examination." From dec0629faef89df1b59d6a15931233ffce833e26 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 11 Oct 2015 11:26:01 -0400 Subject: [PATCH 046/207] Renames latespawn() to be less confusing --- code/game/gamemodes/game_mode_latespawn.dm | 3 ++- code/modules/mob/new_player/new_player.dm | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 038cf351ab8..f2bce2d8718 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -20,7 +20,8 @@ process_count = 0 try_latespawn() -/datum/game_mode/proc/latespawn(var/mob/living/carbon/human/character) +//This can be overriden in case a game mode needs to do stuff when a player latejoins +/datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character) if(!character.mind) return try_latespawn(character.mind) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index fb3b6f4fca3..6afacc4af97 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -323,7 +323,7 @@ character.loc = C.loc AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [character.loc.loc]") - ticker.mode.latespawn(character) + ticker.mode.handle_latejoin(character) qdel(C) qdel(src) @@ -354,7 +354,7 @@ character.buckled.loc = character.loc character.buckled.set_dir(character.dir) - ticker.mode.latespawn(character) + ticker.mode.handle_latejoin(character) if(character.mind.assigned_role != "Cyborg") data_core.manifest_inject(character) From 43d5f2e3bd493ff6fb6b9673be190af953684659 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 11 Oct 2015 11:39:26 -0400 Subject: [PATCH 047/207] Ensures leftover candidates and pending antags are cleared after finalizing --- code/game/antagonist/antagonist.dm | 9 +++++++-- code/game/gamemodes/game_mode.dm | 2 +- code/modules/mob/new_player/new_player.dm | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index faf7526a9cb..d9bc5c56901 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -186,11 +186,16 @@ for(var/datum/mind/player in pending_antagonists) pending_antagonists -= player add_antagonist(player,0,0,1) + + reset_antag_selection() -//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set) -/datum/antagonist/proc/reset() +//Resets the antag selection, clearing all pending_antagonists and their special_role +//(and assigned_role if ANTAG_OVERRIDE_JOB is set) as well as clearing the candidate list. +//Existing antagonists are left untouched. +/datum/antagonist/proc/reset_antag_selection() for(var/datum/mind/player in pending_antagonists) if(flags & ANTAG_OVERRIDE_JOB) player.assigned_role = null player.special_role = null pending_antagonists.Cut() + candidates.Cut() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 705c044e01b..57a936f581f 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -305,7 +305,7 @@ var/global/list/additional_antag_types = list() /datum/game_mode/proc/fail_setup() for(var/datum/antagonist/antag in antag_templates) - antag.reset() + antag.reset_antag_selection() /datum/game_mode/proc/announce_ert_disabled() if(!ert_disabled) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6afacc4af97..9eb43e48d98 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -289,7 +289,7 @@ proc/AttemptLateSpawn(rank,var/spawning_at) - if (src != usr) + if(src != usr) return 0 if(!ticker || ticker.current_state != GAME_STATE_PLAYING) usr << "\red The round is either not ready, or has already finished..." From d715e0645fada6bfe067fc93b2d4cb863053b00b Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 11 Oct 2015 11:48:04 -0400 Subject: [PATCH 048/207] Removes unused latejoin template list --- code/game/gamemodes/game_mode.dm | 3 --- code/game/gamemodes/game_mode_latespawn.dm | 6 ++---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 57a936f581f..b8a99badf11 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -22,7 +22,6 @@ var/global/list/additional_antag_types = list() var/list/antag_tags = list() // Core antag templates to spawn. var/list/antag_templates // Extra antagonist types to include. - var/list/latejoin_templates = list() var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists? var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count. var/require_all_templates = 0 // Will only start if all templates are checked and can spawn. @@ -291,8 +290,6 @@ var/global/list/additional_antag_types = list() if(!(antag.flags & ANTAG_OVERRIDE_JOB)) antag.attempt_spawn() //select antags to be spawned antag.finalize_spawn() //actually spawn antags - if(antag.is_latejoin_template()) - latejoin_templates |= antag if(emergency_shuttle && auto_recall_shuttle) emergency_shuttle.auto_recall = 1 diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index f2bce2d8718..28db276b493 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -27,7 +27,7 @@ try_latespawn(character.mind) return 0 -/datum/game_mode/proc/try_latespawn(var/datum/mind/player, var/latejoin_only) +/datum/game_mode/proc/try_latespawn(var/datum/mind/player) if(emergency_shuttle.departed || !round_autoantag) return @@ -38,9 +38,7 @@ message_admins("AUTO[uppertext(name)]: Attempting spawn.") var/list/usable_templates - if(latejoin_only && latejoin_templates.len) - usable_templates = get_usable_templates(latejoin_templates) - else if (antag_templates && antag_templates.len) + if (antag_templates && antag_templates.len) usable_templates = get_usable_templates(antag_templates) else message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.") From c7afded12d7aeac970d46f863021ebae08516d4a Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 11 Oct 2015 12:00:21 -0400 Subject: [PATCH 049/207] Cleans up calamity shuffle, makes sure antag types are selected in a random order for other game modes. --- code/game/gamemodes/calamity/calamity.dm | 13 +++++++------ code/game/gamemodes/game_mode.dm | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm index 4f7b9ab49de..3104e624e34 100644 --- a/code/game/gamemodes/calamity/calamity.dm +++ b/code/game/gamemodes/calamity/calamity.dm @@ -12,14 +12,15 @@ /datum/game_mode/calamity/create_antagonists() - shuffle(all_antag_types) // This is probably the only instance in the game where the order will be important. - var/i = 1 + //Let's not modify global lists for trivial reasons, even if it seems harmless right now. + var/list/antag_candidates = all_antag_types.Copy() + var/grab_antags = round(num_players()/ANTAG_TYPE_RATIO)+1 - for(var/antag_id in all_antag_types) - if(i > grab_antags) - break + while(antag_candidates.len && antag_tags.len < grab_antags) + var/antag_id = pick(antag_candidates) + antag_candidates -= antag_id antag_tags |= antag_id - i++ + ..() /datum/game_mode/calamity/check_victory() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index b8a99badf11..08a82890602 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -572,6 +572,7 @@ var/global/list/additional_antag_types = list() if(antag) antag_templates |= antag + shuffle(antag_templates) //In the case of multiple antag types newscaster_announcements = pick(newscaster_standard_feeds) /datum/game_mode/proc/check_victory() From e381e2faf2afa6b89ef7bbecf5e1854f0effd776 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 11 Oct 2015 12:16:08 -0400 Subject: [PATCH 050/207] Fixes do_not_announce parameters not actually doing anything --- code/game/antagonist/antagonist_create.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm index 416a774541a..1b8b82210a7 100644 --- a/code/game/antagonist/antagonist_create.dm +++ b/code/game/antagonist/antagonist_create.dm @@ -16,7 +16,8 @@ create_objectives(target) update_icons_added(target) greet(target) - announce_antagonist_spawn() + if(!gag_announcement) + announce_antagonist_spawn() /datum/antagonist/proc/create_default(var/mob/source) var/mob/living/M From 1c8ec1a700b5dbf229cbdb75d5d69c2e132ad0c4 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Sun, 11 Oct 2015 22:02:05 +0200 Subject: [PATCH 051/207] Fixes stack creation logic and return value --- code/game/objects/items/stacks/stack.dm | 7 +++-- code/modules/materials/material_sheets.dm | 5 +-- code/modules/materials/materials.dm | 2 -- html/changelogs/Hubblenaut-master.yml | 37 +++++++++++++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 html/changelogs/Hubblenaut-master.yml diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 8c5ac01c7a5..fdb73aa9679 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -137,6 +137,7 @@ if (istype(O, /obj/item/stack)) var/obj/item/stack/S = O S.amount = produced + S.add_to_stacks(user) if (istype(O, /obj/item/weapon/storage)) //BubbleWrap - so newly formed boxes are empty for (var/obj/item/I in O) @@ -284,13 +285,13 @@ return return max_amount -/obj/item/stack/proc/add_to_stacks(mob/usr as mob) - for (var/obj/item/stack/item in usr.loc) +/obj/item/stack/proc/add_to_stacks(mob/user as mob) + for (var/obj/item/stack/item in user.loc) if (item==src) continue var/transfer = src.transfer_to(item) if (transfer) - usr << "You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s." + user << "You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s." if(!amount) break diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index c2a2b56ab7b..0e6c03b1997 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -45,7 +45,7 @@ /obj/item/stack/material/proc/update_strings() // Update from material datum. singular_name = material.sheet_singular_name - + if(amount>1) name = "[material.use_name] [material.sheet_plural_name]" desc = "A stack of [material.use_name] [material.sheet_plural_name]." @@ -64,9 +64,10 @@ var/obj/item/stack/material/M = S if(!istype(M) || material.name != M.material.name) return 0 - ..(S,tamount,1) + var/transfer = ..(S,tamount,1) if(src) update_strings() if(M) M.update_strings() + return transfer /obj/item/stack/material/attack_self(var/mob/user) if(!material.build_windows(user, src)) diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 46ce8ea445d..5247291f7c8 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -128,8 +128,6 @@ var/list/name_to_material var/obj/item/stack/S = new rod_product(get_turf(user)) S.add_fingerprint(user) S.add_to_stacks(user) - if(!(user.l_hand && user.r_hand)) - user.put_in_hands(S) /material/proc/build_wired_product(var/mob/user, var/obj/item/stack/used_stack, var/obj/item/stack/target_stack) if(!wire_product) diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-master.yml new file mode 100644 index 00000000000..10426fff707 --- /dev/null +++ b/html/changelogs/Hubblenaut-master.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Hubblenaut + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Material stacks now properly merge upon creation." + - bugfix: "Messages for adding to existing stack appear again." From 7247906f41e362dfa7c329b5c46a3585ff3bbaeb Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 12 Oct 2015 12:55:34 +0200 Subject: [PATCH 052/207] ghostize() now attempts to set the most relevant time of death. ghostize() now only uses the mob's time of death if the mob is actually dead, otherwise uses the current time. Fixes #11229. --- code/modules/mob/dead/observer/observer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 80a5bdd5572..f2152a2454d 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -149,7 +149,7 @@ Works together with spawning an observer, noted above. if(key) var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc. ghost.can_reenter_corpse = can_reenter_corpse - ghost.timeofdeath = src.timeofdeath //BS12 EDIT + ghost.timeofdeath = src.stat == DEAD ? src.timeofdeath : world.time ghost.key = key if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! From ab5c5486e04afc7c947410bc8a1729f77363a4fc Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Mon, 12 Oct 2015 16:38:42 +0200 Subject: [PATCH 053/207] Update Changelog --- html/changelogs/{Hubblenaut-master.yml => Hubblenaut-stacks.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename html/changelogs/{Hubblenaut-master.yml => Hubblenaut-stacks.yml} (100%) diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-stacks.yml similarity index 100% rename from html/changelogs/Hubblenaut-master.yml rename to html/changelogs/Hubblenaut-stacks.yml From 241520f0bb4cc5e0d639df8942b86e7ec8c5f4d6 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Mon, 12 Oct 2015 12:47:41 -0400 Subject: [PATCH 054/207] Cleans up autospawn, now uses existing code for selecting and choosing candidates. Adds more debug messages, and removes unused code. --- code/game/antagonist/antagonist.dm | 54 +++++++++++++--------- code/game/antagonist/antagonist_helpers.dm | 6 +-- code/game/antagonist/station/rogue_ai.dm | 4 +- code/game/gamemodes/game_mode.dm | 1 + code/game/gamemodes/game_mode_latespawn.dm | 53 ++++++++------------- code/modules/admin/admin.dm | 7 ++- 6 files changed, 60 insertions(+), 65 deletions(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index d9bc5c56901..011ae5ebe6c 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -86,7 +86,8 @@ /datum/antagonist/proc/tick() return 1 -/datum/antagonist/proc/get_candidates(var/ghosts_only) +// Get the raw list of potential players. +/datum/antagonist/proc/build_candidate_list(var/ghosts_only) candidates = list() // Clear. // Prune restricted status. Broke it up for readability. @@ -108,46 +109,57 @@ return candidates /datum/antagonist/proc/attempt_random_spawn() + update_current_antag_max() build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) attempt_spawn() finalize_spawn() -/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player) +/datum/antagonist/proc/attempt_auto_spawn() if(!can_late_spawn()) return 0 - if(!istype(player)) - var/list/players = get_candidates(is_latejoin_template()) - if(players && players.len) - player = pick(players) - if(!istype(player)) - message_admins("AUTO[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].") - return 0 - player.current << "You have been selected this round as an antagonist!" - message_admins("AUTO[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].") - if(istype(player.current, /mob/dead)) - create_default(player.current) - else - add_antagonist(player,0,0,0,1,1) - return 1 -/datum/antagonist/proc/build_candidate_list(var/ghosts_only) - // Get the raw list of potential players. update_current_antag_max() - candidates = get_candidates(ghosts_only) + var/active_antags = get_active_antag_count() + log_debug("[uppertext(id)]: Found [active_antags]/[cur_max] active [role_text_plural].") + + if(active_antags >= cur_max) + log_debug("Could not auto-spawn a [role_text], active antag limit reached.") + return 0 + + build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + if(!candidates.len) + log_debug("Could not auto-spawn a [role_text], no candidates found.") + return 0 + + attempt_spawn(1) //auto-spawn antags one at a time + if(!pending_antagonists.len) + log_debug("Could not auto-spawn a [role_text], none of the available candidates could be selected.") + return 0 + + var/datum/mind/player = pending_antagonists[1] + if(!add_antagonist(player,0,0,0,1,1)) + log_debug("Could not auto-spawn a [role_text], failed to add antagonist.") + return 0 + + reset_antag_selection() + + return 1 //Selects players that will be spawned in the antagonist role from the potential candidates //Selected players are added to the pending_antagonists lists. //Attempting to spawn an antag role with ANTAG_OVERRIDE_JOB should be done before jobs are assigned, //so that they do not occupy regular job slots. All other antag roles should be spawned after jobs are //assigned, so that job restrictions can be respected. -/datum/antagonist/proc/attempt_spawn(var/rebuild_candidates = 1) +/datum/antagonist/proc/attempt_spawn(var/spawn_target = null) + if(spawn_target == null) + spawn_target = initial_spawn_target // Update our boundaries. if(!candidates.len) return 0 //Grab candidates randomly until we have enough. - while(candidates.len && pending_antagonists.len < initial_spawn_target) + while(candidates.len && pending_antagonists.len < spawn_target) var/datum/mind/player = pick(candidates) candidates -= player draft_antagonist(player) diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index 056fbd18651..37e332d8efb 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -20,6 +20,9 @@ /datum/antagonist/proc/get_antag_count() return current_antagonists ? current_antagonists.len : 0 +/datum/antagonist/proc/get_active_antag_count() + return get_antag_count() //TODO + /datum/antagonist/proc/is_antagonist(var/datum/mind/player) if(player in current_antagonists) return 1 @@ -33,9 +36,6 @@ return (flags & ANTAG_VOTABLE) /datum/antagonist/proc/can_late_spawn() - update_current_antag_max() - if(get_antag_count() >= cur_max) - return 0 return 1 /datum/antagonist/proc/is_latejoin_template() diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm index 52fa7e3f38e..a277df922b2 100644 --- a/code/game/antagonist/station/rogue_ai.dm +++ b/code/game/antagonist/station/rogue_ai.dm @@ -22,13 +22,11 @@ var/datum/antagonist/rogue_ai/malf malf = src -/datum/antagonist/rogue_ai/get_candidates() +/datum/antagonist/rogue_ai/build_candidate_list() ..() for(var/datum/mind/player in candidates) if(player.assigned_role && player.assigned_role != "AI") candidates -= player - if(!candidates.len) - return list() return candidates diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 08a82890602..28f420547fd 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -266,6 +266,7 @@ var/global/list/additional_antag_types = list() /datum/game_mode/proc/pre_setup() for(var/datum/antagonist/antag in antag_templates) + antag.update_current_antag_max() antag.build_candidate_list() //compile a list of all eligible candidates //antag roles that replace jobs need to be assigned before the job controller hands out jobs. diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 28db276b493..9a10f0ce358 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -3,54 +3,39 @@ /datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes. /datum/game_mode/var/process_count = 0 -/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates) - var/list/usable_templates = list() - for(var/datum/antagonist/A in supplied_templates) - if(A.can_late_spawn()) - message_admins("AUTO[uppertext(name)]: [A.id] selected for spawn attempt.") - usable_templates |= A - return usable_templates - ///process() ///Called by the gameticker /datum/game_mode/proc/process() - // Slow this down a bit so latejoiners have a chance of being antags. - process_count++ - if(process_count >= 10) - process_count = 0 - try_latespawn() + if(round_autoantag && world.time < next_spawn && !emergency_shuttle.departed) + process_autoantag() //This can be overriden in case a game mode needs to do stuff when a player latejoins /datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character) - if(!character.mind) - return - try_latespawn(character.mind) return 0 -/datum/game_mode/proc/try_latespawn(var/datum/mind/player) +/datum/game_mode/proc/process_autoantag() + message_admins("[uppertext(name)]: Attempting autospawn.") - if(emergency_shuttle.departed || !round_autoantag) - return - - if(world.time < next_spawn) - return - - message_admins("AUTO[uppertext(name)]: Attempting spawn.") - - var/list/usable_templates - if (antag_templates && antag_templates.len) - usable_templates = get_usable_templates(antag_templates) - else - message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.") + var/list/usable_templates = list() + for(var/datum/antagonist/A in antag_templates) + if(A.can_late_spawn()) + message_admins("[uppertext(name)]: [A.id] selected for spawn attempt.") + usable_templates |= A + + if(!usable_templates.len) + message_admins("[uppertext(name)]: Failed to find configured mode spawn templates, please re-enable auto-antagonists after one is added.") round_autoantag = 0 return - + while(usable_templates.len) var/datum/antagonist/spawn_antag = pick(usable_templates) usable_templates -= spawn_antag - if(spawn_antag.attempt_late_spawn(player)) - message_admins("AUTO[uppertext(name)]: Attempting to latespawn [spawn_antag.id]. ([spawn_antag.get_antag_count()]/[spawn_antag.cur_max])") + + if(spawn_antag.attempt_auto_spawn()) + message_admins("[uppertext(name)]: Auto-added a new [spawn_antag.role_text].") + message_admins("There are now [spawn_antag.get_active_antag_count()]/[spawn_antag.cur_max] active [spawn_antag.role_text_plural].") next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) return - message_admins("AUTO[uppertext(name)]: Failed to proc a viable spawn template.") + + message_admins("[uppertext(name)]: Failed to proc a viable spawn template.") next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index f02292d81f1..241f394cca4 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1386,7 +1386,7 @@ proc/admin_notice(var/message, var/rights) var/datum/antagonist/antag = all_antag_types[antag_type] message_admins("[key_name(usr)] attempting to force latespawn with template [antag.id].") - antag.attempt_late_spawn() + antag.attempt_auto_spawn() /datum/admins/proc/force_mode_latespawn() set category = "Admin" @@ -1403,6 +1403,5 @@ proc/admin_notice(var/message, var/rights) usr << "Mode has not started." return - message_admins("[key_name(usr)] attempting to force mode latespawn.") - ticker.mode.next_spawn = 0 - ticker.mode.try_latespawn() + message_admins("[key_name(usr)] attempting to force mode autospawn.") + ticker.mode.process_autoantag() From c0dc32d60cbe5a2adde646fc84de4072ed471317 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Mon, 12 Oct 2015 12:50:48 -0400 Subject: [PATCH 055/207] If an antag could not be auto-spawned, the game rechecks in the minimum time. --- code/game/gamemodes/game_mode_latespawn.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 9a10f0ce358..9c79a689251 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -38,4 +38,4 @@ return message_admins("[uppertext(name)]: Failed to proc a viable spawn template.") - next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay) + next_spawn = world.time + min_autotraitor_delay //recheck again in the miniumum time From f0244bc9e5b45ad2435153eb208fd02c6b706f68 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 13 Oct 2015 08:02:26 +0200 Subject: [PATCH 056/207] Antag spawner now uses the starting location list... ..instead of the mob. Someone (might just maybe potentially be me, who knows) cleaned up the code a bit too quickly. Fixes #11284. --- code/game/antagonist/antagonist_place.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist_place.dm b/code/game/antagonist/antagonist_place.dm index b5f62868dc5..11ea718f8cc 100644 --- a/code/game/antagonist/antagonist_place.dm +++ b/code/game/antagonist/antagonist_place.dm @@ -23,5 +23,5 @@ /datum/antagonist/proc/place_mob(var/mob/living/mob) if(!starting_locations || !starting_locations.len) return - var/turf/T = pick_mobless_turf_if_exists(mob) + var/turf/T = pick_mobless_turf_if_exists(starting_locations) mob.forceMove(T) From 78956843a819b8e497066e803a18f28d79c519ad Mon Sep 17 00:00:00 2001 From: Kearel Date: Tue, 13 Oct 2015 12:30:52 -0500 Subject: [PATCH 057/207] Pointed secret changes to master New gamemodes on dev will still need to be changed. --- code/game/gamemodes/changeling/changeling.dm | 1 - code/game/gamemodes/cult/cult.dm | 1 - code/game/gamemodes/epidemic/epidemic.dm | 1 - code/game/gamemodes/game_mode.dm | 9 ++------- code/game/gamemodes/heist/heist.dm | 1 - code/game/gamemodes/malfunction/malfunction.dm | 1 - code/game/gamemodes/meme/meme.dm | 1 - code/game/gamemodes/ninja/ninja.dm | 1 - code/game/gamemodes/nuclear/nuclear.dm | 1 - code/game/gamemodes/revolution/revolution.dm | 1 - code/game/gamemodes/wizard/wizard.dm | 1 - html/changelogs/TheWelp-secRemoveMaster.yml | 6 ++++++ 12 files changed, 8 insertions(+), 17 deletions(-) create mode 100644 html/changelogs/TheWelp-secRemoveMaster.yml diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 678d6d71839..1f0745ca288 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -5,7 +5,6 @@ extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. Its unique biology allows it to manipulate its own or anyone else's DNA. With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, its existence is a threat to not only your personal safety but the lives of everyone on board. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck." config_tag = "changeling" required_players = 2 - required_players_secret = 10 required_enemies = 1 end_on_antag_death = 1 antag_scaling_coeff = 10 diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index a1c0acf0081..afc4ed6dd7a 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -4,7 +4,6 @@ extended_round_description = "The station has been infiltrated by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!" config_tag = "cult" required_players = 5 - required_players_secret = 15 required_enemies = 3 uplink_welcome = "Nar-Sie Uplink Console:" end_on_antag_death = 1 diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm index f3017bb1a19..05296b4f269 100644 --- a/code/game/gamemodes/epidemic/epidemic.dm +++ b/code/game/gamemodes/epidemic/epidemic.dm @@ -2,7 +2,6 @@ name = "epidemic" config_tag = "epidemic" required_players = 1 - required_players_secret = 15 round_description = "A deadly epidemic is spreading on the station. Find a cure as fast as possible, and keep your distance to anyone who speaks in a hoarse voice!" var/cruiser_arrival diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 8c0254829a8..e2e37fa66b3 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -30,7 +30,6 @@ var/global/list/additional_antag_types = list() var/probability = 0 var/required_players = 0 // Minimum players for round to start if voted in. - var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret var/required_enemies = 0 // Minimum antagonists for round to start. var/newscaster_announcements = null var/end_on_antag_death = 0 // Round will end when all antagonists are dead. @@ -235,12 +234,8 @@ var/global/list/additional_antag_types = list() if((player.client)&&(player.ready)) playerC++ - if(master_mode=="secret") - if(playerC < required_players_secret) - return 0 - else - if(playerC < required_players) - return 0 + if(playerC < required_players) + return 0 if(!(antag_templates && antag_templates.len)) return 1 diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 03680c8ff34..97c2d19b9b3 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -9,7 +9,6 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' name = "heist" config_tag = "heist" required_players = 15 - required_players_secret = 25 required_enemies = 4 round_description = "An unidentified bluespace signature has slipped past the Icarus and is approaching the station!" end_on_antag_death = 1 diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 19378de1670..c7ddc4d4088 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -5,7 +5,6 @@ uplink_welcome = "Crazy AI Uplink Console:" config_tag = "malfunction" required_players = 2 - required_players_secret = 7 required_enemies = 1 end_on_antag_death = 0 auto_recall_shuttle = 0 diff --git a/code/game/gamemodes/meme/meme.dm b/code/game/gamemodes/meme/meme.dm index 2aa512264df..ac78fe70bea 100644 --- a/code/game/gamemodes/meme/meme.dm +++ b/code/game/gamemodes/meme/meme.dm @@ -6,7 +6,6 @@ name = "Memetic Anomaly" config_tag = "meme" required_players = 3 - required_players_secret = 10 restricted_jobs = list("AI", "Cyborg") recommended_enemies = 2 // need at least a meme and a host votable = 0 // temporarily disable this mode for voting diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index d410dbeb7d3..86b7c6804bd 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -5,6 +5,5 @@ antag_tag = MODE_NINJA config_tag = "ninja" required_players = 1 - required_players_secret = 10 required_enemies = 1 end_on_antag_death = 1 \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index b556ba20709..fccc0790474 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -7,7 +7,6 @@ round_description = "A mercenary strike force is approaching the station!" config_tag = "mercenary" required_players = 15 - required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining required_enemies = 1 end_on_antag_death = 1 antag_tag = MODE_MERCENARY diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 1231e2e3a6e..718f30d502d 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -4,7 +4,6 @@ round_description = "Some crewmembers are attempting to start a revolution!" extended_round_description = "Revolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
    \nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head)." required_players = 4 - required_players_secret = 15 required_enemies = 3 auto_recall_shuttle = 1 uplink_welcome = "AntagCorp Uplink Console:" diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index c000c12ec06..979fbca02c4 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -4,7 +4,6 @@ extended_round_description = "A powerful entity capable of manipulating the elements around him, most commonly referred to as a 'wizard', has infiltrated the station. They have a wide variety of powers and spells available to them that makes your own simple moral self tremble with fear and excitement. Ultimately, their purpose is unknown. However, it is up to you and your crew to decide if their powers can be used for good or if their arrival foreshadows the destruction of the entire station." config_tag = "wizard" required_players = 1 - required_players_secret = 10 required_enemies = 1 uplink_welcome = "Wizardly Uplink Console:" uplink_uses = 10 diff --git a/html/changelogs/TheWelp-secRemoveMaster.yml b/html/changelogs/TheWelp-secRemoveMaster.yml new file mode 100644 index 00000000000..bcf7c7a0294 --- /dev/null +++ b/html/changelogs/TheWelp-secRemoveMaster.yml @@ -0,0 +1,6 @@ +author: TheWelp + +delete-after: True + +changes: + - rscdel: "Removed Higher Secret Player Requirements" From d7b6784e2834d18ea01353db2b14732be7687e1c Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 13 Oct 2015 19:44:49 +0200 Subject: [PATCH 058/207] Fixes law change logging. The "Show last X law changes" review window should now actually be useful, displaying AI law updates with time, user, and law change. --- code/modules/admin/admin.dm | 2 +- code/modules/admin/topic.dm | 2 +- code/modules/mob/living/silicon/laws.dm | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index f02292d81f1..93318196549 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -612,7 +612,7 @@ proc/admin_notice(var/message, var/rights) Bombing List
    Show current traitors and objectives
    Show last [length(lastsignalers)] signalers
    - Show last [length(lawchanges)] law changes
    + Show last [lawchanges.len] law change\s
    Show AI Laws
    Show Game Mode
    Show Crew Manifest
    diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 983292ebc36..45397fa097b 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2300,7 +2300,7 @@ dat += "[sig]
    " usr << browse(dat, "window=lastsignalers;size=800x500") if("list_lawchanges") - var/dat = "Showing last [length(lawchanges)] law changes.
    " + var/dat = "Showing last [lawchanges.len] law change\s.
    " for(var/sig in lawchanges) dat += "[sig]
    " usr << browse(dat, "window=lawchanges;size=800x500") diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 5c2068abdfe..90236d2e521 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -12,7 +12,7 @@ /mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg) laws_sanity_check() laws.set_zeroth_law(law, law_borg) - log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]") + log_law("has given [src] the zeroth law: '[law]'[law_borg ? " / '[law_borg]'" : ""]") /mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg) ..() @@ -22,40 +22,40 @@ /mob/living/silicon/proc/add_ion_law(var/law) laws_sanity_check() laws.add_ion_law(law) - log_and_message_admins("has given [src] the ion law: [law]") + log_law("has given [src] the ion law: [law]") /mob/living/silicon/proc/add_inherent_law(var/law) laws_sanity_check() laws.add_inherent_law(law) - log_and_message_admins("has given [src] the inherent law: [law]") + log_law("has given [src] the inherent law: [law]") /mob/living/silicon/proc/add_supplied_law(var/number, var/law) laws_sanity_check() laws.add_supplied_law(number, law) - log_and_message_admins("has given [src] the supplied law: [law]") + log_law("has given [src] the supplied law: [law]") /mob/living/silicon/proc/delete_law(var/datum/ai_law/law) laws_sanity_check() laws.delete_law(law) - log_and_message_admins("has deleted a law belonging to [src]: [law.law]") + log_law("has deleted a law belonging to [src]: [law.law]") /mob/living/silicon/proc/clear_inherent_laws(var/silent = 0) laws_sanity_check() laws.clear_inherent_laws() if(!silent) - log_and_message_admins("cleared the inherent laws of [src]") + log_law("cleared the inherent laws of [src]") /mob/living/silicon/proc/clear_ion_laws(var/silent = 0) laws_sanity_check() laws.clear_ion_laws() if(!silent) - log_and_message_admins("cleared the ion laws of [src]") + log_law("cleared the ion laws of [src]") /mob/living/silicon/proc/clear_supplied_laws(var/silent = 0) laws_sanity_check() laws.clear_supplied_laws() if(!silent) - log_and_message_admins("cleared the supplied laws of [src]") + log_law("cleared the supplied laws of [src]") /mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws) var/prefix = "" @@ -102,3 +102,7 @@ /mob/living/silicon/proc/lawsync() laws_sanity_check() laws.sort_laws() + +/mob/living/silicon/proc/log_law(var/law_message) + log_and_message_admins(law_message) + lawchanges += "[worldtime2text()] - [usr ? "[key_name(usr)]" : "EVENT"] [law_message]" From e5ef8d5485014e3ec8e22a071c25512aab942f6c Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 14 Oct 2015 08:22:28 +0200 Subject: [PATCH 059/207] Updates changelog. --- html/changelog.html | 13 ++++++++ html/changelogs/.all_changelog.yml | 8 +++++ html/changelogs/Hubblenaut-master.yml | 37 --------------------- html/changelogs/Hubblenaut-stacks.yml | 37 --------------------- html/changelogs/TheWelp-secRemoveMaster.yml | 6 ---- 5 files changed, 21 insertions(+), 80 deletions(-) delete mode 100644 html/changelogs/Hubblenaut-master.yml delete mode 100644 html/changelogs/Hubblenaut-stacks.yml delete mode 100644 html/changelogs/TheWelp-secRemoveMaster.yml diff --git a/html/changelog.html b/html/changelog.html index 64639f2244a..372d1d37624 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,19 @@ -->
    +

    14 October 2015

    +

    Hubblenaut updated:

    +
      +
    • Airlock backup power test light properly offline when backup power down.
    • +
    • Empty flavor texts no longer draw an empty line on examination.
    • +
    • Material stacks now properly merge upon creation.
    • +
    • Messages for adding to existing stack appear again.
    • +
    +

    TheWelp updated:

    +
      +
    • Removed higher Secret player requirements.
    • +
    +

    10 October 2015

    HarpyEagle updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 2db1c6ec288..4dc9f9dac63 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2024,3 +2024,11 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. than they were supposed to. - bugfix: Merc bombs are now appropriately explosive again. Same goes for bombs made by toxins. +2015-10-14: + Hubblenaut: + - bugfix: Airlock backup power test light properly offline when backup power down. + - bugfix: Empty flavor texts no longer draw an empty line on examination. + - bugfix: Material stacks now properly merge upon creation. + - bugfix: Messages for adding to existing stack appear again. + TheWelp: + - rscdel: Removed higher Secret player requirements. diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-master.yml deleted file mode 100644 index 783ec67eead..00000000000 --- a/html/changelogs/Hubblenaut-master.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Hubblenaut - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - bugfix: "Airlock backup power test light properly offline when backup power down." - - bugfix: "Empty flavor texts no longer draw an empty line on examination." diff --git a/html/changelogs/Hubblenaut-stacks.yml b/html/changelogs/Hubblenaut-stacks.yml deleted file mode 100644 index 10426fff707..00000000000 --- a/html/changelogs/Hubblenaut-stacks.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Hubblenaut - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - bugfix: "Material stacks now properly merge upon creation." - - bugfix: "Messages for adding to existing stack appear again." diff --git a/html/changelogs/TheWelp-secRemoveMaster.yml b/html/changelogs/TheWelp-secRemoveMaster.yml deleted file mode 100644 index bcf7c7a0294..00000000000 --- a/html/changelogs/TheWelp-secRemoveMaster.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: TheWelp - -delete-after: True - -changes: - - rscdel: "Removed Higher Secret Player Requirements" From 4db9677c883c75e9006e1d4404fa8b7cce3da045 Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 14 Oct 2015 14:25:12 -0400 Subject: [PATCH 060/207] Fixes pepperspray confusion Eye protection now prevents blindness, face protection prevents stun, instead of face protection doing both. --- .../Chemistry-Reagents-Food-Drinks.dm | 10 +++++----- .../changelogs/HarpyEagle-pepperspray-fix.yml | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 html/changelogs/HarpyEagle-pepperspray-fix.yml diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 0d04d8ad99b..9edd9193cb8 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -286,18 +286,18 @@ M << "Your [safe_thing] protects you from the pepperspray!" return else if(eyes_covered) - M << "Your [safe_thing] protect you from most of the pepperspray!" - M.eye_blurry = max(M.eye_blurry, 15) - M.eye_blind = max(M.eye_blind, 5) + M << "Your [safe_thing] protect your eyes from the pepperspray!" + M.eye_blurry = max(M.eye_blurry, 5) M.Stun(5) M.Weaken(5) return else if (mouth_covered) // Mouth cover is better than eye cover M << "Your [safe_thing] protects your face from the pepperspray!" - M.eye_blurry = max(M.eye_blurry, 5) + M.eye_blurry = max(M.eye_blurry, 15) + M.eye_blind = max(M.eye_blind, 5) return else // Oh dear :D - M << "You're sprayed directly in the eyes with pepperspray!" + M << "You're sprayed directly with the pepperspray!" M.eye_blurry = max(M.eye_blurry, 25) M.eye_blind = max(M.eye_blind, 10) M.Stun(5) diff --git a/html/changelogs/HarpyEagle-pepperspray-fix.yml b/html/changelogs/HarpyEagle-pepperspray-fix.yml new file mode 100644 index 00000000000..c474310d0f8 --- /dev/null +++ b/html/changelogs/HarpyEagle-pepperspray-fix.yml @@ -0,0 +1,20 @@ +################################ +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +author: HarpyEagle +delete-after: True +changes: + - bugfix: "When affected by pepperspray, eye protection now prevents blindness and face protection now prevents stun, instead of face protection doing both." \ No newline at end of file From ffb26a6f87f01d3418523fa7a965614b49eb28bb Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Mon, 12 Oct 2015 13:25:42 -0400 Subject: [PATCH 061/207] Adds checks for antags being dead or SSD --- code/game/antagonist/antagonist_helpers.dm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index 37e332d8efb..adc706734fd 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -21,7 +21,15 @@ return current_antagonists ? current_antagonists.len : 0 /datum/antagonist/proc/get_active_antag_count() - return get_antag_count() //TODO + var/active_antags = 0 + for(var/datum/mind/player in current_antagonists) + var/mob/living/L = player.current + if(!L || L.stat == DEAD) + continue //no mob or dead + if(!L.client && !L.teleop) + continue //SSD + active_antags++ + return active_antags /datum/antagonist/proc/is_antagonist(var/datum/mind/player) if(player in current_antagonists) From 27429f7b0ccebe64c8cf97d6754c18d7f926f52c Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 00:02:18 -0400 Subject: [PATCH 062/207] Less copypasta --- .../Chemistry-Reagents-Food-Drinks.dm | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 9edd9193cb8..3323e6e4158 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -219,6 +219,10 @@ description = "This is what makes chilis hot." reagent_state = LIQUID color = "#B31008" + var/agony_dose = 5 + var/agony_amount = 2 + var/discomfort_message = "Your insides feel uncomfortably hot!" + var/slime_temp_adj = 10 /datum/reagent/capsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) if(alien == IS_DIONA) @@ -232,30 +236,31 @@ var/mob/living/carbon/human/H = M if(H.species && (H.species.flags & (NO_PAIN | IS_SYNTHETIC))) return - if(dose < 5 && (dose == metabolism || prob(5))) - M << "Your insides feel uncomfortably hot!" - if(dose >= 5) - M.apply_effect(2, AGONY, 0) + if(dose < agony_dose) + if(prob(5) || dose == metabolism) //dose == metabolism is a very hacky way of forcing the message the first time this procs + M << initial_message + else + M.apply_effect(agony_amount, AGONY, 0) if(prob(5)) - M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!")]", "You feel like your insides are burning!") + M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!")]") + M << "You feel like your insides are burning!" if(istype(M, /mob/living/carbon/slime)) - M.bodytemperature += rand(10, 25) + M.bodytemperature += rand(0, 15) + slime_temp_adj holder.remove_reagent("frostoil", 5) -/datum/reagent/condensedcapsaicin +/datum/reagent/capsaicin/condensed name = "Condensed Capsaicin" id = "condensedcapsaicin" description = "A chemical agent used for self-defense and in police work." reagent_state = LIQUID touch_met = 50 // Get rid of it quickly color = "#B31008" + agony_dose = 0.5 + agony_amount = 4 + discomfort_message = "You feel like your insides are burning!" + slime_temp_adj = 15 -/datum/reagent/condensedcapsaicin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) - if(alien == IS_DIONA) - return - M.adjustToxLoss(0.5 * removed) - -/datum/reagent/condensedcapsaicin/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) +/datum/reagent/capsaicin/condensed/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) var/eyes_covered = 0 var/mouth_covered = 0 var/obj/item/safe_thing = null @@ -304,21 +309,6 @@ M.Weaken(5) return -/datum/reagent/condensedcapsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species && (H.species.flags & (NO_PAIN | IS_SYNTHETIC))) - return - if(dose == metabolism) - M << "You feel like your insides are burning!" - else - M.apply_effect(4, AGONY, 0) - if(prob(5)) - M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!")]", "You feel like your insides are burning!") - if(istype(M, /mob/living/carbon/slime)) - M.bodytemperature += rand(15, 30) - holder.remove_reagent("frostoil", 5) - /* Drinks */ /datum/reagent/drink From fd03e4d59b63d90c11ca586f89b34461fece75fa Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 15 Oct 2015 10:18:55 +0200 Subject: [PATCH 063/207] Surgical kits can now contain their equipment. The surgical kit can now contain the equipment it came with. It can also not contain more items of a given type than it was spawned with. This means that even if the storage container otherwise has sufficient space it can, for example, still only ever contain 1 surgical saw. Fixes #11298. Fixes #11297. --- code/__HELPERS/lists.dm | 16 +++++++--- .../objects/items/weapons/storage/firstaid.dm | 6 ++-- .../objects/items/weapons/storage/storage.dm | 31 ++++++++++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index ed0f0c97809..a6b010dbc93 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -71,11 +71,17 @@ proc/isemptylist(list/list) return 1 return 0 -//Empties the list by setting the length to 0. Hopefully the elements get garbage collected -proc/clearlist(list/list) - if(istype(list)) - list.len = 0 - return +/proc/instances_of_type_in_list(var/atom/A, var/list/L) + var/instances = 0 + for(var/type in L) + if(istype(A, type)) + instances++ + return instances + +//Empties the list by .Cut(). Setting lenght = 0 has been confirmed to leak references. +proc/clearlist(var/list/L) + if(islist(L)) + L.Cut() //Removes any null entries from the list proc/listclearnulls(list/list) diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index c23dfcdb516..a76fb4f1a1f 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -130,8 +130,7 @@ /obj/item/weapon/storage/firstaid/surgery name = "surgery kit" - desc = "Contains tools for surgery." - storage_slots = 10 + desc = "Contains tools for surgery. Has precise foam fitting for safe transport." /obj/item/weapon/storage/firstaid/surgery/New() ..() @@ -146,7 +145,8 @@ new /obj/item/weapon/bonegel(src) new /obj/item/weapon/FixOVein(src) new /obj/item/stack/medical/advanced/bruise_pack(src) - return + + make_exact_fit() /* * Pill Bottles diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 22277c33e2a..6f2ba544ab7 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -51,10 +51,10 @@ //there's got to be a better way of doing this. if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) return - + if (( usr.restrained() ) || ( usr.stat )) return - + if ((src.loc == usr) && !usr.unEquip(src)) return @@ -232,12 +232,16 @@ usr << "[src] is full, make some space." return 0 //Storage item is full - if(can_hold.len && !is_type_in_list(W, can_hold)) - if(!stop_messages) - if (istype(W, /obj/item/weapon/hand_labeler)) - return 0 - usr << "[src] cannot hold [W]." - return 0 + if(can_hold.len) + if(!is_type_in_list(W, can_hold)) + if(!stop_messages && ! istype(W, /obj/item/weapon/hand_labeler)) + usr << "[src] cannot hold [W]." + return 0 + var/max_instances = can_hold[W.type] + if(max_instances && instances_of_type_in_list(W, contents) >= max_instances) + if(!stop_messages && !istype(W, /obj/item/weapon/hand_labeler)) + usr << "[src] has no more space for an additional [W]." + return 0 if(cant_hold.len && is_type_in_list(W, cant_hold)) if(!stop_messages) @@ -449,6 +453,17 @@ var/obj/O = A O.hear_talk(M, text, verb, speaking) +/obj/item/weapon/storage/proc/make_exact_fit() + storage_slots = contents.len + + can_hold.Cut() + max_w_class = 0 + max_storage_space = 0 + for(var/obj/item/I in src) + max_w_class = max(I.w_class, max_w_class) + max_storage_space += I.get_storage_cost() + can_hold[I.type] = ++can_hold[I.type] + //Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). //Returns -1 if the atom was not found on container. /atom/proc/storage_depth(atom/container) From e79e82f55d54e4b5a41272718ecf27b43275af67 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 15 Oct 2015 10:32:56 +0200 Subject: [PATCH 064/207] Gives replacement light boxes the same fitness treatment. --- code/game/objects/items/weapons/storage/boxes.dm | 13 +++++++------ code/game/objects/items/weapons/storage/storage.dm | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index d28107dd8f3..aa3fe35f9b6 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -598,32 +598,33 @@ icon_state = "light" desc = "This box is shaped on the inside so that only light tubes and bulbs fit." item_state = "syringe_kit" - storage_slots=21 - can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb) - max_storage_space = 42 //holds 21 items of w_class 2 use_to_pickup = 1 // for picking up broken bulbs, not that most people will try + +/obj/item/weapon/storage/box/lights/New() + ..() + make_exact_fit() /obj/item/weapon/storage/box/lights/bulbs/New() - ..() for(var/i = 0; i < 21; i++) new /obj/item/weapon/light/bulb(src) + ..() /obj/item/weapon/storage/box/lights/tubes name = "box of replacement tubes" icon_state = "lighttube" /obj/item/weapon/storage/box/lights/tubes/New() - ..() for(var/i = 0; i < 21; i++) new /obj/item/weapon/light/tube(src) + ..() /obj/item/weapon/storage/box/lights/mixed name = "box of replacement lights" icon_state = "lightmixed" /obj/item/weapon/storage/box/lights/mixed/New() - ..() for(var/i = 0; i < 14; i++) new /obj/item/weapon/light/tube(src) for(var/i = 0; i < 7; i++) new /obj/item/weapon/light/bulb(src) + ..() diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 6f2ba544ab7..9f5fe9ea7c7 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -235,12 +235,12 @@ if(can_hold.len) if(!is_type_in_list(W, can_hold)) if(!stop_messages && ! istype(W, /obj/item/weapon/hand_labeler)) - usr << "[src] cannot hold [W]." + usr << "[src] cannot hold \the [W]." return 0 var/max_instances = can_hold[W.type] if(max_instances && instances_of_type_in_list(W, contents) >= max_instances) if(!stop_messages && !istype(W, /obj/item/weapon/hand_labeler)) - usr << "[src] has no more space for an additional [W]." + usr << "[src] has no more space specifically for \the [W]." return 0 if(cant_hold.len && is_type_in_list(W, cant_hold)) @@ -460,9 +460,9 @@ max_w_class = 0 max_storage_space = 0 for(var/obj/item/I in src) + can_hold[I.type]++ max_w_class = max(I.w_class, max_w_class) max_storage_space += I.get_storage_cost() - can_hold[I.type] = ++can_hold[I.type] //Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). //Returns -1 if the atom was not found on container. From 2fcaaf80c7155f0dc0ca8b0716a98f0861dfbe33 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 15 Oct 2015 11:31:57 +0200 Subject: [PATCH 065/207] Chemistry machinery fixes. Makes Topic() calls check parent. Adds proper operable() checks where applicable. Makes the interact_offline only affect the NOPOWER flag. Fixes #11116. Fixes #11302. --- code/game/machinery/machinery.dm | 5 +++- code/modules/reagents/Chemistry-Machinery.dm | 28 ++++++++----------- code/modules/reagents/dispenser/dispenser2.dm | 11 ++------ 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 62909fc3daf..97d92903c01 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -195,7 +195,10 @@ Class Procs: return (stat & (NOPOWER|BROKEN|additional_flags)) /obj/machinery/CanUseTopic(var/mob/user) - if(!interact_offline && (stat & (NOPOWER|BROKEN))) + if(stat & BROKEN) + return STATUS_CLOSE + + if(!interact_offline && (stat & NOPOWER)) return STATUS_CLOSE return ..() diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index c010acd4bb3..726303273aa 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -80,13 +80,8 @@ return /obj/machinery/chem_master/Topic(href, href_list) - if(stat & (BROKEN|NOPOWER)) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - src.add_fingerprint(usr) - usr.set_machine(src) - + if(..()) + return 1 if (href_list["ejectp"]) if(loaded_pill_bottle) @@ -236,7 +231,7 @@ return src.attack_hand(user) /obj/machinery/chem_master/attack_hand(mob/user as mob) - if(stat & BROKEN) + if(inoperable()) return user.set_machine(src) if(!(user.client in has_sprites)) @@ -345,11 +340,8 @@ /obj/machinery/computer/pandemic/Topic(href, href_list) - if(stat & (NOPOWER|BROKEN)) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - usr.set_machine(src) + if(..()) + return 1 if(!beaker) return if (href_list["create_vaccine"]) @@ -657,10 +649,12 @@ return 0 /obj/machinery/reagentgrinder/attack_hand(mob/user as mob) - user.set_machine(src) interact(user) /obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu + if(inoperable()) + return + user.set_machine(src) var/is_chamber_empty = 0 var/is_beaker_ready = 0 var/processing_chamber = "" @@ -707,8 +701,8 @@ /obj/machinery/reagentgrinder/Topic(href, href_list) if(..()) - return - usr.set_machine(src) + return 1 + switch(href_list["action"]) if ("grind") grind() @@ -717,7 +711,7 @@ if ("detach") detach() src.updateUsrDialog() - return + return 1 /obj/machinery/reagentgrinder/proc/detach() diff --git a/code/modules/reagents/dispenser/dispenser2.dm b/code/modules/reagents/dispenser/dispenser2.dm index 8decba10d49..df63f5c8a78 100644 --- a/code/modules/reagents/dispenser/dispenser2.dm +++ b/code/modules/reagents/dispenser/dispenser2.dm @@ -113,9 +113,6 @@ return ..() /obj/machinery/chemical_dispenser/ui_interact(mob/user, ui_key = "main",var/datum/nanoui/ui = null, var/force_open = 1) - if(stat & (BROKEN|NOPOWER)) return - if(user.stat || user.restrained()) return - // this is the data which will be sent to the ui var/data[0] data["amount"] = amount @@ -148,8 +145,8 @@ ui.open() /obj/machinery/chemical_dispenser/Topic(href, href_list) - if(stat & (NOPOWER|BROKEN)) - return 0 // don't update UIs attached to this object + if(..()) + return 1 if(href_list["amount"]) amount = round(text2num(href_list["amount"]), 1) // round to nearest 1 @@ -171,9 +168,7 @@ return 1 // update UIs attached to this object /obj/machinery/chemical_dispenser/attack_ai(mob/user as mob) - src.attack_hand(user) + ui_interact(user) /obj/machinery/chemical_dispenser/attack_hand(mob/user as mob) - if(stat & BROKEN) - return ui_interact(user) From dcde34512cb7c3941ff8a1267aafdb07507a1301 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 00:25:31 -0400 Subject: [PATCH 066/207] Refactors pepperspray touch effect, adjusts pepperspray messages. --- .../Chemistry-Reagents-Food-Drinks.dm | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 3323e6e4158..43639afea11 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -238,11 +238,11 @@ return if(dose < agony_dose) if(prob(5) || dose == metabolism) //dose == metabolism is a very hacky way of forcing the message the first time this procs - M << initial_message + M << discomfort_message else M.apply_effect(agony_amount, AGONY, 0) if(prob(5)) - M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!")]") + M.custom_emote(2, "[pick("dry heaves!","coughs!","splutters!")]") M << "You feel like your insides are burning!" if(istype(M, /mob/living/carbon/slime)) M.bodytemperature += rand(0, 15) + slime_temp_adj @@ -263,51 +263,51 @@ /datum/reagent/capsaicin/condensed/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) var/eyes_covered = 0 var/mouth_covered = 0 - var/obj/item/safe_thing = null + var/no_pain = 0 + var/obj/item/eye_protection = null + var/obj/item/face_protection = null + + var/list/protection if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M + protection = list(H.head, H.glasses, H.wear_mask) if(H.species && (H.species.flags & NO_PAIN)) - return - if(H.head) - if(H.head.flags & MASKCOVERSEYES) + no_pain = 1 //TODO: living-level can_feel_pain() proc + else + protection = list(M.wear_mask) + + for(var/obj/item/I in protection) + if(I) + if(I.flags & MASKCOVERSEYES) eyes_covered = 1 - safe_thing = H.head - if(H.head.flags & MASKCOVERSMOUTH) + eye_protection = I + if(I.flags & MASKCOVERSMOUTH) mouth_covered = 1 - safe_thing = H.head - if(H.wear_mask) - if(!eyes_covered && H.wear_mask.flags & MASKCOVERSEYES) - eyes_covered = 1 - safe_thing = H.wear_mask - if(!mouth_covered && H.wear_mask.flags & MASKCOVERSMOUTH) - mouth_covered = 1 - safe_thing = H.wear_mask - if(H.glasses) - if(!eyes_covered) - eyes_covered = 1 - if(!safe_thing) - safe_thing = H.glasses - if(eyes_covered && mouth_covered) - M << "Your [safe_thing] protects you from the pepperspray!" - return - else if(eyes_covered) - M << "Your [safe_thing] protect your eyes from the pepperspray!" - M.eye_blurry = max(M.eye_blurry, 5) + face_protection = I + + var/message = null + if(eyes_covered) + message = "Your [eye_protection] protects your eyes from the pepperspray!" + else + message = "The pepperspray gets in your eyes!" + if(mouth_covered) + M.eye_blurry = max(M.eye_blurry, 15) + M.eye_blind = max(M.eye_blind, 5) + else + M.eye_blurry = max(M.eye_blurry, 25) + M.eye_blind = max(M.eye_blind, 10) + + if(mouth_covered) + if(!message) + message = "Your [face_protection] protects you from the pepperspray!" + else if(!no_pain) + message = "Your face and throat burn!" + if(prob(25)) + M.custom_emote(2, "[pick("coughs!","coughs hysterically!","splutters!")]") M.Stun(5) M.Weaken(5) - return - else if (mouth_covered) // Mouth cover is better than eye cover - M << "Your [safe_thing] protects your face from the pepperspray!" - M.eye_blurry = max(M.eye_blurry, 15) - M.eye_blind = max(M.eye_blind, 5) - return - else // Oh dear :D - M << "You're sprayed directly with the pepperspray!" - M.eye_blurry = max(M.eye_blurry, 25) - M.eye_blind = max(M.eye_blind, 10) - M.Stun(5) - M.Weaken(5) - return + + M << message /* Drinks */ From d260b3bb18bf15fdd688f90631f3808923515511 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 01:36:34 -0400 Subject: [PATCH 067/207] Fixes #11300 Atoms crossing a smoke cloud now get splashed with up to 10 units of reagent. --- code/game/objects/effects/chem/chemsmoke.dm | 29 ++++++++++++++++--- .../Chemistry-Reagents-Food-Drinks.dm | 7 +++-- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index 3fa93e7e467..d8e589027f9 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -6,11 +6,32 @@ opacity = 0 time_to_live = 300 pass_flags = PASSTABLE | PASSGRILLE | PASSGLASS //PASSGLASS is fine here, it's just so the visual effect can "flow" around glass + var/splash_amount = 10 //atoms moving through a smoke cloud get splashed with up to 10 units of reagent + var/turf/destination -/obj/effect/effect/smoke/chem/New() +/obj/effect/effect/smoke/chem/New(var/newloc, turf/dest = null) ..() create_reagents(500) - return + destination = dest + if(destination) + walk_to(src, destination) + +/obj/effect/effect/smoke/chem/Move() + var/list/oldlocs = view(1, src) + . = ..() + if(.) + for(var/turf/T in view(1, src) - oldlocs) + for(var/atom/movable/AM in T) + if(!istype(AM, /obj/effect/effect/smoke/chem)) + reagents.splash(AM, splash_amount, copy = 1) + if(loc == destination) + bound_width = 96 + bound_height = 96 + +/obj/effect/effect/smoke/chem/Crossed(atom/movable/AM) + ..() + if(!istype(AM, /obj/effect/effect/smoke/chem)) + reagents.splash(AM, splash_amount, copy = 1) /datum/effect/effect/system/smoke_spread/chem smoke_type = /obj/effect/effect/smoke/chem @@ -152,16 +173,16 @@ if(passed_smoke) smoke = passed_smoke else - smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location) + smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, T)) if(chemholder.reagents.reagent_list.len) chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents + smoke.icon = I smoke.layer = 6 smoke.set_dir(pick(cardinal)) smoke.pixel_x = -32 + rand(-8, 8) smoke.pixel_y = -32 + rand(-8, 8) - walk_to(smoke, T) smoke.opacity = 1 //switching opacity on after the smoke has spawned, and then sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner smoke.opacity = 0 // lighting and view range updates diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 43639afea11..62808ba4546 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -280,14 +280,15 @@ if(I) if(I.flags & MASKCOVERSEYES) eyes_covered = 1 - eye_protection = I + eye_protection = I.name if(I.flags & MASKCOVERSMOUTH) mouth_covered = 1 - face_protection = I + face_protection = I.name var/message = null if(eyes_covered) - message = "Your [eye_protection] protects your eyes from the pepperspray!" + if(!mouth_covered) + message = "Your [eye_protection] protects your eyes from the pepperspray!" else message = "The pepperspray gets in your eyes!" if(mouth_covered) From 41e87985161fd5279d77c99ac342b1fb368ae2de Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 01:40:39 -0400 Subject: [PATCH 068/207] Adjusts chemsmoke breathing Inhaled reagents are now split between bloodstream and ingestion. Reagents are not inhaled if environment pressure is too low. --- code/modules/mob/living/carbon/breathe.dm | 6 ++++-- code/modules/mob/living/carbon/human/life.dm | 2 +- code/modules/mob/living/carbon/human/species/species.dm | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index 2746e0c82e9..66cdd2f75e5 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -60,13 +60,15 @@ //Handle possble chem smoke effect /mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment) + if(species && environment.return_pressure() < species.breath_pressure/5) + return //pressure is too low to even breathe in. if(wear_mask && (wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)) return for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) if(smoke.reagents.total_volume) - smoke.reagents.trans_to_mob(src, 10, CHEM_INGEST, copy = 1) - //maybe check air pressure here or something to see if breathing in smoke is even possible. + smoke.reagents.trans_to_mob(src, 5, CHEM_INGEST, copy = 1) + smoke.reagents.trans_to_mob(src, 5, CHEM_BLOOD, copy = 1) // 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 diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index cbec800efd5..baae688eb08 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -391,7 +391,7 @@ return 0 - var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa + var/safe_pressure_min = species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa // Lung damage increases the minimum safe pressure. if(species.has_organ["lungs"]) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 313fa2e1c77..4169f6177d6 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -60,6 +60,7 @@ // Environment tolerance/life processes vars. var/reagent_tag //Used for metabolizing reagents. + var/breath_pressure = 16 // Minimum partial pressure safe for breathing, kPa var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. var/poison_type = "phoron" // Poisonous air. var/exhale_type = "carbon_dioxide" // Exhaled gas type. From 27fe99bdf07f2a80896c33bfc0f94927480af2db Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 06:36:50 -0400 Subject: [PATCH 069/207] Reagent transfer now checks simulated var --- code/modules/reagents/Chemistry-Holder.dm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 8a7e34ccb9b..d077c5f3aa1 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -311,7 +311,7 @@ trans_to(target, amount, multiplier, copy) /datum/reagents/proc/trans_id_to(var/atom/target, var/id, var/amount = 1) - if (!target || !target.reagents) + if (!target || !target.reagents || !target.simulated) return amount = min(amount, get_reagent_amount(id)) @@ -340,7 +340,7 @@ return /datum/reagents/proc/touch_mob(var/mob/target) - if(!target || !istype(target)) + if(!target || !istype(target) || !target.simulated) return for(var/datum/reagent/current in reagent_list) @@ -349,7 +349,7 @@ update_total() /datum/reagents/proc/touch_turf(var/turf/target) - if(!target || !istype(target)) + if(!target || !istype(target) || !target.simulated) return for(var/datum/reagent/current in reagent_list) @@ -358,7 +358,7 @@ update_total() /datum/reagents/proc/touch_obj(var/obj/target) - if(!target || !istype(target)) + if(!target || !istype(target) || !target.simulated) return for(var/datum/reagent/current in reagent_list) @@ -377,7 +377,7 @@ return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy) /datum/reagents/proc/trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder... - if(!target || !istype(target)) + if(!target || !istype(target) || !target.simulated) return if(iscarbon(target)) var/mob/living/carbon/C = target @@ -396,7 +396,7 @@ R.touch_mob(target) /datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it. - if(!target) + if(!target || !target.simulated) return var/datum/reagents/R = new /datum/reagents(amount * multiplier) @@ -405,7 +405,7 @@ return /datum/reagents/proc/trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch. - if(!target) + if(!target || !target.simulated) return if(!target.reagents) From 7272deb5ae3c43b1eb3fcb1f05340985727df7d0 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 06:57:23 -0400 Subject: [PATCH 070/207] Fixes #11216 Sunglass-derived custom gear is now only available to roles that normally have access to them. --- code/modules/client/preferences_gear.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/client/preferences_gear.dm b/code/modules/client/preferences_gear.dm index 5be7e2dcde7..9cc57be5365 100644 --- a/code/modules/client/preferences_gear.dm +++ b/code/modules/client/preferences_gear.dm @@ -297,17 +297,18 @@ var/global/list/gear_datums = list() allowed_roles = list("Security Officer","Head of Security","Warden") /datum/gear/thugshades - display_name = "Sunglasses, Fat (Security)" + display_name = "Sunglasses, Fat" path = /obj/item/clothing/glasses/sunglasses/big cost = 1 slot = slot_glasses - allowed_roles = list("Security Officer","Head of Security","Warden") + allowed_roles = list("Security Officer","Head of Security","Warden","Detective","Internal Affairs Agent","Quartermaster","Head of Personnel","Captain") /datum/gear/prescriptionsun display_name = "sunglasses, presciption" path = /obj/item/clothing/glasses/sunglasses/prescription cost = 2 slot = slot_glasses + allowed_roles = list("Security Officer","Head of Security","Warden","Detective","Internal Affairs Agent","Quartermaster","Head of Personnel","Captain") // Mask From e8d6772523ddd190abe4c73837aefc59cd992db2 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 15 Oct 2015 16:53:06 -0400 Subject: [PATCH 071/207] Smoke clouds dissipate faster in low pressure --- code/game/objects/effects/chem/chemsmoke.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index d8e589027f9..293992b7354 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -10,6 +10,14 @@ var/turf/destination /obj/effect/effect/smoke/chem/New(var/newloc, turf/dest = null) + + //Calculate time to live + var/pressure = 0 + var/datum/gas_mixture/environment = loc.return_air() + if(environment) pressure = environment.return_pressure() + + time_to_live = max(5, time_to_live*min(pressure/(ONE_ATMOSPHERE/3), 1)) + ..() create_reagents(500) destination = dest From 111973ed5c622c4c1c7e24c9cf97bf43f60caa3f Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Thu, 15 Oct 2015 19:05:31 -0400 Subject: [PATCH 072/207] AI's can now use languages through holopads... ...and have it respect if the listener understands. Resolves #11113 (AI's speech not timestamped through holopad) Resolves #11183 (All languages can be understood when AI speaks them through a holopad.) Resolves #6217 (pAIs cannot hear AI hologram speech) --- code/modules/mob/living/silicon/say.dm | 57 ++++++++++++++++---------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index ece00da5ee7..16a00368a80 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -68,31 +68,46 @@ if (!message) return - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.masters[src])//If there is a hologram and its master is the user. - - //Human-like, sorta, heard by those who understand humans. - var/rendered_a - //Speach distorted, heard by those who do not understand AIs. - var/message_stars = stars(message) - var/rendered_b + var/obj/machinery/hologram/holopad/H = src.holo + if(H && H.masters[src])//If there is a hologram and its master is the user. + // AI can hear their own message, this formats it for them. if(speaking) - rendered_a = "[name] [speaking.format_message(message, verb)]" - rendered_b = "[voice_name] [speaking.format_message(message_stars, verb)]" - src << "Holopad transmitted, [real_name] [speaking.format_message(message, verb)]"//The AI can "hear" its own message. + src << "Holopad transmitted, [real_name] [speaking.format_message(message, verb)]" else - rendered_a = "[name] [verb], \"[message]\"" - rendered_b = "[voice_name] [verb], \"[message_stars]\"" - src << "Holopad transmitted, [real_name] [verb], \"[message]\""//The AI can "hear" its own message. + src << "Holopad transmitted, [real_name] [verb], \"[message]\"" + + //This is so pAI's and people inside lockers/boxes,etc can hear the AI Holopad, the alternative being recursion through contents. + //This is much faster. + var/list/listening = list() + var/list/listening_obj = list() + var/turf/T = get_turf(H) + + if(T) + var/list/hear = hear(7, T) + var/list/hearturfs = list() + + for(var/I in hear) + if(istype(I, /mob/)) + var/mob/M = I + listening += M + hearturfs += M.locs[1] + for(var/obj/O in M.contents) + listening_obj |= O + else if(istype(I, /obj/)) + var/obj/O = I + hearturfs += O.locs[1] + listening_obj |= O + + + for(var/mob/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS)) + M.hear_say(message,verb,speaking,null,null, src) + continue + if(M.loc && M.locs[1] in hearturfs) + M.hear_say(message,verb,speaking,null,null, src) + - for(var/mob/M in hearers(T.loc))//The location is the object, default distance. - if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to. - M.show_message(rendered_a, 2) - else//If they do not. - M.show_message(rendered_b, 2) - /*Radios "filter out" this conversation channel so we don't need to account for them. - This is another way of saying that we won't bother dealing with them.*/ else src << "No holopad connected." return 0 From bb93245ccda71ef77001f7b5ca9a7530b9c7213d Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Thu, 15 Oct 2015 21:08:14 -0400 Subject: [PATCH 073/207] Fixes the tapping messages check. The check is now in Topic() instead of being based on the href link sent. Resolves #11039 --- code/game/objects/items/devices/PDA/PDA.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 25f2b407cea..35ab855f053 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -721,7 +721,8 @@ var/global/list/obj/item/device/pda/PDAs = list() if("Message") var/obj/item/device/pda/P = locate(href_list["target"]) - src.create_message(U, P, !href_list["notap"]) + var/tap = istype(U, /mob/living/carbon) + src.create_message(U, P, tap) if(mode == 2) if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp. active_conversation = href_list["target"] @@ -1040,7 +1041,7 @@ var/global/list/obj/item/device/pda/PDAs = list() new_message(sending_device, sending_device.owner, sending_device.ownjob, message) /obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message) - var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply)" + var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply)" new_info(message_silent, ttone, reception_message) log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]") @@ -1052,7 +1053,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(ismob(sending_unit.loc) && isAI(loc)) track = "(Follow)" - var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]" + var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]" new_info(message_silent, newstone, reception_message) log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]") From a70ec21e64beadccc8527b8d9afb24a23ccb73f1 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 16 Oct 2015 14:17:47 +0200 Subject: [PATCH 074/207] Fixes #11276 - Re-adjusts two values to take new lighting in account. - For reference. Turf which has light fixture (large) on it, has light value of 6. An average half-lit turf has around 1.5. These values were obtained via in-game tests. - Using old values, diona would die (without another light source such as flashlight) when standing on any other turf other than turf with light fixture. - Now it should be relatively similar to the old values before lighting changes. --- code/modules/mob/living/carbon/human/life.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index cbec800efd5..031a69dddb5 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -890,9 +890,9 @@ var/turf/T = loc var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T if(L) - light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights + light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 2 //hardcapped so it's not abused by having a ton of flashlights else - light_amount = 5 + light_amount = 1 nutrition += light_amount traumatic_shock -= light_amount From c3e161117823e6031d9c5959639dc5e9341aa338 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 16 Oct 2015 14:38:20 +0200 Subject: [PATCH 075/207] Fixes #11149 - Corrects APC behavior when hacked by malfunctioning AI. - It should now be possible to hack the APC to unlock it even when it is hacked by the AI. Normal IDs still don't work on hacked APCs. - A little side-fix, removal of malfunctioning AI's hack of an APC should now work correctly. --- code/modules/power/apc.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 6a3fd1da71c..ba2bf2a7e7c 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -627,6 +627,7 @@ // Malf AI, removes the APC from AI's hacked APCs list. if(hacker && hacker.hacked_apcs && src in hacker.hacked_apcs) hacker.hacked_apcs -= src + hacker = null if (opened==2) opened = 1 update_icon() @@ -862,7 +863,7 @@ user << "\The [src] have AI control disabled!" return 0 else - if ((!in_range(src, user) || !istype(src.loc, /turf) || hacker)) // AI-hacked APCs cannot be controlled by other AIs, unlinked cyborgs or humans. + if (!in_range(src, user) || !istype(src.loc, /turf)) return 0 var/mob/living/carbon/human/H = user if (istype(H)) From cbcddcad53b9bb62acdc74a3a2edb3d006b65de7 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 16 Oct 2015 14:44:01 +0200 Subject: [PATCH 076/207] Adjustment according to PsiOmegaDelta's suggestion --- code/modules/power/apc.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index ba2bf2a7e7c..a1811e496c4 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -625,7 +625,7 @@ qdel(W) stat &= ~BROKEN // Malf AI, removes the APC from AI's hacked APCs list. - if(hacker && hacker.hacked_apcs && src in hacker.hacked_apcs) + if(hacker && hacker.hacked_apcs && (src in hacker.hacked_apcs)) hacker.hacked_apcs -= src hacker = null if (opened==2) From 6107db1ba4f98d635b017c72947b364e4d3b0b9f Mon Sep 17 00:00:00 2001 From: Daranz Date: Fri, 16 Oct 2015 12:31:39 -0400 Subject: [PATCH 077/207] Fix missing quote marks in HTML lines. --- code/game/machinery/wall_frames.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/wall_frames.dm b/code/game/machinery/wall_frames.dm index b7f98667dce..c9182586c8c 100644 --- a/code/game/machinery/wall_frames.dm +++ b/code/game/machinery/wall_frames.dm @@ -35,14 +35,14 @@ var/turf/loc = get_turf(usr) var/area/A = loc.loc if (!istype(loc, /turf/simulated/floor)) - usr << "\The [src] Alarm cannot be placed on this spot." return if (A.requires_power == 0 || A.name == "Space") - usr << "\The [src] Alarm cannot be placed in this area." return if(gotwallitem(loc, ndir)) - usr << "" + usr << "There's already an item on this wall!" return var/obj/machinery/M = new build_machine_type(loc, ndir, 1) From 03447fb6091cf7752eaa1c5ff9bc74e754e4cf3e Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 17 Oct 2015 16:01:49 +0200 Subject: [PATCH 078/207] Malf announcement type change. Malf announcements are now command instead of priority announcements. This will make them be logged by newscasters. Fixes #11325. --- .../malfunction/newmalf_ability_trees/tree_networking.dm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm index 4a163884c48..9b4871bbae9 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm @@ -85,7 +85,7 @@ /datum/game_mode/malfunction/verb/advanced_encryption_hack() set category = "Software" - set name = "Advanced Encrypthion Hack" + set name = "Advanced Encryption Hack" set desc = "75 CPU - Attempts to bypass encryption on Central Command Quantum Relay, giving you ability to fake centcom messages. Has chance of failing." var/price = 75 var/mob/living/silicon/ai/user = usr @@ -106,15 +106,12 @@ announce_hack_failure(user, "quantum message relay") return - var/datum/announcement/priority/command/AN = new/datum/announcement/priority/command() - AN.title = title - AN.Announce(text) - + command_announcement.Announce(text, title) /datum/game_mode/malfunction/verb/elite_encryption_hack() set category = "Software" set name = "Elite Encryption Hack" - set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failijng." + set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failing." var/price = 200 var/mob/living/silicon/ai/user = usr if(!ability_prechecks(user, price)) From 7641ff5100382c6e3a565981595a68f3474e59ec Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Fri, 16 Oct 2015 11:03:04 +0200 Subject: [PATCH 079/207] Secures the AI and Cyborg upload console circuits in the ERT staging area. --- maps/exodus-2.dmm | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/maps/exodus-2.dmm b/maps/exodus-2.dmm index 0ad7c5cb128..a1729c1e029 100644 --- a/maps/exodus-2.dmm +++ b/maps/exodus-2.dmm @@ -1086,7 +1086,7 @@ "uT" = (/obj/machinery/door/window/northleft,/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/centcom/control) "uU" = (/obj/effect/landmark{name = "Marauder Exit"},/turf/unsimulated/floor{name = "plating"},/area/centcom/specops) "uV" = (/turf/unsimulated/floor{name = "plating"},/area/centcom/specops) -"uW" = (/obj/machinery/door/blast/regular{icon_state = "pdoor1"; id = "CREED"; name = "Ready Room"; p_open = 0},/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) +"uW" = (/obj/machinery/door/blast/regular{id = "ert_synth_equipment"; name = "Synthetics Modification Equipment"},/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) "uX" = (/turf/unsimulated/floor{icon_state = "warnplate"; dir = 8},/area/centcom/specops) "uY" = (/turf/unsimulated/floor{icon_state = "warnplate"; dir = 4},/area/centcom/specops) "uZ" = (/obj/machinery/mass_driver{dir = 8; id = "ASSAULT3"; name = "gravpult"},/turf/unsimulated/floor{icon_state = "bot"},/area/centcom/specops) @@ -1128,7 +1128,7 @@ "vJ" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/turf/unsimulated/floor{name = "plating"},/area/centcom/control) "vK" = (/obj/machinery/vending/tool,/turf/unsimulated/floor{icon_state = "vault"; dir = 1},/area/centcom/specops) "vL" = (/obj/structure/sign/poster{poster_type = "/datum/poster/bay_50"; pixel_x = -32},/turf/simulated/shuttle/floor{icon_state = "floor6"},/area/syndicate_station/start) -"vM" = (/obj/structure/table/woodentable{dir = 10},/obj/machinery/button/remote/blast_door{id = "CREED"; name = "Spec Ops Ready Room"; pixel_y = 4; req_access = list(108)},/obj/machinery/button/remote/blast_door{icon_state = "doorctrl0"; id = "ASSAULT"; name = "Mech Storage"; pixel_y = -4; req_access = list(108)},/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/creed) +"vM" = (/obj/item/weapon/aiModule/nanotrasen,/obj/item/weapon/aiModule/reset,/obj/item/weapon/aiModule/freeformcore,/obj/item/weapon/aiModule/protectStation,/obj/item/weapon/aiModule/quarantine,/obj/item/weapon/aiModule/paladin,/obj/item/weapon/aiModule/robocop,/obj/item/weapon/aiModule/safeguard,/obj/structure/table/rack,/turf/unsimulated/floor{icon_state = "vault"; dir = 1},/area/centcom/specops) "vN" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/blast/regular{id = "skipjackshutters"; name = "Skipjack Blast Shielding"},/turf/simulated/shuttle/plating,/area/skipjack_station/start) "vO" = (/obj/machinery/door/airlock/centcom{name = "Maintenance Access"; opacity = 1; req_access = list(106)},/turf/unsimulated/floor{icon_state = "dark"},/area/centcom/control) "vP" = (/obj/mecha/combat/gygax/dark,/obj/machinery/camera/network/ert{c_tag = "Assault Armor North"},/turf/unsimulated/floor{icon_state = "delivery"; dir = 6},/area/centcom/specops) @@ -1166,7 +1166,7 @@ "wv" = (/obj/structure/window/reinforced{dir = 4},/turf/unsimulated/floor{icon_state = "floor"},/area/centcom/control) "ww" = (/obj/structure/bed/chair{dir = 1},/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/centcom/control) "wx" = (/obj/mecha/working/ripley/firefighter,/turf/unsimulated/floor{icon_state = "delivery"; dir = 6},/area/centcom/specops) -"wy" = (/obj/item/weapon/circuitboard/aiupload,/obj/item/weapon/circuitboard/borgupload,/obj/item/weapon/circuitboard/smes,/obj/item/weapon/aiModule/nanotrasen,/obj/item/weapon/aiModule/reset,/obj/item/weapon/aiModule/freeformcore,/obj/item/weapon/aiModule/protectStation,/obj/item/weapon/aiModule/quarantine,/obj/item/weapon/aiModule/paladin,/obj/item/weapon/aiModule/robocop,/obj/item/weapon/aiModule/safeguard,/obj/structure/table/steel_reinforced,/turf/unsimulated/floor{icon_state = "vault"; dir = 1},/area/centcom/specops) +"wy" = (/obj/machinery/portable_atmospherics/canister/air,/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) "wz" = (/obj/machinery/door/airlock/centcom{name = "Maintenance Access"; opacity = 1; req_access = list(106)},/turf/unsimulated/floor{icon_state = "delivery"},/area/centcom/control) "wA" = (/obj/structure/sign/securearea,/turf/unsimulated/wall,/area/centcom/control) "wB" = (/obj/machinery/door/airlock/centcom{name = "Teleporter Bay"; opacity = 1; req_access = list(107)},/turf/unsimulated/floor{icon_state = "delivery"},/area/centcom/control) @@ -1940,9 +1940,13 @@ "Lp" = (/obj/item/pizzabox/meat,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/skipjack_station/start) "Lq" = (/obj/structure/bed,/obj/item/weapon/bedsheet/rd,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/skipjack_station/start) "Lr" = (/obj/structure/bed,/obj/item/weapon/bedsheet/clown,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/skipjack_station/start) +"Ls" = (/obj/structure/table/rack,/obj/item/weapon/circuitboard/borgupload,/obj/item/weapon/circuitboard/aiupload{pixel_x = -3; pixel_y = -3},/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) +"Lt" = (/obj/structure/table/woodentable{dir = 10},/obj/machinery/button/remote/blast_door{id = "CREED"; name = "Spec Ops Ready Room"; pixel_x = -5; pixel_y = 4; req_access = list(108)},/obj/machinery/button/remote/blast_door{icon_state = "doorctrl0"; id = "ASSAULT"; name = "Mech Storage"; pixel_x = -5; pixel_y = -4; req_access = list(108)},/obj/machinery/button/remote/blast_door{id = "ert_synth_equipment"; name = "Synth Modification Equipment"; pixel_x = 5; pixel_y = -4; req_access = list(108)},/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/creed) "Lu" = (/turf/unsimulated/floor{tag = "icon-ironsand7"; icon_state = "ironsand7"},/turf/unsimulated/floor{tag = "icon-asteroid7"; name = "plating"; icon_state = "asteroid7"},/area/wizard_station) "Lv" = (/turf/unsimulated/floor{tag = "icon-ironsand12"; icon_state = "ironsand12"},/turf/unsimulated/floor{tag = "icon-asteroid2"; name = "plating"; icon_state = "asteroid2"},/area/wizard_station) +"Lw" = (/obj/structure/table/steel_reinforced,/obj/item/weapon/circuitboard/smes,/obj/item/weapon/circuitboard/smes,/turf/unsimulated/floor{icon_state = "vault"; dir = 8},/area/centcom/specops) "Lx" = (/obj/structure/sign/nosmoking_2{pixel_x = 32},/turf/simulated/shuttle/floor{icon_state = "floor6"},/area/syndicate_station/start) +"Ly" = (/obj/machinery/door/airlock/centcom{name = "Special Operations"; opacity = 1; req_access = list(103)},/obj/machinery/door/blast/regular{icon_state = "pdoor1"; id = "CREED"; name = "Ready Room"; p_open = 0},/turf/unsimulated/floor{icon_state = "delivery"},/area/centcom/specops) "Lz" = (/turf/simulated/floor/holofloor{icon_state = "carpet7-3"; dir = 4},/area/holodeck/source_theatre) "LA" = (/turf/simulated/floor/holofloor/grass,/turf/simulated/floor/holofloor{icon_state = "wood_siding1"; dir = 2},/obj/structure/flora/ausbushes/ywflowers,/turf/simulated/floor/holofloor{icon_state = "wood_siding5"; dir = 2},/area/holodeck/source_picnicarea) "LB" = (/turf/simulated/floor/holofloor{icon_state = "carpet11-12"; dir = 4},/area/holodeck/source_theatre) @@ -2186,16 +2190,16 @@ aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMjHoUoVoVoVqRpepepepepepepepepepeqHoVoVoVoVpFpFtctdpFpFpFtctetdpFqvqvqvpFtftgtgtgtgtgthpFpZqztitjqYqYqYtktlqAjIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMmumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumumumu aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMjHoUoVoVoVoVoVoVoVoVoVoVoVoVoVoVoVoVoVoVoVpFtptptptptptptptptppFpFumpFpFtptptptptptptppFpZqztrtstttttttstuqAjIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumumumu aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvyhyhyhyhyhyhyhtptptptxtxtxtxtxtxpFtytztypFtxtxtxtxtxtxtxtxpZqzqztAtBtBtBtCqzqAjIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvuntvupuxuuuzuyuAtvveuhvfvfvkvgvpvpvyvyyhzdyIyIyIyIvzvAvHvAvJtOtPtQtRtSpFtytztypFtTtUtVtWtWtxaMaMpZqzqzqzqzqzqzqzqzqAjIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvtvtvtvtvtvtvAgtvuhuhuhuhuhuhtvvKuhuhuhuhuhuhuhuhuhyhyByIvMyIyIvEurururvOueufufufufpFtytztypFtWtWtWtWtWtxaMaMugugugugugugugugugugugtxtxtxtxtxtxtxtxtxtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutvPvbuvuwvQuhuhuhuhuhuhuhvRtvvSuhuhuhuhuhuhuhuhuhyhyHvTzqyIyIvzvAvHvAvJueufufufufpFvUumwhpFtWtWtWtWtWtxuguguguguguguowjuqtxurururtxururururururururtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVAIuXuVuVuVuYAIuZvavbvbvctvwluhuhuhuhuhuhuhtvwmuhuhuhuhvpwownwpwpyhzrzpzEyIyIyhwqwqwqtvuDuEuFuGuHtxuIuIuItxtWtWtWtWtWtxuJuKuJuLuMuguNuNuNuOurururuOuruPuQuPuruRuSuTtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvvQtvtvtvuhuhuhuhuhuhuhuhtvuhuhuhuhwytvtvtvtvtvyhyhyhyhyhyhyhxQxQxQtvwzwAvlvmvntxufJyuftxvlvmvowAwBtxvqvrvqvrvqugtxtxtxtxurururtxvsvtuPvuvsvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutvIvbvbwEtvvxwPukxowVwXuhuhtvuhuhuhuhwYtvxawZwZxaxcxbxexdxQxQxQxQxQxgtvufufvBvCvCvCvCvCvCvCvCvCvDufufxhvqvqvqvqvqugvFuNuotxurururtxvGvGxkvGvGvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVwWuXuVuVuVuYwWwivavbvbxltvwFwGwGwGwItvuhuhtvuhuhuhuhxmtvuhxQxQxQxnxQxQxQxQxQxQxQxQxptvufJyvVvWvXvXvXvXvXvXvXvYueJyufugvZwawbwcwdugweuNwjtxurururtxwfwfuNwfwfvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMwgaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvuntvupuxuuuzuyuAtvvMuWuhwyvkvgvfvfvyvyyhzdyIyIyIyIvzvAvHvAvJtOtPtQtRtSpFtytztypFtTtUtVtWtWtxaMaMpZqzqzqzqzqzqzqzqzqAjIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvtvtvtvtvtvtvAgtvuhuhuhuhuhuhtvLsuWuhuhuhuhuhuhuhuhyhyByILtyIyIvEurururvOueufufufufpFtytztypFtWtWtWtWtWtxaMaMugugugugugugugugugugugtxtxtxtxtxtxtxtxtxtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutvPvbuvuwvQuhuhuhuhuhuhuhvRtvtvtvuhuhuhuhuhuhuhuhyhyHvTzqyIyIvzvAvHvAvJueufufufufpFvUumwhpFtWtWtWtWtWtxuguguguguguguowjuqtxurururtxururururururururtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVAIuXuVuVuVuYAIuZvavbvbvctvwluhuhuhuhuhuhuhtvveuhuhuhvpvpwownwpwpyhzrzpzEyIyIyhwqwqwqtvuDuEuFuGuHtxuIuIuItxtWtWtWtWtWtxuJuKuJuLuMuguNuNuNuOurururuOuruPuQuPuruRuSuTtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvvQtvtvtvuhuhuhuhuhuhuhuhtvvKuhuhuhLwtvtvtvtvtvyhyhyhyhyhyhyhxQxQxQtvwzwAvlvmvntxufJyuftxvlvmvowAwBtxvqvrvqvrvqugtxtxtxtxurururtxvsvtuPvuvsvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutvIvbvbwEtvvxwPukxowVwXuhuhtvvSuhuhuhwYtvxawZwZxaxcxbxexdxQxQxQxQxQxgtvufufvBvCvCvCvCvCvCvCvCvCvDufufxhvqvqvqvqvqugvFuNuotxurururtxvGvGxkvGvGvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVwWuXuVuVuVuYwWwivavbvbxltvwFwGwGwGwItvuhuhtvwmuhuhuhxmtvuhxQxQxQxnxQxQxQxQxQxQxQxQxptvufJyvVvWvXvXvXvXvXvXvXvYueJyufugvZwawbwcwdugweuNwjtxurururtxwfwfuNwfwfvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMwgaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumu aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutwxvbvbxqxcxrxtxsxvxuxcuhuhxcuhuhuhuhxwxcuhxQxQuwxxxQxQxQxexetvtvtvtvtvufufvVwrwsufwtwuwvufwswrueufufugugugugugugugweuNwjtxurururtxwwwwuNwwwwvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumu aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVxyuXuVuVuVuYxyxzvavbvbxAxnxHuhuhuhxIxnuhuhxnuhuhxKxJxLxnxMxQxQxQtvwFwGwHwGwItvwJwJwJxNufufwKwLwMwNwOxOwQwRwSwLwTufufxRwUwUwUwUwUtxtxuOtxtxtxuOtxtxuNuNuNuNuNvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumu -aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutxXvbvbxYtvyauhuhuhuhtvybybtvycyctvtvtvtvxMxQxQuwuWxfxfxfxfxfydxfxfxfydufufufyeufufxiufxiufufyeufufufxjurururururxjurururururururxjwwwwwwwwwwvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMmu +aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvutxXvbvbxYtvyauhuhuhuhtvybybtvycyctvtvtvtvxMxQxQuwyWxfxfxfxfxfydxfxfxfLyufufufyeufufxiufxiufufyeufufufxjurururururxjurururururururxjwwwwwwwwwwvvvwvwtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMmu aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMuUuVuVuVuVuVuVuVuVuVuVuVuVuVyfuXuVuVuVuYyfygyivbvbuwyjuhuhuhuhuhyjuhuhykuhuhymylyzyzuhxQxQvdtvwFwGwHwGwItvxBxBxByAufufvBxCxDwNxEufxFwRxGxCvDufufxjurururururxjurururururururxjwwwwwwwwwwtxuOuOtxtxtxtxtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMustvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvtvvbvbuwyjuhuhuhuhuhyjuhuhyCuhuhxQyDyDyDxQxQxQzcyKyGyMxQySyQtvtvtvtvtvufufvVwLxSufxiufxikayqwLueufufwAxTxUxUxUxVtxtxxWtxtxtxuOtxtxtxyXyXyXtxtxurururyYurxZtxaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM aMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMtvvbvbyZtvwFwGwGwGwItvzezetvzfuhxQzgzizhxQxQxQyRzkyMxQxQxQxQxxxQxKzltvufufvVtxtxynyoufypxStxtxueufuftxaMaMaMaMaMtxyrystxuNytuNuNyuyvywywywzmtxururuQuQururyyaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMmumumumumuaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM From ffc50c3cfa04af5dc2949bd2630ada3e7aab48a6 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sat, 17 Oct 2015 20:53:03 -0400 Subject: [PATCH 080/207] Fixes #11321 --- code/modules/mob/living/carbon/human/life.dm | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 031a69dddb5..d5fe68a4882 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -364,17 +364,23 @@ internals.icon_state = "internal0" return null + get_breath_from_environment(var/volume_needed=BREATH_VOLUME) + var/datum/gas_mixture/breath = ..() + + if(breath) + //exposure to extreme pressures can rupture lungs + var/check_pressure = breath.return_pressure() + if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5) + if(is_lung_ruptured() && prob(5)) + rupture_lung() + + return breath handle_breath(datum/gas_mixture/breath) if(status_flags & GODMODE) return - //exposure to extreme pressures can rupture lungs - if(breath && (breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)) - if(!is_lung_ruptured() && prob(5)) - rupture_lung() - //check if we actually need to process breath if(!breath || (breath.total_moles == 0) || suiciding) failed_last_breath = 1 From 9aea0cecc772c521a2179cba06ea0e23c6982cc0 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Thu, 15 Oct 2015 21:25:32 -0400 Subject: [PATCH 081/207] Dead people feel no pain. Resolves #10797 --- code/modules/mob/living/carbon/human/unarmed_attack.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 289b4a22733..1d148b96ead 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -32,6 +32,9 @@ /datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone) + if(target.stat == DEAD) + return + var/stun_chance = rand(0, 100) if(attack_damage >= 5 && armour < 2 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance @@ -233,4 +236,4 @@ switch(attack_damage) if(1 to 4) user.visible_message("[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!") - if(5) user.visible_message("[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/ \ No newline at end of file + if(5) user.visible_message("[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/ From 47ace5ed3e7ceefea76630f89de27acb776c1bd8 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Fri, 16 Oct 2015 01:07:31 -0400 Subject: [PATCH 082/207] Chem smoke refactor --- code/__HELPERS/unsorted.dm | 2 +- code/game/objects/effects/chem/chemsmoke.dm | 94 +++++++++++++-------- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 7122d32f852..0593e055a9c 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -538,7 +538,7 @@ Turf and target are seperate in case you want to teleport some distance from a t var/y = min(world.maxy, max(1, A.y + dy)) return locate(x,y,A.z) -//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. +//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. Lower bound takes priority. /proc/between(var/low, var/middle, var/high) return max(min(middle, high), low) diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index 293992b7354..034ce946864 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -4,26 +4,40 @@ /obj/effect/effect/smoke/chem icon = 'icons/effects/chemsmoke.dmi' opacity = 0 + layer = 6 time_to_live = 300 pass_flags = PASSTABLE | PASSGRILLE | PASSGLASS //PASSGLASS is fine here, it's just so the visual effect can "flow" around glass var/splash_amount = 10 //atoms moving through a smoke cloud get splashed with up to 10 units of reagent var/turf/destination -/obj/effect/effect/smoke/chem/New(var/newloc, turf/dest = null) - - //Calculate time to live - var/pressure = 0 - var/datum/gas_mixture/environment = loc.return_air() - if(environment) pressure = environment.return_pressure() - - time_to_live = max(5, time_to_live*min(pressure/(ONE_ATMOSPHERE/3), 1)) +/obj/effect/effect/smoke/chem/New(var/newloc, smoke_duration, turf/dest_turf = null, icon/cached_icon = null) + time_to_live = smoke_duration ..() + create_reagents(500) - destination = dest + + if(cached_icon) + icon = cached_icon + + set_dir(pick(cardinal)) + pixel_x = -32 + rand(-8, 8) + pixel_y = -32 + rand(-8, 8) + + //switching opacity on after the smoke has spawned, and then turning it off before it is deleted results in cleaner + //lighting and view range updates (Is this still true with the new lighting system?) + opacity = 1 + + //float over to our destination, if we have one + destination = dest_turf if(destination) walk_to(src, destination) +/obj/effect/effect/smoke/chem/Destroy() + opacity = 0 + fadeOut() + ..() + /obj/effect/effect/smoke/chem/Move() var/list/oldlocs = view(1, src) . = ..() @@ -41,6 +55,25 @@ if(!istype(AM, /obj/effect/effect/smoke/chem)) reagents.splash(AM, splash_amount, copy = 1) +/obj/effect/effect/smoke/chem/proc/initial_splash() + for(var/turf/T in view(1, src)) + for(var/atom/movable/AM in T) + if(!istype(AM, /obj/effect/effect/smoke/chem)) + reagents.splash(AM, splash_amount, copy = 1) + +// Fades out the smoke smoothly using it's alpha variable. +/obj/effect/effect/smoke/chem/proc/fadeOut(var/frames = 16) + if(!alpha) return //already transparent + + frames = max(frames, 1) //We will just assume that by 0 frames, the coder meant "during one frame". + var/alpha_step = round(alpha / frames) + while(alpha > 0) + alpha = max(0, alpha - alpha_step) + sleep(world.tick_lag) + +///////////////////////////////////////////// +// Chem Smoke Effect System +///////////////////////////////////////////// /datum/effect/effect/system/smoke_spread/chem smoke_type = /obj/effect/effect/smoke/chem var/obj/chemholder @@ -144,13 +177,21 @@ else I = icon('icons/effects/96x96.dmi', "smoke") + //Calculate smoke duration + var/smoke_duration = 150 + + var/pressure = 0 + var/datum/gas_mixture/environment = location.return_air() + if(environment) pressure = environment.return_pressure() + smoke_duration = between(5, smoke_duration*pressure/(ONE_ATMOSPHERE/3), smoke_duration) + var/const/arcLength = 2.3559 //distance between each smoke cloud for(var/i = 0, i < range, i++) //calculate positions for smoke coverage - then spawn smoke var/radius = i * 1.5 if(!radius) spawn(0) - spawnSmoke(location, I, 1) + spawnSmoke(location, I, 1, 1) continue var/offset = 0 @@ -175,43 +216,26 @@ // Randomizes and spawns the smoke effect. // Also handles deleting the smoke once the effect is finished. //------------------------------------------ -/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1, var/obj/effect/effect/smoke/chem/passed_smoke) +/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/smoke_duration, var/dist = 1, var/splash_initial=0, var/obj/effect/effect/smoke/chem/passed_smoke) var/obj/effect/effect/smoke/chem/smoke if(passed_smoke) smoke = passed_smoke else - smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, T)) + smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, smoke_duration + rand(0, 20), T, I)) if(chemholder.reagents.reagent_list.len) chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents - smoke.icon = I - smoke.layer = 6 - smoke.set_dir(pick(cardinal)) - smoke.pixel_x = -32 + rand(-8, 8) - smoke.pixel_y = -32 + rand(-8, 8) - smoke.opacity = 1 //switching opacity on after the smoke has spawned, and then - sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner - smoke.opacity = 0 // lighting and view range updates - fadeOut(smoke) - qdel(src) + //Kinda ugly, but needed unless the system is reworked + if(splash_initial) + smoke.initial_splash() -/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1) + +/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/smoke_duration, var/icon/I, var/dist = 1) var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location) spores.name = "cloud of [seed.seed_name] [seed.seed_noun]" - ..(T, I, dist, spores) - -/datum/effect/effect/system/smoke_spread/chem/proc/fadeOut(var/atom/A, var/frames = 16) // Fades out the smoke smoothly using it's alpha variable. - if(A.alpha == 0) //Handle already transparent case - return - if(frames == 0) - frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame". - var/step = A.alpha / frames - for(var/i = 0, i < frames, i++) - A.alpha -= step - sleep(world.tick_lag) - return + ..(T, I, smoke_duration, dist, spores) /datum/effect/effect/system/smoke_spread/chem/proc/smokeFlow() // Smoke pathfinder. Uses a flood fill method based on zones to quickly check what turfs the smoke (airflow) can actually reach. From 64176f1c4e6c76c49f371f9341994ca44bbc4401 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 18 Oct 2015 17:51:42 +0200 Subject: [PATCH 083/207] Relocates synth flash recharge code. Moves the flash recharge from security modules to all of them. Fixes #11322. --- .../mob/living/silicon/robot/robot_modules.dm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index d5a2edf3e13..60e6c0f5d65 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -88,6 +88,14 @@ var/global/list/robot_modules = list( return /obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate) + var/obj/item/device/flash/F = locate() in src.modules + if(F.broken) + F.broken = 0 + F.times_used = 0 + F.icon_state = "flash" + else if(F.times_used) + F.times_used-- + if(!synths || !synths.len) return @@ -271,7 +279,6 @@ var/global/list/robot_modules = list( return /obj/item/weapon/robot_module/medical/crisis/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) - var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules if(S.mode == 2) S.reagents.clear_reagents() @@ -424,13 +431,7 @@ var/global/list/robot_modules = list( return /obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) - var/obj/item/device/flash/F = locate() in src.modules - if(F.broken) - F.broken = 0 - F.times_used = 0 - F.icon_state = "flash" - else if(F.times_used) - F.times_used-- + ..() var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules if(T.power_supply.charge < T.power_supply.maxcharge) T.power_supply.give(T.charge_cost * amount) @@ -464,6 +465,7 @@ var/global/list/robot_modules = list( return /obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + ..() var/obj/item/device/lightreplacer/LR = locate() in src.modules LR.Charge(R, amount) if(src.emag) @@ -547,6 +549,7 @@ var/global/list/robot_modules = list( src.emag = new /obj/item/weapon/stamp/denied(src) /obj/item/weapon/robot_module/general/butler/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + ..() var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules E.reagents.add_reagent("enzyme", 2 * amount) if(src.emag) From b92be265ee6b398383755fc4d624e56f2ad83f74 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 19 Oct 2015 12:49:32 +0200 Subject: [PATCH 084/207] Limits the number of runes to one per turf. Fixes #11248. --- code/game/gamemodes/cult/ritual.dm | 6 +++++- code/modules/spells/general/rune_write.dm | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index b4846ecc76e..3cd2ddef9ff 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -527,7 +527,11 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," user << "\red You do not have enough space to write a proper rune." var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun") r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. - var/obj/effect/rune/R = new /obj/effect/rune + if(locate(/obj/effect/rune) in user.loc) + user << "There is already a rune in this location." + return + + var/obj/effect/rune/R = new /obj/effect/rune(user.loc) if(istype(user, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user R.blood_DNA = list() diff --git a/code/modules/spells/general/rune_write.dm b/code/modules/spells/general/rune_write.dm index c110a76ac14..c28289d60f4 100644 --- a/code/modules/spells/general/rune_write.dm +++ b/code/modules/spells/general/rune_write.dm @@ -21,6 +21,10 @@ runerandom() var/list/runes = list("Teleport", "Teleport Other", "Spawn a Tome", "Change Construct Type", "Convert", "EMP", "Drain Blood", "See Invisible", "Resurrect", "Hide Runes", "Reveal Runes", "Astral Journey", "Manifest a Ghost", "Imbue Talisman", "Sacrifice", "Wall", "Free Cultist", "Summon Cultist", "Deafen", "Blind", "BloodBoil", "Communicate", "Stun") var/r = input(user, "Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. + if(locate(/obj/effect/rune) in user.loc) + user << "There is already a rune in this location." + return + var/obj/effect/rune/R = new /obj/effect/rune(user.loc) if(istype(user.loc,/turf)) var/area/A = get_area(user) From 2a936d247d4a20de26d2a167510c734ca539eb1b Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 20 Oct 2015 08:31:40 +0200 Subject: [PATCH 085/207] Airlocks should no longer be temporarily electrified for the rest of the round. Airlocks are no longer electrified for as long as the round has been going when EMPd. --- code/game/machinery/doors/airlock.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 0f5eeb48b7b..524708b64ed 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1067,8 +1067,8 @@ About the new airlock wires panel: /obj/machinery/door/airlock/emp_act(var/severity) if(prob(40/severity)) - var/duration = world.time + SecondsToTicks(30 / severity) - if(duration > electrified_until) + var/duration = SecondsToTicks(30 / severity) + if(electrified_until > -1 && (duration + world.time) > electrified_until) electrify(duration) ..() From 4c96cd62a72139071f6ddd6b39a60f6a49763d7c Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 20 Oct 2015 17:11:55 +0200 Subject: [PATCH 086/207] Condiments now check for proximity before continuing with the rest of afterattack. Fixes #11334. --- code/modules/reagents/reagent_containers/food/condiment.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index a8184ac8157..b5fd5e53444 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -25,7 +25,10 @@ if(standard_feed_mob(user, M)) return - afterattack(var/obj/target, var/mob/user, var/flag) + afterattack(var/obj/target, var/mob/user, var/proximity) + if(!proximity) + return + if(standard_dispenser_refill(user, target)) return if(standard_pour_into(user, target)) From 8c56aaa372d212047fda425f7aab0214b1262f57 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 27 Oct 2015 12:31:18 +0100 Subject: [PATCH 087/207] Updates changelog. --- html/changelog.html | 6 ++++++ html/changelogs/.all_changelog.yml | 4 ++++ .../changelogs/HarpyEagle-pepperspray-fix.yml | 20 ------------------- 3 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 html/changelogs/HarpyEagle-pepperspray-fix.yml diff --git a/html/changelog.html b/html/changelog.html index 372d1d37624..554144e8fc1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,12 @@ -->
      +

      27 October 2015

      +

      HarpyEagle updated:

      +
        +
      • When affected by pepperspray, eye protection now prevents blindness and face protection now prevents stun, instead of face protection doing both.
      • +
      +

      14 October 2015

      Hubblenaut updated:

        diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 4dc9f9dac63..89f6ba658f4 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2032,3 +2032,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: Messages for adding to existing stack appear again. TheWelp: - rscdel: Removed higher Secret player requirements. +2015-10-27: + HarpyEagle: + - bugfix: When affected by pepperspray, eye protection now prevents blindness and + face protection now prevents stun, instead of face protection doing both. diff --git a/html/changelogs/HarpyEagle-pepperspray-fix.yml b/html/changelogs/HarpyEagle-pepperspray-fix.yml deleted file mode 100644 index c474310d0f8..00000000000 --- a/html/changelogs/HarpyEagle-pepperspray-fix.yml +++ /dev/null @@ -1,20 +0,0 @@ -################################ -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -author: HarpyEagle -delete-after: True -changes: - - bugfix: "When affected by pepperspray, eye protection now prevents blindness and face protection now prevents stun, instead of face protection doing both." \ No newline at end of file From 2ba9c7bc79ebd94b01bfac942924187c18c9c475 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 28 Oct 2015 09:17:31 +0100 Subject: [PATCH 088/207] Allows drones to recharge their synth materials. Fixes #11387. --- .../mob/living/silicon/robot/robot_modules.dm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 60e6c0f5d65..560bf09cc13 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -89,12 +89,13 @@ var/global/list/robot_modules = list( /obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate) var/obj/item/device/flash/F = locate() in src.modules - if(F.broken) - F.broken = 0 - F.times_used = 0 - F.icon_state = "flash" - else if(F.times_used) - F.times_used-- + if(F) + if(F.broken) + F.broken = 0 + F.times_used = 0 + F.icon_state = "flash" + else if(F.times_used) + F.times_used-- if(!synths || !synths.len) return From 4b42f692474dbb061e967d4454381ad3e7eeeea7 Mon Sep 17 00:00:00 2001 From: Daranz Date: Wed, 28 Oct 2015 13:35:24 -0400 Subject: [PATCH 089/207] Fix a problem with solar control computers not connecting to powernets on build --- code/modules/power/solar.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index a355e169571..a6184a1a932 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -360,9 +360,8 @@ var/list/solars_list = list() /obj/machinery/power/solar_control/initialize() ..() - if(!powernet) return + if(!connect_to_network()) return set_panels(cdir) - connect_to_network() /obj/machinery/power/solar_control/update_icon() if(stat & BROKEN) From ab2ddfcba72516cef95503c60b5ffbe2fbf80c51 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 29 Oct 2015 16:55:58 +0100 Subject: [PATCH 090/207] Atmospheric computer circuit additions. Adds several missing variables used in the construction and deconstruction set of gas management computers. Fixes #11392. Computers also no longer attemps to qdel a type on Destroy() --- code/game/machinery/computer/computer.dm | 5 - .../circuitboards/computer/air_management.dm | 112 +++++++++++++++++- 2 files changed, 110 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 1e9409437af..4317f749696 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -12,11 +12,6 @@ var/light_range_on = 3 var/light_power_on = 1 -/obj/machinery/computer/Destroy() - qdel(circuit) - circuit = null - return ..() - /obj/machinery/computer/initialize() power_change() diff --git a/code/game/objects/items/weapons/circuitboards/computer/air_management.dm b/code/game/objects/items/weapons/circuitboards/computer/air_management.dm index d244fd6b5c0..7651ac7bcb5 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/air_management.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/air_management.dm @@ -1,27 +1,135 @@ #ifndef T_BOARD -#error T_BOARD macro is not defined but we need it! +#error T_BOARD macro is not defined but we need it! #endif /obj/item/weapon/circuitboard/air_management name = T_BOARD("atmosphere monitoring console") build_path = /obj/machinery/computer/general_air_control + var/console_name var/frequency = 1439 + var/list/sensors = list() + var/list/sensor_information = list() + /obj/item/weapon/circuitboard/air_management/tank_control name = T_BOARD("tank control") build_path = /obj/machinery/computer/general_air_control/large_tank_control frequency = 1441 + var/input_tag + var/output_tag + + var/list/input_info = list() + var/list/output_info = list() + + var/input_flow_setting = 200 + var/pressure_setting = ONE_ATMOSPHERE * 45 + /obj/item/weapon/circuitboard/air_management/supermatter_core name = T_BOARD("core control") build_path = /obj/machinery/computer/general_air_control/supermatter_core frequency = 1438 + var/input_tag + var/output_tag + + var/list/input_info = list() + var/list/output_info = list() + + var/input_flow_setting = 700 + var/pressure_setting = 100 + /obj/item/weapon/circuitboard/air_management/injector_control name = T_BOARD("injector control") build_path = /obj/machinery/computer/general_air_control/fuel_injection + var/device_tag + var/list/device_info + var/automation = 0 + var/cutoff_temperature = 2000 + var/on_temperature = 1200 +/************ +* Construct * +************/ /obj/item/weapon/circuitboard/air_management/construct(var/obj/machinery/computer/general_air_control/C) if (..(C)) - C.frequency = frequency + if(console_name) + C.name = console_name + C.set_frequency(frequency) + C.sensors = sensors.Copy() + C.sensor_information = sensor_information.Copy() + return 1 +/obj/item/weapon/circuitboard/air_management/tank_control/construct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC) + if(..(LTC)) + LTC.input_tag = input_tag + LTC.output_tag = output_tag + + LTC.input_info = input_info.Copy() + LTC.output_info = output_info.Copy() + + LTC.input_flow_setting = input_flow_setting + LTC.pressure_setting = pressure_setting + return 1 + +/obj/item/weapon/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/general_air_control/supermatter_core/SC) + if(..(SC)) + SC.input_tag = input_tag + SC.output_tag = output_tag + + SC.input_info = input_info.Copy() + SC.output_info = output_info.Copy() + + SC.input_flow_setting = input_flow_setting + SC.pressure_setting = input_flow_setting + return 1 + +/obj/item/weapon/circuitboard/air_management/injector_control/construct(var/obj/machinery/computer/general_air_control/fuel_injection/FI) + if(..(FI)) + FI.device_tag = device_tag + FI.device_info = device_info.Copy() + FI.automation = automation + FI.cutoff_temperature = cutoff_temperature + FI.on_temperature = on_temperature + return 1 + +/************** +* Deconstruct * +**************/ /obj/item/weapon/circuitboard/air_management/deconstruct(var/obj/machinery/computer/general_air_control/C) if (..(C)) + console_name = C.name frequency = C.frequency + sensors = C.sensors.Copy() + sensor_information = C.sensor_information.Copy() + return 1 + +/obj/item/weapon/circuitboard/air_management/tank_control/deconstruct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC) + if(..(LTC)) + input_tag = LTC.input_tag + output_tag = LTC.output_tag + + input_info = LTC.input_info.Copy() + output_info = LTC.output_info.Copy() + + input_flow_setting = LTC.input_flow_setting + pressure_setting = LTC.pressure_setting + return 1 + +/obj/item/weapon/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/general_air_control/supermatter_core/SC) + if(..(SC)) + input_tag = SC.input_tag + output_tag = SC.output_tag + + input_info = SC.input_info.Copy() + output_info = SC.output_info.Copy() + + input_flow_setting = SC.input_flow_setting + pressure_setting = SC.input_flow_setting + return 1 + +/obj/item/weapon/circuitboard/air_management/injector_control/deconstruct(var/obj/machinery/computer/general_air_control/fuel_injection/FI) + if(..(FI)) + device_tag = FI.device_tag + device_info = FI.device_info.Copy() + automation = FI.automation + cutoff_temperature = FI.cutoff_temperature + on_temperature = FI.on_temperature + return 1 From f8752c7456b58b0a07d39691f27ad4fac2776669 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Sun, 1 Nov 2015 14:33:54 +0100 Subject: [PATCH 091/207] Fixes #11395 + 2 other minor issues - Fixes #11395 - light fixtures in xenobiology access moved by one tile, so they may be reached without deconstructing windows. - Adds missing air canister to departures airlock port. - One turf in engineering shuttle dock had wrong area (engine maintenance). I assume this was not intended, as rest of the room had proper area set (engineering shuttle dock) --- maps/exodus-1.dmm | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index 1d71a3f7d6c..2801b367f19 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -5533,7 +5533,7 @@ "ccu" = (/obj/structure/table/standard,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_pump/on{dir = 4},/turf/simulated/floor{dir = 9; icon_state = "whitered"},/area/medical/patient_c) "ccv" = (/obj/structure/window/basic{dir = 8},/obj/machinery/shower{dir = 1},/obj/machinery/door/window/northright{name = "Shower"},/obj/structure/curtain/open/shower/engineering,/turf/simulated/floor{icon_state = "freezerfloor"},/area/crew_quarters/sleep/engi_wash) "ccw" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/visible/universal{dir = 4},/turf/simulated/floor/plating,/area/maintenance/research_starboard) -"ccx" = (/obj/machinery/atmospherics/portables_connector{dir = 1},/turf/simulated/floor/plating,/area/storage/emergency) +"ccx" = (/obj/machinery/atmospherics/portables_connector{dir = 1},/obj/machinery/portable_atmospherics/canister/air/airlock,/turf/simulated/floor/plating,/area/storage/emergency) "ccy" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/floor/plating,/area/storage/emergency) "ccz" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/floor/plating,/area/storage/emergency) "ccA" = (/obj/machinery/power/breakerbox/activated{RCon_tag = "Research Substation Bypass"},/turf/simulated/floor/plating,/area/maintenance/substation/research) @@ -5883,11 +5883,11 @@ "cjg" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/turf/simulated/floor{tag = "icon-whitegreen_v (SOUTHWEST)"; icon_state = "whitegreen_v"; dir = 10},/area/rnd/xenobiology/xenoflora_storage) "cjh" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/atmos_control) "cji" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/red,/turf/simulated/floor,/area/engineering/foyer) -"cjj" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/light,/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor/plating,/area/rnd/xenobiology) -"cjk" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/turf/simulated/floor{icon_state = "white"},/area/rnd/xenobiology) +"cjj" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/obj/machinery/light,/turf/simulated/floor{icon_state = "white"},/area/rnd/xenobiology) +"cjk" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor/plating,/area/rnd/xenobiology) "cjl" = (/obj/machinery/door/firedoor/border_only{dir = 1; name = "Engineering Firelock"},/obj/machinery/door/airlock/glass_engineering{name = "Engineering EVA Storage"; req_one_access = list(11,24)},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/red{tag = "icon-intact (EAST)"; icon_state = "intact"; dir = 4},/turf/simulated/floor,/area/engineering/engine_eva) -"cjm" = (/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/machinery/atmospherics/pipe/manifold/hidden/purple,/turf/simulated/floor{icon_state = "white"},/area/rnd/xenobiology) -"cjn" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/light,/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor/plating,/area/rnd/xenobiology/xenoflora) +"cjm" = (/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/machinery/atmospherics/pipe/manifold/hidden/purple,/obj/machinery/light,/turf/simulated/floor{icon_state = "white"},/area/rnd/xenobiology) +"cjn" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only{dir = 2},/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor/plating,/area/rnd/xenobiology/xenoflora) "cjo" = (/obj/machinery/atmospherics/pipe/simple/hidden/purple{dir = 4},/turf/simulated/floor{icon_state = "hydrofloor"},/area/rnd/xenobiology/xenoflora) "cjp" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/red{tag = "icon-intact (NORTHWEST)"; icon_state = "intact"; dir = 9},/turf/simulated/floor,/area/engineering/foyer) "cjq" = (/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/machinery/camera/network/engineering{c_tag = "Engineering Foyer"; dir = 8},/turf/simulated/floor{dir = 2; icon_state = "yellowcorner"},/area/engineering/foyer) @@ -6857,7 +6857,6 @@ "cBS" = (/obj/machinery/atmospherics/binary/pump{dir = 4; name = "Mixing to Port"},/turf/simulated/floor,/area/engineering/atmos) "cBT" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor,/area/engineering) "cBU" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor,/area/engineering) -"cBV" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/engi_engine) "cBW" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) "cBX" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) "cBY" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) @@ -7555,7 +7554,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaaaaaaaaaaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacejcejcejcejcejcejcejcetcesbYIbYIbYIbYIbYIcgfcgmcgjcgjcgjcgocewbXzbXybYeceybYjceEceTceSceWceUceXbSUcezaJFceYaJFcaqbTFcbIceDcfacfacfaceFceGbTJcgCcgBbTJcedcbNceJcefcaEcgOceLceMcaIbZxbWQceNbZyceOcePbZAbZAbZAbZAbZAccbceRbYfcaQbYcccdcgRbYcbYcchBcgVcjfcdLcgWcfbcfbcfccdOcfdcgXcffcdOcfgcfhcfhcfhcgYchacgZchdchbcfnchicfpcdScfqcfrchmbUnbUnbUnbUnaaaaafaaaaaaaaaaahaahaahaafaaaaaaaafaaaaaaaafaafaafcftcfBcfvbNebKsbKtbKtbLTbLUbLTbKtbKtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaafaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafcejchpchnchrchqchucejcfDcfCcfFcfEcfHchvchychycfKcfJcfJchzchEcbqbXzbXybYecfNcaicfOcfQcfPchLchFcggbSUaJFaJFcaqceBcaqbTFcbIcfVcfWcfWcfWcfXcbIcfYchPcgacfYcgbcgccgdchScaEchVceLcgicaIcghccfchYbZycgkcglbZycifbLvbVicgnccgcchbYfccjcciccicckcclcclcclcclccmcdLcijcgycgycgzcgActscgrcgpcgucgtcgGcgGcgGcgxcgIcgIcgJciycgLcgDcgMcdScgNciCcgPcgNaaaaaaaaaaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafcgQbKqbKqbKrbKsbKsbKtbKtbKtbKtbKuaafaafaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaafaafaafcgEcgEcgEcgEcgEcgEcgEcgEcgEcgEcgEcgEcgEaaaaaacgSciKcgTcgTcgUciLcejcgHcgFciPcgKciVciQcjaciWcjlcjicjpchcchfchechhchgchjcjqbSUbSUbSUbSUbSUbSUbSUbSUcjsccvcaqcjtcaqbTFcbIcbIctpctqctrcbIcbIcjuchschtcfYcaEcaEcaEcaEcaEcaIchkchlcaIchwcjvchwbZycjIcjCbZychAchBbVichCbVichDbYfccobYfbYfccpcdCcdCcdCcdDbYfcdLchIchJchJchKckachMchochOckdchQckLckLckLckLckjckfckLckmckLcknckocdSchZciachGcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaaaaaaaaaaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEchHckpchHcgEchNckCchNcgEchRckFchRcgEaaaaaaciiciKcgTcgUcgUckNcejchUchTchWckQclfchXcidcicclgcieciecigciecbqbXzcihbYecikcimcilciocinciocipcirciqciqciAciAciAciAbTFciGciHciIciIciJclpclrciMciXciOclycluciRciSciSciTciUcaIcaIcaIclCcdEckqbZybZybZybZychBchBbViciYbViciZbYfccobYfaaaaaaaaaaaaaaaaaaaaacdLcjgcisciucitcjjcjkcivcjmcjncjociwcjocjocixclKclGcgIclVcgIcmgcmkcdScmpcjwcjxcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEchHckpchHcgEchNckCchNcgEchRckFchRcgEaaaaaaciiciKcgTcgUcgUckNcejchUchTchWckQclfchXcidcicclgcieciecigciecbqbXzcihbYecikcimcilciocinciocipcirciqciqciAciAciAciAbTFciGciHciIciIciJclpclrciMciXciOclycluciRciSciSciTciUcaIcaIcaIclCcdEckqbZybZybZybZychBchBbViciYbViciZbYfccobYfaaaaaaaaaaaaaaaaaaaaacdLcjgcisciucitcjkcjjcivcjmcjncjociwcjocjocixclKclGcgIclVcgIcmgcmkcdScmpcjwcjxcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEchHcjbchHcgEchNcjcchNcgEchRcjdchRcgEaaaaaaciicgTcgUcgUcgUcjBcmscjhcjechWcmwcmGcmBcmPcmOcjzcjycjDcjAcjEcbqbXzcjFchjcjGcmQcjHcjJcjJcjJcjKcjMcjLcjNcmRcjOceAciAbTFciGcmXciIckbckccnbcubcneckgckhcngcnfckkcklciScnhciUcnkcnwcnucjQcjPcdHcnEcdIcdIcdJcdIcdKbVibVibVibVibYfccobYfaaaaaaaaaaaaaaaaaaaaacdLcnFcjRcjTcjSckEcdOcnIcdOckGckHcjXcjUcjUcjYcgIcgIckecjZcjUckickOcdSckPcnKckRcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEckrckuckscgEckzckBckAcgEckDckJckIcgEaaaaafciiclbcgTcgUcgUcgUcejckMckKchWchWcnLchWchWchWchWckTcieckWckYcbqclackZcldclccnNcleclhclhclhclicljcljclkciAcllcgqclwclxciGcnPciIclzclAclBcnQclDclEclFcnTclHclIclJciScnUciUcnVcnXclNclnclmclQclNclRclSclTbYfceQcdIcdIcdIcdIcdIcltbYfaaaaaaaaaaaaaaaaaaaaacdLcmacmbcmccmdcdOcmecmfcnZcdScmhcmicmicmiclvcoacmlclPclOcmicmicmncdScmocobcmqcmraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaafaafcgEclXcmmcmjcgEcmtcmmcEgcgEcmtcmmcEgcgEaaaaafcmzcgTcgTcgUcgUcmAcejcmvcmucmxcolconcmycmCcmCcmEcmDcmCcmFcoqcbqcmIcmHcmKcmJcimcmLcmLcmMcljcmNcotcorcorciAcibceVcoycqgciGcoAciIcnccndcoBciGcmSciNcmWciUcoCcnicnjciScoFciUclLclMclNcnlcoJcnlclNaaaaaaaaabYfbYfbYfcnnclSclSclTbYfbYfaaaaaaaaaaaacdOcdOcdOcdOcdOcdOcdOcdOcdOcnocnpcnqcdScdScnrcnscntcdScdScdScdScoLcnscntcdScdScnvcpdcnvaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7572,7 +7571,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaaaaaaaaacptcpFczmcrWcrWczpcxGcrWczpcrWcxIczMctIctIczSctIczTctIctIctSczVcybcpFcpFcyjcylcykcynczXcyocpFcAhcyqcyscyscAtcytcoTcxucyvcnOcAvcpacyxcpacAwcyycpjcpjcpjcpjcpjcpjcpjbPxcvMcvNcAxcyNcxLcyOcxLcxNcAAcvNcrGcJGcrGaaaaaaaaaaaaaaaaaacqvcuVcAHctFctFcAJcyAcAQcyWctMctDctNcyBctMcvhcyYcqvaaaaaaaaaaaacdOcplcplcplckXcARczacrNcrNcrNcyfcrNczbcrNczccrNczdaafaafcrPaafckVckSckSckSckSckyckxckwckvckvckvckvckUaafcrPaaaczLczLczLczLaaaaaaaaaczLczLczLczLczLczLczLaaaaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaaaaaaaaacptcpFcqXcpFcpFcpFcyMcpFcpFcpFcyMcpFcpFcpFcyCcpFcvWcpFcpFcpFcyDcybcpFcpFcATcyTctfcyGcwgcAUcwgcwgcyqcAWcyIcBkcytcoTcxucoTcnOcBncBmcBscBqczfcpacnOcBucBzcBzczhcBAcBDczNczOcvNcBEczPczQcxNczRcBHcBIcvNcJIcJHcrGaaaaaaaaaaaaaaaaaacqvczWcuMcBLcuVczYczZcAactFcAbcAccsPcyBczWczjcAecqvaaaaaaaaaaaackEcdOcAfcAgcAgczkcAicAjcAkcAlcAmcAncAocApcAqcokcAraaaaaacrPaafcwjcwjcwjcwjcwjaaackxaafcwjcwjcwjcwjcwjaaacrPaaaczLczLczLczLaaaaaaczLczLczLczLczLczLczLczLczLaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaIaaaaaaczlcpFcqXcpFcBOcxactxcxacBRcxactxcxacBRcxacxccxacxbcBSctectdcCcctfczsczucztczwczvczxcwgczzczycwgcwgcwgcwgcwgczAcpCcCecpCcnOcnOcnOcnOcnOcnOcnOcnOczDcBzcBzczEcANcAObPxcAPcvNcCgcCfcClcCicCqcCncCvcvNcAXcJJcrGaaaaaaaaaaaaaaaaaacqvcuQcAZcAectFcBacBbcBcctFcBdcBecCBczGczIcBecCFcqvaafaafaaaaaaaaaaaabquaaacdOcBlczJcCJcBocBpczJcCNcBrcBpczJcCOcdOaaaaaacbOaaaaafaaaaafaaaaafaaackxaaaaafaaaaafaafaafaafcrPaaaczLczLczLczLaaaaaaczLczLczLczLczLczLczLczLczLaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbOaaaaaaaaaaaIaaaaaacAdcpFcqXcpFcCQcylcqXcpFcCYcylcqXcpFcAucylcpFcpFcDacpFcDccylcDdcAzcAycABcDmcDpcACcAEcwgcDtcAFcDwcAIcAKcumcAMcALcumcAScumcBfcuocBgcBicBhcBhcBjcDxcBVcBWcBWcBXcBYcAObPxcBZcvNcvNcCacCbcDFcCbcCacCdcvNcrGcDIcrGaaaaaaaaaaaaaaaaaacqvctFcDLcuVctFcDNcChcDOctFcCjcCkcqycgvcBtcCkcCocrHaaaaaaaaaaaaaaaaaacgwaafcdOcDUcCKclUcomclscDXclqcomclocEbclWcdOaaaaaacrPaaactXctXctXctXctXaafckxaafctXctXctXctXctXaafcrPaaaczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbOaaaaaaaaaaaIaaaaaacAdcpFcqXcpFcCQcylcqXcpFcCYcylcqXcpFcAucylcpFcpFcDacpFcDccylcDdcAzcAycABcDmcDpcACcAEcwgcDtcAFcDwcAIcAKcumcAMcALcumcAScumcBfcuocBgcBicBhcBhcBjcDxcBWcBWcBWcBXcBYcAObPxcBZcvNcvNcCacCbcDFcCbcCacCdcvNcrGcDIcrGaaaaaaaaaaaaaaaaaacqvctFcDLcuVctFcDNcChcDOctFcCjcCkcqycgvcBtcCkcCocrHaaaaaaaaaaaaaaaaaacgwaafcdOcDUcCKclUcomclscDXclqcomclocEbclWcdOaaaaaacrPaaactXctXctXctXctXaafckxaafctXctXctXctXctXaafcrPaaaczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrPaafaafaafaaIaafaafcAdcpFcEecBycBxcEicEfcBCcBBcEqcEjcBGcBFcErcpFcBvcEycEBcBJcBMcEEcnycnycnycnycnycnycnycnycEJcBNczAcBPcBQcoTcEXcoTcoTcxucoTcoTcEZcoTcBQcBTcCpcBUcCrcFecFrcFgcCPcFCcAObPwcCRcCScCTcCacAGcAVcBwcCacCtcCscCucFEcCXaaaaaaaaaaaaaaaaaacqvcFFctDcuQcFKcDbcuQcFUcFLcDeaafaaachxcCxcCwcCyaaaaaaaaaaacaaaaaaaaaaaaaaacdOcDhcplcplcomcDicplcplcomcDicplcplcdOaafaafcrPaafckVckSckSckSckSckyckxckwckvckvckvckvckUaafcrPaaaczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrPcCzaaaaaaaaIaaaaaacCAcCCcFVcCEcCDcCGcFWcCHcCDcCGcFWcCHcCDcCGcCIcCIcGgcCHcCDcCGcGhcnyaaacCMcCLcCVcCUcCZcCWcDjcDgcDkcDkcGocDlcDocDncDqcGucDncDqcDocDrcGvcDscDrczAczAcAOcGEcGAcDPcDQcAObNUcDRcDScDTcCacCbcGMcCbcCacDvcDucDfaafaaaaaaaaaaaaaaaaaaaaacqvcFFcDVcGZcGOcGOcGZcsPcDYcqvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacdOcDZcplcplcomcEacplcplcomcEacplcplcdOaaaaaacrPaafcwjcwjcwjcwjcwjaaackxaaacwjcwjcwjcwjcwjaaacrPaaaczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrPcHacHjcHjcHCcHjcHjcHjcHjcHVcHjcIAcHjcHVcHjcIAcHjcHVcHjcIAcHjcHjcHjcIAcHjcIAcHjcIMaafaaacDzcDycDBcDAcDDcDCcDjcDEcDkcIRcDHcDGcDJcITcIZcDKcDWcDMcDJcJhcEdcJlcDraaaaafcAOcJpcECcEDaafaaabNUbPxbPxbSkcCaclZcEFclYcCaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacqvcJzcuXcJBcJAcJAcJBcuQcEKcqvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacdOcplcplcplcomcELcplcplcomcELcplcplcdOaacaaacrPaaaaaaaafaafaafaaaaaacmTaafaaaaaaaafaafaaaaaacrPaaaczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa From f49b6d7cd117b29abff535d9fcf9cfeecb4c2f91 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Mon, 2 Nov 2015 23:35:25 -0500 Subject: [PATCH 092/207] Fixes #11405 --- code/modules/mob/living/carbon/human/life.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 79abbaef67a..f8abe2778ba 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -371,7 +371,7 @@ //exposure to extreme pressures can rupture lungs var/check_pressure = breath.return_pressure() if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5) - if(is_lung_ruptured() && prob(5)) + if(!is_lung_ruptured() && prob(5)) rupture_lung() return breath From daa9b0e0bc9ba1639c188053adbffac2af61c986 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 4 Nov 2015 17:49:42 +0100 Subject: [PATCH 093/207] When a diona splits, the main nymph inherits all known languages. Fixes #11401. --- code/modules/mob/language/language.dm | 4 ++++ code/modules/mob/living/carbon/human/human_powers.dm | 3 +-- code/modules/mob/mob_helpers.dm | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 8c6b92c5557..c6d9756c9b3 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -188,4 +188,8 @@ else return ..() +/proc/transfer_languages(var/mob/source, var/mob/target) + for(var/datum/language/L in source.languages) + target.add_language(L.name) + #undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 50f46b4bb41..8ddd6bb1a6a 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -229,6 +229,7 @@ var/mob/living/carbon/alien/diona/S = new(T) S.set_dir(dir) + transfer_languages(src, S) if(mind) mind.transfer_to(S) @@ -254,5 +255,3 @@ visible_message("\The [src] quivers slightly, then splits apart with a wet slithering noise.") qdel(src) - - diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 862f92fd5bc..4f55f3d55b4 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -640,7 +640,7 @@ proc/is_blind(A) // A proper CentCom id is hard currency. else if(id && istype(id, /obj/item/weapon/card/id/centcom)) return SAFE_PERP - + if(check_access && !access_obj.allowed(src)) threatcount += 4 From 1e6c0017d4a3bf382c7891abaaae467f8251bf92 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 5 Nov 2015 08:07:12 +0100 Subject: [PATCH 094/207] Changes alien intent_hurt icon state to intent_harm. Fixes #11415. --- icons/mob/screen1_alien.dmi | Bin 141060 -> 141059 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/screen1_alien.dmi b/icons/mob/screen1_alien.dmi index b21cd203dd59dd4e0bc8c244c29fbe7f091156a4..4ee41ca91c655ff0c0002c465fb7b73713b999f6 100644 GIT binary patch delta 806 zcmV+>1KIq9&Ip6f2#_Ry0eVzebVOxyV{&P5bZKvH004NLrI$^Q+At7?&*WFQyT^u> z1hVDArP@`shwWd8oOpt*ICg3~eDv4%02SfG%%Bw~q$jV(_B-R5XZG{$*ZXhw`thD@ zzeT4m?}2>;zQ2 zZigPllnLMr*RvCu-6u0LnWJQ*9N;TA$^pKr-R*HHyW8VR!R~OSV0XBZ1g?X`#SR=* z4?oufHz#rnB3Inz@?;`F^F3R!A}uaIdO^keK@;rP4_ePks|8992L24HCn@4bUTI#p zG>RM5@c_5s#p#rP@?w@|X_k)N1YJ+?9CSUwzR>l!MFMm^Zjb<7AF;>i+UM!~{F5my z$|)_(DJ{C{B9h0374wyjaHxuXKXi-_x|EaE5OU*k;C)g2!5sHl`@TWH6G*_I(o4C_f~2B z2pf4l$Bj{%r+KUjkCY<&o?j?^rkd~YoZUN7~O53`BC8U-wFFJup)6wu+nKdf6<+`PC zZZL+z38<}BhS0SE*FpXu4s5tL19ZKP&MeoH?36Nq9jDm`*!%%@9%o0L{vusojkymj zQjpj~Ng|<#XS3vll6gc)-NKP2HXuiu)MEUPf};D^8Yn&BTa(-no;S&jAhh;%DDMvX k&+P3G_bYq-cu)QTG`eml25!UPgD(SzF9QL$F9QPABMga`g#Z8m delta 807 zcmV+?1K9k7&Ip9g2#_Ry0(w+fbVOxyV{&P5bZKvH004NLrI*ca+b|5r&+$`e?QzZ) zJ8_pwE<=l&*`g!CvgAo}KKArGBtx7Jg$xRx4E#h<;-3`x%znQ8djHK{Ki-oK zIIpZ>E4KJHOD0<-f@CW;&y$G+wU*)V;{y-CR_y61nF!@PTd`$-GHD#|z_S(0PC&)$ zcIZ(|nE=jkJv))veKI4HIZ8Il0lssi9N@d!-5xh(cYEAYushsRusht61g?X`jU70u zJ^Wq|+?>cQh+J`-%ae%!&G&4@inO>~^nx1i2ThP)KWIHGtrjRb82B@&o@5cf@=Ei% zrBU3djt966FHX0Alozu!OS5#WCg^&C=Ai2d@`bL)B@&?Pae)Nr`iMM6VV|e-^CeT7 zms6UXQ<|UC2OX`nB}A6jp$yX5ZE2h45!#So;ViDy3q40lx#UKa%J4d<%}9icJ2a84 z!31!m^GI&+3_XV;o9<9EJ6t~8IlH}06(?C_hjdKyWa40dtBklxZi5S@(cH@jH9M2w zKn#Zc}$Wr9o^9xI#spdPp=MdbrS-vE3FL;kFxNGP5izeK#UPmOpynfQM z%TCi+;ZyfeqJYfUeikndN$tol*v{<23sKn?JzLcG53K@ z3KDxLNhI{}Y?ho*GLI;!TR5`B2INSST8#f*3=Yr2zt%wM0Y94LhVZ;eZUmvVuS0ov l(0^tTZ@*vJ>&JWY4@p>VLLb!-$b&8ehb{vFw=M$$)gvg5la~Mh From 5f4af85af985227e1dbfca34438760fd53a4fd5c Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 5 Nov 2015 08:14:22 +0100 Subject: [PATCH 095/207] Refactors diona split code for maximum reuse. --- .../mob/living/carbon/human/human_powers.dm | 9 ++++++--- .../living/carbon/human/species/station/station.dm | 14 +------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 8ddd6bb1a6a..bcb4dd2c33b 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -224,7 +224,9 @@ set name = "Split" set desc = "Split your humanoid form into its constituent nymphs." set category = "Abilities" + diona_split_into_nymphs(5, 1) // Separate proc to void argments being supplied when used as a verb +/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs, var/delete_self = 1) var/turf/T = get_turf(src) var/mob/living/carbon/alien/diona/S = new(T) @@ -243,8 +245,8 @@ D.loc = T D.set_dir(pick(NORTH, SOUTH, EAST, WEST)) - if(nymphs < 5) - for(var/i in nymphs to 4) + if(nymphs < number_of_resulting_nymphs) + for(var/i in nymphs to (number_of_resulting_nymphs - 1)) var/mob/M = new /mob/living/carbon/alien/diona(T) M.set_dir(pick(NORTH, SOUTH, EAST, WEST)) @@ -254,4 +256,5 @@ visible_message("\The [src] quivers slightly, then splits apart with a wet slithering noise.") - qdel(src) + if(delete_self) + qdel(src) diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 010cfae341a..54b7c322052 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -221,19 +221,7 @@ return ..() /datum/species/diona/handle_death(var/mob/living/carbon/human/H) - - var/mob/living/carbon/alien/diona/S = new(get_turf(H)) - - if(H.mind) - H.mind.transfer_to(S) - - for(var/mob/living/carbon/alien/diona/D in H.contents) - if(D.client) - D.loc = H.loc - else - qdel(D) - - H.visible_message("\red[H] splits apart with a wet slithering noise!") + diona_split_into_nymphs(0, 0) /datum/species/machine name = "Machine" From 20eb505c694fdf5342ac4bc5915aaf0230a98d3f Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 5 Nov 2015 08:46:26 +0100 Subject: [PATCH 096/207] Adds antag datum flag that is used to exlude the type from random selection. Death Commando, Mercenary Commando (inherits from death commando), and the ERT antag types added to the exclude list. Fixes #11416. --- code/game/antagonist/_antagonist_setup.dm | 1 + code/game/antagonist/antagonist_helpers.dm | 10 +++++++++- code/game/antagonist/outsider/deathsquad.dm | 2 +- code/game/antagonist/outsider/ert.dm | 2 +- code/game/gamemodes/calamity/calamity.dm | 8 +++----- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/code/game/antagonist/_antagonist_setup.dm b/code/game/antagonist/_antagonist_setup.dm index fa99f001f32..a5212256026 100644 --- a/code/game/antagonist/_antagonist_setup.dm +++ b/code/game/antagonist/_antagonist_setup.dm @@ -26,6 +26,7 @@ #define ANTAG_RANDSPAWN 256 // Potentially randomly spawns due to events. #define ANTAG_VOTABLE 512 // Can be voted as an additional antagonist before roundstart. #define ANTAG_SET_APPEARANCE 1024 // Causes antagonists to use an appearance modifier on spawn. +#define ANTAG_RANDOM_EXCEPTED 2048 // If a game mode randomly selects antag types, antag types with this flag should be excluded. // Globals. var/global/list/all_antag_types = list() diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index adc706734fd..1a3f9aa67d0 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -47,4 +47,12 @@ return 1 /datum/antagonist/proc/is_latejoin_template() - return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) \ No newline at end of file + return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB)) + +/proc/all_random_antag_types() + // No caching as the ANTAG_RANDOM_EXCEPTED flag can be added/removed mid-round. + var/list/antag_candidates = all_antag_types.Copy() + for(var/datum/antagonist/antag in antag_candidates) + if(antag.flags & ANTAG_RANDOM_EXCEPTED) + antag_candidates -= antag + return antag_candidates diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index cbb57abe1ab..e716cc72e95 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -7,7 +7,7 @@ var/datum/antagonist/deathsquad/deathsquad role_text_plural = "Death Commandos" welcome_text = "You work in the service of Central Command Asset Protection, answering directly to the Board of Directors." landmark_id = "Commando" - flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER + flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER | ANTAG_RANDOM_EXCEPTED default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage) antaghud_indicator = "huddeathsquad" diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm index 67d98f8ae5c..23e94dc24fb 100644 --- a/code/game/antagonist/outsider/ert.dm +++ b/code/game/antagonist/outsider/ert.dm @@ -9,7 +9,7 @@ var/datum/antagonist/ert/ert welcome_text = "As member of the Emergency Response Team, you answer only to your leader and CentComm officials." leader_welcome_text = "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however." landmark_id = "Response Team" - flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME + flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME | ANTAG_RANDOM_EXCEPTED antaghud_indicator = "hudloyalist" hard_cap = 5 diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm index 3104e624e34..b17277aaae9 100644 --- a/code/game/gamemodes/calamity/calamity.dm +++ b/code/game/gamemodes/calamity/calamity.dm @@ -11,19 +11,17 @@ event_delay_mod_major = 0.75 /datum/game_mode/calamity/create_antagonists() + var/list/antag_candidates = all_random_antag_types() - //Let's not modify global lists for trivial reasons, even if it seems harmless right now. - var/list/antag_candidates = all_antag_types.Copy() - var/grab_antags = round(num_players()/ANTAG_TYPE_RATIO)+1 while(antag_candidates.len && antag_tags.len < grab_antags) var/antag_id = pick(antag_candidates) antag_candidates -= antag_id antag_tags |= antag_id - + ..() /datum/game_mode/calamity/check_victory() world << "This terrible, terrible day has finally ended!" -#undef ANTAG_TYPE_RATIO \ No newline at end of file +#undef ANTAG_TYPE_RATIO From 73f99a4c018440323560b46497ba40e852f23d50 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 5 Nov 2015 08:20:34 +0100 Subject: [PATCH 097/207] Secondary diona nymphs now get non-restricted/whitelisted languages on split. --- code/modules/mob/language/language.dm | 4 +++- .../modules/mob/living/carbon/human/human_powers.dm | 13 ++++++------- .../living/carbon/human/species/station/station.dm | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index c6d9756c9b3..2d058e3b780 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -188,8 +188,10 @@ else return ..() -/proc/transfer_languages(var/mob/source, var/mob/target) +/proc/transfer_languages(var/mob/source, var/mob/target, var/except_flags) for(var/datum/language/L in source.languages) + if(L.flags & except_flags) + continue target.add_language(L.name) #undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index bcb4dd2c33b..1728b61008d 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -224,9 +224,9 @@ set name = "Split" set desc = "Split your humanoid form into its constituent nymphs." set category = "Abilities" - diona_split_into_nymphs(5, 1) // Separate proc to void argments being supplied when used as a verb + diona_split_into_nymphs(5) // Separate proc to void argments being supplied when used as a verb -/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs, var/delete_self = 1) +/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs) var/turf/T = get_turf(src) var/mob/living/carbon/alien/diona/S = new(T) @@ -242,19 +242,18 @@ for(var/mob/living/carbon/alien/diona/D in src) nymphs++ - D.loc = T + D.forceMove(T) + transfer_languages(src, D, WHITELISTED|RESTRICTED) D.set_dir(pick(NORTH, SOUTH, EAST, WEST)) if(nymphs < number_of_resulting_nymphs) for(var/i in nymphs to (number_of_resulting_nymphs - 1)) var/mob/M = new /mob/living/carbon/alien/diona(T) + transfer_languages(src, M, WHITELISTED|RESTRICTED) M.set_dir(pick(NORTH, SOUTH, EAST, WEST)) - for(var/obj/item/W in src) drop_from_inventory(W) visible_message("\The [src] quivers slightly, then splits apart with a wet slithering noise.") - - if(delete_self) - qdel(src) + qdel(src) diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 54b7c322052..9ba341ff4a1 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -221,7 +221,7 @@ return ..() /datum/species/diona/handle_death(var/mob/living/carbon/human/H) - diona_split_into_nymphs(0, 0) + H.diona_split_into_nymphs(0) /datum/species/machine name = "Machine" From 5c587e69b68195956cf6711e37dddd3de259733c Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 7 Nov 2015 17:12:50 +0100 Subject: [PATCH 098/207] Exploit fix. Players can no longer immediately respawn as mice by ghosting. --- code/modules/mob/dead/observer/observer.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f2152a2454d..63f60c6f239 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -151,6 +151,8 @@ Works together with spawning an observer, noted above. ghost.can_reenter_corpse = can_reenter_corpse ghost.timeofdeath = src.stat == DEAD ? src.timeofdeath : world.time ghost.key = key + if(ghost.client) + ghost.client.time_died_as_mouse = ghost.timeofdeath if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! return ghost From c54db5b25a55609c99dd575e61af97e539fb1239 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Sat, 7 Nov 2015 17:20:34 +0100 Subject: [PATCH 099/207] Corrects mismatched areas - Fixes #11421 --- maps/exodus-1.dmm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index 2801b367f19..10871db39c8 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -966,7 +966,7 @@ "asD" = (/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "Prison Gate"; name = "Security Blast Door"; opacity = 0},/obj/machinery/door/firedoor/border_only{dir = 2},/obj/machinery/door/airlock/glass_security{name = "Security Lobby"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor,/area/hallway/primary/fore) "asE" = (/obj/item/device/radio/intercom{pixel_x = 30},/obj/machinery/door_timer/cell_1{pixel_x = 32; pixel_y = -32},/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor{icon_state = "red"; dir = 6},/area/security/brig) "asF" = (/obj/effect/decal/cleanable/dirt,/obj/structure/bed/chair{dir = 1},/turf/simulated/floor,/area/security/prison) -"asG" = (/obj/machinery/portable_atmospherics/powered/scrubber/huge,/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor,/area/security/brig) +"asG" = (/obj/machinery/portable_atmospherics/powered/scrubber/huge,/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor,/area/security/prison) "asH" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor,/area/security/prison) "asI" = (/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/security/prison) "asJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/security/prison) @@ -4702,7 +4702,7 @@ "bMv" = (/obj/structure/bed/chair,/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/heads/cmo) "bMw" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hor) "bMx" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/airlock/command{name = "Research Director"; req_access = list(30)},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/rnd/research) -"bMy" = (/obj/machinery/hologram/holopad,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hop) +"bMy" = (/obj/machinery/hologram/holopad,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hor) "bMz" = (/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/heads/cmo) "bMA" = (/obj/machinery/hologram/holopad,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/heads/cmo) "bMB" = (/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable/green{d2 = 2; icon_state = "0-2"},/obj/structure/closet/secure_closet/CMO,/obj/item/clothing/mask/gas,/turf/simulated/floor{tag = "icon-whiteblue (EAST)"; icon_state = "whiteblue"; dir = 4},/area/crew_quarters/heads/cmo) @@ -4749,7 +4749,7 @@ "bNq" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/sign/securearea{desc = "A warning sign which reads 'SERVER ROOM'."; name = "SERVER ROOM"; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden{tag = "icon-intact (EAST)"; icon_state = "intact"; dir = 4},/turf/simulated/floor/plating,/area/server) "bNr" = (/obj/structure/closet/secure_closet/quartermaster,/turf/simulated/floor,/area/quartermaster/qm) "bNs" = (/obj/structure/table/standard,/obj/item/weapon/cartridge/signal/science,/obj/item/weapon/cartridge/signal/science{pixel_x = -4; pixel_y = 2},/obj/item/weapon/cartridge/signal/science{pixel_x = 4; pixel_y = 6},/obj/item/clothing/glasses/welding/superior,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/camera/network/research{c_tag = "Research - RD's Office"; dir = 1},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hor) -"bNt" = (/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = -24},/obj/machinery/light,/obj/structure/table/standard,/obj/machinery/photocopier/faxmachine{department = "Research Director's Office"},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hop) +"bNt" = (/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = -24},/obj/machinery/light,/obj/structure/table/standard,/obj/machinery/photocopier/faxmachine{department = "Research Director's Office"},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/crew_quarters/heads/hor) "bNu" = (/obj/structure/closet/crate,/obj/effect/decal/cleanable/cobweb,/turf/simulated/floor/plating,/area/maintenance/cargo) "bNv" = (/obj/structure/closet/crate,/turf/simulated/floor/plating,/area/maintenance/cargo) "bNw" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/cargo) From 858451365284c66d77a7972cd328b9a88fa71044 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 14 Nov 2015 00:43:11 +0100 Subject: [PATCH 100/207] Fixes the mining rig camera not properly showing up on the station camera list. Was using "Mine" instead of "MINE. Corrected by replacing all networks with the defined presets. --- code/modules/clothing/spacesuits/rig/suits/ert.dm | 2 +- code/modules/clothing/spacesuits/rig/suits/light.dm | 2 +- .../modules/clothing/spacesuits/rig/suits/station.dm | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/code/modules/clothing/spacesuits/rig/suits/ert.dm b/code/modules/clothing/spacesuits/rig/suits/ert.dm index c46b019a4d2..88c33cee261 100644 --- a/code/modules/clothing/spacesuits/rig/suits/ert.dm +++ b/code/modules/clothing/spacesuits/rig/suits/ert.dm @@ -1,6 +1,6 @@ /obj/item/clothing/head/helmet/space/rig/ert light_overlay = "helmet_light_dual" - camera_networks = list("ERT") + camera_networks = list(NETWORK_ERT) /obj/item/weapon/rig/ert name = "ERT-C hardsuit control module" diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm index 270e7a37613..3eeb7988755 100644 --- a/code/modules/clothing/spacesuits/rig/suits/light.dm +++ b/code/modules/clothing/spacesuits/rig/suits/light.dm @@ -40,7 +40,7 @@ airtight = 0 seal_delay = 5 //not being vaccum-proof has an upside I guess - + helm_type = /obj/item/clothing/head/lightrig/hacker chest_type = /obj/item/clothing/suit/lightrig/hacker glove_type = /obj/item/clothing/gloves/lightrig/hacker diff --git a/code/modules/clothing/spacesuits/rig/suits/station.dm b/code/modules/clothing/spacesuits/rig/suits/station.dm index 50a18c9ace1..e3ac8906d3c 100644 --- a/code/modules/clothing/spacesuits/rig/suits/station.dm +++ b/code/modules/clothing/spacesuits/rig/suits/station.dm @@ -1,23 +1,23 @@ /obj/item/clothing/head/helmet/space/rig/industrial - camera_networks = list("Mine") + camera_networks = list(NETWORK_MINE) /obj/item/clothing/head/helmet/space/rig/ce - camera_networks = list("Engineering") + camera_networks = list(NETWORK_ENGINEERING) /obj/item/clothing/head/helmet/space/rig/eva light_overlay = "helmet_light_dual" - camera_networks = list("Engineering") + camera_networks = list(NETWORK_ENGINEERING) /obj/item/clothing/head/helmet/space/rig/hazmat light_overlay = "hardhat_light" - camera_networks = list("Research") + camera_networks = list(NETWORK_RESEARCH) /obj/item/clothing/head/helmet/space/rig/medical - camera_networks = list("Medbay") + camera_networks = list(NETWORK_MEDICAL) /obj/item/clothing/head/helmet/space/rig/hazard light_overlay = "helmet_light_dual" - camera_networks = list("Security") + camera_networks = list(NETWORK_SECURITY) /obj/item/weapon/rig/industrial name = "industrial suit control module" From dc8b6035b5f1e2c1e473ff25270183d358926e50 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Tue, 17 Nov 2015 18:44:24 +0100 Subject: [PATCH 101/207] Maps in few extra lights - Maps in few lights to areas which are dark but probably shouldn't be (hallways, atmospherics) --- maps/exodus-1.dmm | 64 ++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index 10871db39c8..eb9ee49eca7 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -629,7 +629,7 @@ "ame" = (/turf/simulated/floor{icon_state = "redcorner"; dir = 1},/area/security/lobby) "amf" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor,/area/security/lobby) "amg" = (/turf/simulated/floor,/area/security/lobby) -"amh" = (/obj/item/device/radio/intercom{pixel_x = 27},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{icon_state = "redcorner"; dir = 4},/area/security/lobby) +"amh" = (/obj/item/device/radio/intercom{pixel_x = 27},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor{icon_state = "redcorner"; dir = 4},/area/security/lobby) "ami" = (/turf/simulated/wall,/area/lawoffice) "amj" = (/obj/structure/table/reinforced,/obj/item/device/flashlight/lamp,/turf/simulated/floor{icon_state = "cult"; dir = 2},/area/lawoffice) "amk" = (/obj/structure/table/reinforced,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/hand_labeler,/obj/item/weapon/pen,/turf/simulated/floor{icon_state = "cult"; dir = 2},/area/lawoffice) @@ -1189,7 +1189,7 @@ "awS" = (/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/blood/oil,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 8},/area/maintenance/evahallway) "awT" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "eva_inner"; locked = 1; name = "EVA Internal Access"; req_access = list(13)},/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor/plating,/area/maintenance/evahallway) "awU" = (/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/carpet{tag = "icon-carpet3-0"; icon_state = "carpet3-0"},/area/crew_quarters/sleep/bedrooms) -"awV" = (/turf/simulated/floor{icon_state = "redcorner"; dir = 1},/area/hallway/primary/fore) +"awV" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor{icon_state = "redcorner"; dir = 1},/area/hallway/primary/fore) "awW" = (/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 31},/turf/simulated/floor{icon_state = "redcorner"; dir = 4},/area/hallway/primary/fore) "awX" = (/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/crew_quarters/fitness) "awY" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/sleep/bedrooms) @@ -1495,7 +1495,7 @@ "aCM" = (/turf/simulated/wall/r_wall,/area/storage/primary) "aCN" = (/obj/structure/closet/secure_closet/freezer/money,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/security/nuke_storage) "aCO" = (/obj/machinery/light_switch{pixel_y = 28},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/turf/simulated/floor{icon_state = "vault"; dir = 6},/area/security/nuke_storage) -"aCP" = (/obj/machinery/light/small{dir = 1},/obj/machinery/alarm{pixel_y = 23},/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor{icon_state = "vault"},/area/security/nuke_storage) +"aCP" = (/obj/machinery/alarm{pixel_y = 23},/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/machinery/light{dir = 1},/turf/simulated/floor{icon_state = "vault"},/area/security/nuke_storage) "aCQ" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/turf/simulated/floor{icon_state = "vault"; dir = 10},/area/security/nuke_storage) "aCR" = (/obj/machinery/computer/secure_data/detective_computer,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/security/nuke_storage) "aCS" = (/obj/machinery/gateway{dir = 10},/obj/effect/landmark{name = "JoinLateGateway"},/turf/simulated/floor{icon_state = "vault"; dir = 4},/area/gateway) @@ -1953,7 +1953,7 @@ "aLC" = (/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"; dir = 8},/turf/space,/area/shuttle/arrival/station) "aLD" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) "aLE" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/hallway/secondary/entry/port) -"aLF" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/turf/simulated/floor{icon_state = "neutralcorner"; dir = 2},/area/hallway/secondary/entry/starboard) +"aLF" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/machinery/light,/turf/simulated/floor{icon_state = "neutralcorner"; dir = 2},/area/hallway/secondary/entry/starboard) "aLG" = (/turf/simulated/floor{icon_state = "neutral"},/area/hallway/secondary/entry/starboard) "aLH" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor{icon_state = "neutral"},/area/hallway/secondary/entry/starboard) "aLI" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{dir = 8; icon_state = "neutralcorner"},/area/hallway/secondary/entry/starboard) @@ -2210,7 +2210,7 @@ "aQz" = (/obj/structure/bed/chair/comfy/brown{dir = 1},/turf/simulated/floor{icon_state = "cult"; dir = 2},/area/library) "aQA" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/table/reinforced,/obj/machinery/chemical_dispenser/bar_alc/full,/turf/simulated/floor{icon_state = "grimy"},/area/crew_quarters/bar) "aQB" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) -"aQC" = (/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) +"aQC" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) "aQD" = (/obj/machinery/vending/snack,/turf/simulated/floor{dir = 9; icon_state = "warning"},/area/hallway/secondary/entry/port) "aQE" = (/obj/structure/extinguisher_cabinet{pixel_x = -27; pixel_y = 1},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/machinery/camera/network/civilian_east{c_tag = "Hydroponics Pasture West"; dir = 4},/turf/simulated/floor{dir = 9; icon_state = "green"},/area/hydroponics) "aQF" = (/obj/structure/closet/emcloset,/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/hallway/secondary/entry/port) @@ -2320,7 +2320,7 @@ "aSF" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/blast/shutters{dir = 8; id = "office_shutter"; layer = 3.1; name = "Office Shutters"},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "aSG" = (/obj/structure/table/reinforced,/obj/machinery/door/firedoor/border_only,/obj/machinery/door/blast/shutters{dir = 2; id = "kitchen"; layer = 3.3; name = "Kitchen Shutters"},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/hallway/primary/starboard) "aSH" = (/obj/item/weapon/material/hatchet,/obj/item/weapon/material/minihoe,/obj/structure/table/standard{name = "plastic table frame"},/turf/simulated/floor{icon_state = "green"; dir = 8},/area/hydroponics) -"aSI" = (/obj/machinery/camera/network/exodus{c_tag = "Arrivals Southwest"},/turf/simulated/floor,/area/hallway/secondary/entry/port) +"aSI" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/light,/turf/simulated/floor,/area/hallway/primary/port) "aSJ" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/primary/central_two) "aSK" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/primary/central_two) "aSL" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only{dir = 2},/turf/simulated/floor/plating,/area/hallway/primary/central_two) @@ -2372,7 +2372,7 @@ "aTF" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; icon_state = "intact"; tag = "icon-intact-f (SOUTHWEST)"},/turf/simulated/floor,/area/hallway/secondary/entry/port) "aTG" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) "aTH" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/plating,/area/hallway/secondary/entry/port) -"aTI" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "neutralcorner"; dir = 4},/area/hallway/secondary/entry/starboard) +"aTI" = (/obj/machinery/camera/network/exodus{c_tag = "Arrivals Southwest"},/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/hallway/secondary/entry/port) "aTJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/hallway/secondary/entry/starboard) "aTK" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/hallway/secondary/entry/starboard) "aTL" = (/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/hallway/secondary/entry/starboard) @@ -2387,9 +2387,9 @@ "aTU" = (/turf/simulated/floor,/area/crew_quarters/locker) "aTV" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor,/area/crew_quarters/locker) "aTW" = (/obj/structure/reagent_dispensers/fueltank,/obj/machinery/light_switch{pixel_y = 28},/turf/simulated/floor,/area/crew_quarters/locker) -"aTX" = (/obj/machinery/vending/cola,/turf/simulated/floor,/area/crew_quarters/locker) +"aTX" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/light{dir = 1},/turf/simulated/floor{icon_state = "neutralcorner"; dir = 4},/area/hallway/secondary/entry/starboard) "aTY" = (/obj/structure/disposalpipe/segment,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor,/area/crew_quarters/locker) -"aTZ" = (/obj/machinery/vending/coffee,/turf/simulated/floor,/area/crew_quarters/locker) +"aTZ" = (/obj/machinery/vending/cola,/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/crew_quarters/locker) "aUa" = (/obj/machinery/vending/snack,/turf/simulated/floor,/area/crew_quarters/locker) "aUb" = (/obj/machinery/vending/cigarette,/turf/simulated/floor,/area/crew_quarters/locker) "aUc" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor,/area/crew_quarters/locker) @@ -2857,7 +2857,7 @@ "bcW" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor{dir = 1; icon_state = "green"},/area/hydroponics/garden) "bcX" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/hydroponics/garden) "bcY" = (/obj/structure/flora/ausbushes,/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/grass,/area/hydroponics/garden) -"bcZ" = (/obj/machinery/embedded_controller/radio/airlock/docking_port{frequency = 1380; id_tag = "centcom_shuttle_dock_airlock"; pixel_x = 0; pixel_y = 30; req_one_access = list(13); tag_airpump = "centcom_shuttle_dock_pump"; tag_chamber_sensor = "centcom_shuttle_dock_sensor"; tag_exterior_door = "centcom_shuttle_dock_outer"; tag_interior_door = "centcom_shuttle_dock_inner"},/obj/machinery/airlock_sensor{frequency = 1380; id_tag = "centcom_shuttle_dock_sensor"; pixel_x = 0; pixel_y = -25},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1380; id_tag = "centcom_shuttle_dock_pump"},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) +"bcZ" = (/obj/machinery/vending/coffee,/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/crew_quarters/locker) "bda" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor,/area/hallway/primary/starboard) "bdb" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor,/area/hallway/primary/starboard) "bdc" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/machinery/door/airlock/glass{name = "Library"},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/carpet,/area/hallway/primary/starboard) @@ -3007,7 +3007,7 @@ "bfQ" = (/obj/structure/sign/double/barsign,/turf/simulated/wall,/area/hallway/primary/starboard) "bfR" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 0},/turf/simulated/wall,/area/hallway/primary/starboard) "bfS" = (/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard) -"bfT" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/unary/vent_pump/on,/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard) +"bfT" = (/obj/machinery/embedded_controller/radio/airlock/docking_port{frequency = 1380; id_tag = "centcom_shuttle_dock_airlock"; pixel_x = 0; pixel_y = 30; req_one_access = list(13); tag_airpump = "centcom_shuttle_dock_pump"; tag_chamber_sensor = "centcom_shuttle_dock_sensor"; tag_exterior_door = "centcom_shuttle_dock_outer"; tag_interior_door = "centcom_shuttle_dock_inner"},/obj/machinery/airlock_sensor{frequency = 1380; id_tag = "centcom_shuttle_dock_sensor"; pixel_x = 0; pixel_y = -25},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1380; id_tag = "centcom_shuttle_dock_pump"},/obj/machinery/light/small,/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "bfU" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard) "bfV" = (/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard) "bfW" = (/obj/item/weapon/folder/yellow,/obj/structure/table/standard{name = "plastic table frame"},/turf/simulated/floor,/area/security/vacantoffice) @@ -3226,7 +3226,7 @@ "bkb" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 8},/turf/simulated/floor,/area/hallway/primary/central_two) "bkc" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor,/area/hallway/primary/central_two) "bkd" = (/obj/machinery/door/airlock/glass{name = "Central Access"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor,/area/hallway/primary/starboard) -"bke" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor,/area/hallway/primary/starboard) +"bke" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/unary/vent_pump/on,/obj/machinery/light{dir = 1},/turf/simulated/floor{dir = 1; icon_state = "whitecorner"},/area/hallway/primary/starboard) "bkf" = (/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -30},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor,/area/hallway/primary/starboard) "bkg" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -29},/turf/simulated/floor,/area/hallway/primary/starboard) "bkh" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/turf/simulated/floor,/area/hallway/primary/starboard) @@ -3291,7 +3291,7 @@ "blo" = (/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/embedded_controller/radio/docking_port_multi{child_names_txt = "Airlock One;Airlock Two"; child_tags_txt = "escape_dock_north_airlock;escape_dock_south_airlock"; frequency = 1380; id_tag = "escape_dock"; pixel_x = 0; pixel_y = -25; req_one_access = list(13)},/turf/simulated/floor{dir = 2; icon_state = "warning"},/area/hallway/secondary/exit) "blp" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area/hallway/primary/central_one) "blq" = (/turf/simulated/floor{dir = 8; icon_state = "browncorner"},/area/hallway/primary/central_one) -"blr" = (/obj/machinery/embedded_controller/radio/airlock/docking_port{frequency = 1380; id_tag = "specops_dock_airlock"; pixel_x = 0; pixel_y = 30; req_one_access = list(13); tag_airpump = "specops_dock_pump"; tag_chamber_sensor = "specops_dock_sensor"; tag_exterior_door = "specops_dock_outer"; tag_interior_door = "specops_dock_inner"},/obj/machinery/airlock_sensor{frequency = 1380; id_tag = "specops_dock_sensor"; pixel_x = 0; pixel_y = -25},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1380; id_tag = "specops_dock_pump"},/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) +"blr" = (/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/hallway/primary/starboard) "bls" = (/obj/machinery/requests_console{announcementConsole = 1; department = "Bridge"; departmentType = 5; name = "Bridge RC"; pixel_y = -30},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/wood,/area/bridge/meeting_room) "blt" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/carpet,/area/bridge/meeting_room) "blu" = (/obj/machinery/computer/security/telescreen/entertainment{pixel_x = 0; pixel_y = -32},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/carpet,/area/bridge/meeting_room) @@ -6695,7 +6695,7 @@ "cyM" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/visible/green,/turf/simulated/floor,/area/engineering/atmos) "cyN" = (/obj/machinery/atmospherics/trinary/mixer,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) "cyO" = (/mob/living/simple_animal/mouse,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator) -"cyP" = (/obj/machinery/atmospherics/binary/pump{dir = 8; name = "Port to Waste"},/turf/simulated/floor,/area/engineering/atmos) +"cyP" = (/obj/machinery/door/firedoor/border_only{dir = 8; name = "Firelock West"},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/light,/turf/simulated/floor,/area/hallway/primary/starboard) "cyQ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/rnd/docking) "cyR" = (/obj/machinery/atmospherics/pipe/manifold/visible/red{tag = "icon-map (WEST)"; icon_state = "map"; dir = 8},/turf/simulated/floor,/area/engineering/atmos) "cyS" = (/obj/machinery/atmospherics/pipe/manifold4w/visible,/turf/simulated/floor,/area/engineering/atmos) @@ -6857,6 +6857,7 @@ "cBS" = (/obj/machinery/atmospherics/binary/pump{dir = 4; name = "Mixing to Port"},/turf/simulated/floor,/area/engineering/atmos) "cBT" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor,/area/engineering) "cBU" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor,/area/engineering) +"cBV" = (/obj/machinery/embedded_controller/radio/airlock/docking_port{frequency = 1380; id_tag = "specops_dock_airlock"; pixel_x = 0; pixel_y = 30; req_one_access = list(13); tag_airpump = "specops_dock_pump"; tag_chamber_sensor = "specops_dock_sensor"; tag_exterior_door = "specops_dock_outer"; tag_interior_door = "specops_dock_inner"},/obj/machinery/airlock_sensor{frequency = 1380; id_tag = "specops_dock_sensor"; pixel_x = 0; pixel_y = -25},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1380; id_tag = "specops_dock_pump"},/obj/machinery/light/small,/turf/simulated/floor/plating,/area/hallway/secondary/entry/aft) "cBW" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) "cBX" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) "cBY" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/maintenance/engi_shuttle) @@ -7391,6 +7392,11 @@ "cMh" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 8},/area/maintenance/engi_engine) "cMi" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/engi_engine) "cMj" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/mob/living/simple_animal/mouse,/turf/simulated/floor/plating,/area/maintenance/engi_engine) +"cMk" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock East"},/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/hallway/primary/central_three) +"cMl" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor{dir = 8; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"cMm" = (/obj/structure/table/standard,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor,/area/engineering/locker_room) +"cMn" = (/turf/simulated/wall,/area/engineering/atmos) +"cMo" = (/obj/machinery/atmospherics/binary/pump{dir = 8; name = "Port to Waste"},/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/engineering/atmos) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7498,7 +7504,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaynayoaypayoazUayoayrayoaAbaytayvayvayvayvaywauNawNatqaaaaafaafaaaaaaaaaaaaaafaaaayyaBkayyaafaaaaafaaaaaaaaaaaaaaaanXayBayCayDayCayCayCayCayEayCayCayFayGayDaBRayIaxMaxMaxMaxMaxMaxMayJayKayLayLayLayLayMayLayLaArayLayMayLayLayLarAaAtayPayQarEaAiasZcfSaycaxUatCayUayTayWaAvayYayXayYaAHayTazaazbazcazdazeazdazdazfaxraAWaxtaxTaxvatRatRatRatRatRatRatRatRatRatRavcaafaaaaaaaaaaaaaaaaaaaaaaaaaafaafaBuaBvaBaaBxaByaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazqazrazsaztazuazvazwazxazyazwazzazAazwazwaBcauNavHauRaafaafaaaaaaaaaaaaaaaaafazDazEaCiaCeazHaaaaafaaaaaaaaaaaaaaaanXazIanXazJazKazLazLazLazMazLazLazLazNazJazOazPazPazPazPazPazPazPazQazRayLazSazTaBwazVazWazXazYazZaAaaBEazTaAcarAaAdayPayQarEaAiasZaBOaAeawgatCaxWaxXaxXaxXaxXazBaBQaAlaAmaAnaxkaAoaylaApaApaApaAqayVatPayZatPatPatRatRatRatRatRatRatRatRatRatRavcaafaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaCvaCwaCpaCyaCvaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafauNaAwaAxaAwaAyazsazsaAzaAwaAxaAwaAAaABaACaADauNavHauQauQaAEauUauUauUauUauVauQaAFaAGaDAaCIaAFanXanXaxHaAJaxIanXanXanXazIaAKazJaaaaafaaaaafaaaaafaaaaafaaaazJazOazPaALaAMaANaAOaAPazPazQaucayLaAQaAQaARaASaATaAUaAVaATaCtaAXazTaAcarAaAdayPaDdarEaAiasZaxGaAgaAhaBbayRaBdaBeazhaBgaBhaBiaBjaBjaCDaBjatPaBlaBmaBnaBoaBpaBraxvaziaCJaCHatRatRatRatRatRatRatRatRatRatRavcaafaaaaaaaaaaaaaaaaacaaaaaaaafaaaaCvazlaECaDBaCvaaaaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaBzatSaBAawHaBBaBCaBDaCLaBFaBBawHaBGaBHaBIaBJaBKaBLavHavHavHavHavHavHavHavHaDcaBPaAFazmaESaBSaAFaBTaBUayCayCayCayCayCaBVaBWaBXazJaafaBYaBYaBYaBYaBYaBYaBYaafazJazOazPaBZaCaaCbaCcaBZazPazQaCdayLayLayLayLaDnaCfaCgaChaCfaDoaCjazTaCkarAaAdayPaClarEaJCasZaDtaAYaDxatCaxWavqatEaBjaBjaBjaBjaBjaCqaCraCsaBjatPatPatPatPaDyatPatPaAfaAkaDQatRatRatRatRatRatRatRatRatRatRaumaafaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaCvaEXaEYaDYaCvaaaaaaaaaaafaafaaaaaaaaaaaaaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaBzatSaBAawGaBBaBCaBDaCLaBFaBBawGaBGaBHaBIaBJaBKaBLavHavHavHavHavHavHavHavHaDcaBPaAFazmaESaBSaAFaBTaBUayCayCayCayCayCaBVaBWaBXazJaafaBYaBYaBYaBYaBYaBYaBYaafazJazOazPaBZaCaaCbaCcaBZazPazQaCdayLayLayLayLaDnaCfaCgaChaCfaDoaCjazTaCkarAaAdayPaClarEaJCasZaDtaAYaDxatCaxWavqatEaBjaBjaBjaBjaBjaCqaCraCsaBjatPatPatPatPaDyatPatPaAfaAkaDQatRatRatRatRatRatRatRatRatRatRaumaafaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaCvaEXaEYaDYaCvaaaaaaaaaaafaafaaaaaaaaaaaaaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazqaAxaCzaCAaCAaCAaCAaCBaAxazqaaaaBIaCCaxzaBLaCEaCEaCEaCEaCEaCEaCEavHaCFaCGaAFaEcaFzaAsaAFaCKaEdaCKaCKaCKaCKaCKaCKaCKaCKaCMaaaaBYaCNaCOaCPaCQaCRaBYaaaazJazOazPaBZaCSaCTaCUaBZazPazQanXayLaCVaCWaARaCXaCYaCZaDaaDbaEeayLayLayLarAaAdayPayQarEaAiasZaEgaEfawgatCaDgavqatEaDhaDiaDjaDkaBjaCqaDlaCsaBjaDmaEhaEvaDpaDqaGwaDsatPatPatPaAZatjatjatjatjaEzatjatjatjatjaBfaafaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaCvaCvbhYaGyaCvaDCaDDaDEaDCaDCaDCaDCaDCaDCaDCaDFaDGaDGaDGaDHaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaaaaaaaDIaDJaDKaDJaDJaDLaDMaDJaDJaDKaDNaDOaBIaDPaEMaBLaDRaDSaDTaDUaDVaDWaCEavHaDXauQaAFaAFbjraDZaCMaEaaEbaEVaFnaFhaFyaFqaFEaEiaEjaCMaafaBYaEkaElaEmaEnaEoaBYaafazJazOazPaEpaEqaEraEsaEtazPazQaEuayLazSazTaFGaEwaCfaExaEyaATaFIaEAaEBaEBarAaAdayPayQarEaAiaCmaCmaCmaCmaCmaEHaEIatEaEJaEKaEKaELaFSaEKaENaEOaBjaEPaEQaERaFZaETaCnaDsaaaaafaafaafaaaaaaaafaafaafaafaaaaaaaafaafaafaaaaaaaaaaaaaaaaaaaaaaDCaBsaBqaDCaBtbnKaGfaFdaFdaFdaFdaFeaFfaFgaFgaFgaFgaFgaFgaFgaGkaFiaFjaafaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaDIaDNaDJaFkaGqaFlaFmaGraFoaFpaGxaFlaGHaFraFsaFtaDPayuaBLaFvayxaBMaCxaBMaBNaGPavHaFuaGVaFxaHcbnLaDfaHdaFJaFKaFLaFLaFLaDraFLaFLaFNaFOaCMaaaaBYaHIaElaFQaEnaFRaBYaaaazJazOazPaHJaFTaFUaFTaFVazPazQaFWayLayLayLayLaFXaCfaCgazTaCfaFYaHYazTaGaarAaGbaGcaGdarEaAiaDeaDvaDuaCoaDeaIcaDzaIhaGlaGmaBjaBjaBjaBjaBjaBjaGnaGoaGpaIkaDpaInaIlaDsaDsaDsaDsaDsaDsaDsaDsaDsaFaaFbaDsaDsaFaaGtaDsaDsaaaaaaaDsaDCaDCaDCaDCaEZaEWaFdaFcaFwaDCaDCaDCaDCaDCaGDaGEaGFaGFaGFaGFaGFaGFaGGaGGaIzaGGaGGaGGaGGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7508,20 +7514,20 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaLyaLzaDJaFkaGqaFlaFlaNGaFlaFlaNPaFlaGHaFraLCaLDaDPaLEaLFaLGaLHaLGaLGaLGaLGaLGaLIaLJaFCaFCaFCaFCaFCaFCaLLaLMaLNaLOaLOaLOaLOaLPaLQaLRaKuaLSaLTaLTaLUaLVaLWaLTaLTaLXaKuaNXaKuaKuaLZaMaaLZaJeaJeaMbaOiaJeaJeaJeaJeaMdaMeaOpaOoaMhaMiaJeaJeaJeaJeaMjaKNaMkaMkaMlaMmaMnaMoaJlaMpaLqaLnaJlaJlaJlaJlaJlaJlaJlaJlaBjaBjaMsaMtaMuaOqaOsaLvaMyaMfaKZaMAaMBaMCaMCaMDaLfaOCaOHaMGaMHaMIaMJaMKaMLaMMaMNaMHaMJaMIaMHaMOaLfaJRaIgaMPaMgaMRaMSaMqaMUaIgaOMaMWaPiaMYaMraNaaNbaGFaGGaQaaJVaIoaMxaQcaNfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaaaaaaaLyaDJaDKaDJaDJaDLaDMaDJaDJaDKaLzaNgaBIaNhaLEaNiaMzaMzaNkaMzaNlaIAaNmaNnaLJaNoaNpaNqaNraNsaNtaNraNuaNraNraNraNvaNraNraNwaNxaNyaNzaNzaNBaQdaNCaNzaNzaNzaNzaNDaNEaNFaQgaNraNHaNIaNJaNKaNLaNMaNLaNNaNOaQlaNQaNQaNRaNSaNTaNSaNUaNVaNWaEGaNYaNZaOaaObaOcaMkaMkaMkaOdaOeaMTaMQaOhaQqaOjaOkaOlaOmaOnaJlaQyaQxaQAaOraOtaOtaOuaMZaOwaNdaKZaOyaOzaOAaOAaOBaLfaQEaODaOEaOEaOEaOEaOFaOGaQJaOIaOJaOKaOKaOLaQTaLfaJRaIgaONaOOaNjaOfaONaONaIgaORaOSaGFaOTaOUaOVaOWaGFaIoaIoaJVaIoaGGaGGaGGaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaOXaOYaOZaPaaPaaPaaPaaPbaOYaOXaaaaBIaPcaPdaPeaOvaOgaPhaPhaOxaIAaPjaNnaPkaPlaPmaPnaPoaPpaPqaPqaPraPsaPsaPsaPtaPuaPuaPvaPwaNIaPqaPqaPxaPyaPzaPAaPBaPBaPCaPBaPDaPyaPyaPyaPEaPFaPGaPHaMkaPIaPJaPJaPJaPJaPJaPJaPJaPJaPKaPJaPLaPMaPNaPOaPPaPQaPRaPSaPTaPJaPUaPJaPVaPWaPXaPWaPWaPWaPWaPWaPWaPYaPZaRsaQbaQbaQbaRbaQbaQbaRraQeaQfaRxaKZaQhaMCaQiaQjaQkaLfaRyaQmaQnaQnaQnaQnaQnaQoaQpaOPaQraQnaQnaQsaQtaLfaJRaIgaQuaONaONaQvaONaQwaIgaGFaGFaGFaGFaGFaGFaRCaGFaIoaIoaJVaIoaSoaOQaGGaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaafaBIawqaBIaQBaQCaGOaQDaStaQFaQGaGOaQCaQHaQIaBIaSuaLEaPeaPfaQLaPhaPhaOxaIAaQMaNnaLJaQNaNpaQOaQPaNraNraQQaQRaQSaSvaNraQUaQVaQWaQVaQXaQYaQVaQVaQZaQVaQVaRaaSyaQVaRcaQVaRdaNraNraNraReaPFaPGaPHaMkaRfaMkaRgaRgaRgaRgaRgaRgaRgaRgaRhaRiaRgaRjaRgaRgaRkaRgaRgaRgaRgaRlaRmaRnaRoaRoaRoaRoaRoaRoaRoaRpaRqaRpaJlaImawOawOawOawOawOaItaRuaRvaRwaKZaKZaKZaKZaKZaSEaLfaSHaQmaQnaRzaRAaRBaPgaRDaREaRFaQraRGaRHaRIaRJaLfaJRaIgaRKaRKaRLaRMaRNaRNaROaIgaRPaRQaRRaGGaRSaRTaRUaRVaRVaRWaRXaGGaRYaGGaRZaRZaRZaSaaSbaScaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaGeaGgaGgaGiaSIaGhaSdaOYaLDaDPaHxaHxaSfaLDaOYaLDaHyaHAaHzaLEaSkaSUaSUaNkaSUaNlaIAaSmaNnaSnaIAaLKaLKaSVaLKaLKaLKaLKaLKaLKaSpaSqaLKaLKaLKaLKaLKaLKaSraSsaSraLKaSZaLKaNraQPaTPaUfaSwaSxaNraReaUjaMbaMbaMkaSzaKOaSAaMnaMnaSBaSBaSBaSBaSCaJeasfasNarVarXarXavParXarXarVasNawFaJeaSJaSKaSKaSKaSKaSLaSLaSMaSNaRqaRpaJlaUxaUlaUlaUlaUlaUlaUlaSQaSRaSSaSTaUJaUOaSWaSXaSYaKZaKZaURaTaaTbaTcaTdaTeaTeaTeaTfaTgaTfaTeaTeaTeaTeaJRaIgaThaONaRLaRMaONaONaTiaIgaTjaQzaTlaGGaIoaTmaTnaToaTpaTqaIoaTraQKaGGaTtaTuaRZaTvaTwaTxaafaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaUSaVeaUVaVkaVfaSgaSeaSiaShaSjaSiaTzaTyaTBaTAaTEaTCaTAaTFcozaTIaTJaTKaTLaTLaTLaTMaTLaTNaTOaIAaVraTQaTRaTSaTTaTUaTVaTWaTXaTUaTYaTZaUaaUbaUcaUdaUeaVzaUgaUhaUeaUiaLKaLKaVIaLKaLKaLKaLKaUkaVLaLKaUmaMbaUnaSzaKOaUoaaaaaaaaaaaaaaaaaaaaaaUpaUqaUraUsaUtaUvaUuaVPaUwaUzaUyaVUaUpaaaaaaaaaaaaaaaaaaaaaaUAaSNaRqaUBaUCaUDaUEaUFaUFaUFaUFaUGaUHaUIaUFaUFaUFaWdaUKaULaUMaUNaWjaUPaUQaWnaWkaUTaTfaUUaWoaWwaUXaUYaUZaVaaVbaTeaJRaIgaVcaVcaRLaRMaVdaVdaWyaIgaIgaWFaIgaGGaVgaVhaViaViaViaVjaWKaGGaGGaGGaVlaVmaVnaVoaVpaVqaafaafaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaafaBIawqaBIaQBaQCaGOaQDaStaQFaQGaGOaQCaQHaQIaBIaSuaLEaPeaPfaQLaPhaPhaOxaIAaQMaNnaLJaQNaNpaQOaQPaNraNraQQaQRaQSaSvaNraQUaQVaQWaQVaQXaQYaQVaQVaQZaQVaQVaRaaSyaQVaRcaQVaRdaNraNraNraReaSIaPGaPHaMkaRfaMkaRgaRgaRgaRgaRgaRgaRgaRgaRhaRiaRgaRjaRgaRgaRkaRgaRgaRgaRgaRlaRmaRnaRoaRoaRoaRoaRoaRoaRoaRpaRqaRpaJlaImawOawOawOawOawOaItaRuaRvaRwaKZaKZaKZaKZaKZaSEaLfaSHaQmaQnaRzaRAaRBaPgaRDaREaRFaQraRGaRHaRIaRJaLfaJRaIgaRKaRKaRLaRMaRNaRNaROaIgaRPaRQaRRaGGaRSaRTaRUaRVaRVaRWaRXaGGaRYaGGaRZaRZaRZaSaaSbaScaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaGeaGgaGgaGiaTIaGhaSdaOYaLDaDPaHxaHxaSfaLDaOYaLDaHyaHAaHzaLEaSkaSUaSUaNkaSUaNlaIAaSmaNnaSnaIAaLKaLKaSVaLKaLKaLKaLKaLKaLKaSpaSqaLKaLKaLKaLKaLKaLKaSraSsaSraLKaSZaLKaNraQPaTPaUfaSwaSxaNraReaUjaMbaMbaMkaSzaKOaSAaMnaMnaSBaSBaSBaSBaSCaJeasfasNarVarXarXavParXarXarVasNawFaJeaSJaSKaSKaSKaSKaSLaSLaSMaSNaRqaRpaJlaUxaUlaUlaUlaUlaUlaUlaSQaSRaSSaSTaUJaUOaSWaSXaSYaKZaKZaURaTaaTbaTcaTdaTeaTeaTeaTfaTgaTfaTeaTeaTeaTeaJRaIgaThaONaRLaRMaONaONaTiaIgaTjaQzaTlaGGaIoaTmaTnaToaTpaTqaIoaTraQKaGGaTtaTuaRZaTvaTwaTxaafaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaUSaVeaUVaVkaVfaSgaSeaSiaShaSjaSiaTzaTyaTBaTAaTEaTCaTAaTFcozaTXaTJaTKaTLaTLaTLaTMaTLaTNaTOaIAaVraTQaTRaTSaTTaTUaTVaTWaTZaTUaTYbcZaUaaUbaUcaUdaUeaVzaUgaUhaUeaUiaLKaLKaVIaLKaLKaLKaLKaUkaVLaLKaUmaMbaUnaSzaKOaUoaaaaaaaaaaaaaaaaaaaaaaUpaUqaUraUsaUtaUvaUuaVPaUwaUzaUyaVUaUpaaaaaaaaaaaaaaaaaaaaaaUAaSNaRqaUBaUCaUDaUEaUFaUFaUFaUFaUGaUHaUIaUFaUFaUFaWdaUKaULaUMaUNaWjaUPaUQaWnaWkaUTaTfaUUaWoaWwaUXaUYaUZaVaaVbaTeaJRaIgaVcaVcaRLaRMaVdaVdaWyaIgaIgaWFaIgaGGaVgaVhaViaViaViaVjaWKaGGaGGaGGaVlaVmaVnaVoaVpaVqaafaafaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaXdcmVaXhaXiaDPaVsaVsaVtaVsaVsaVsaVDaVsaVsaVtaVsaVsaYEaWYaVuaVvaKdaKdaKdaKdaKdaVwaVxaVyaXjaIAaTQaTQaVAaTSaVBaTUaTUaTUaTUaTUaTYaVCaTUaTUaTUaUdaUeaXkaVEaVFaUeaUiaVGaVHaKeaKcaVKaUmaXlaVMaVNaVOaXmaVQaMkaSzaKOaUoaaaaaaaaaaaaaUpaUpaUpaUpaVRaSlaVTaXEaVVaSDaVXaXFaVZaSOaWbaUpaUpaUpaUpaaaaaaaaaaaaaUAaSNaRqaRpaWcaSSaSPaWeaTkaSSaTsaUWaWiaVSaXnaVWaWmaXoaQbaXuaWpaWqaWraWsaWtaWtaWuaWvaXwaWaaXzaXCaWAaWBaWCaWDaWEaTeaJRaIgaThaONaRLaRMaONaONaONaXGaWGaONaWHaGGaWIaWJaToaToaToaTqaIoaYsaGGaWfaVoaLuaWQaVoaWRaWSaWTaWTaWUaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTGaGgaTHaGiaBIaBIaBIaWVaWWaWWaWWaWWaWWaWWaWWaWXaBIaBLcpSaWZaIAaXcaXbaXbaXbaYraXIaIAaIAaIAaIAaTQaXeaXfaTSaXgaTUaTUaWgaXOaXNaXTaXRaTUaTUaTUaXWaUeaXXaXZaXYaUeaUiaVGaXpaKfaXraXsaUmaXtaXmaYeaXvaYfaXxaMkaSzaKOaMmaSCaMbaXyaUpaUpaVYaXAaYkaYqaXDaXDaXEaXFaYwaXEaXFaXDaXDaXHaYxaXJaXBaUpaUpaXyaJlaXLaXMaSNaRqaRpaJlaYyaSPaYAaTkaSSaXPaXQaSSaWhaXSaTkaSSaYGaOtaXUaXVaUQaYHaYKaYJaYMaYaaYbaYcaYdaWoaYNaYgaWBaYhaWDaYiaTeaJRaIgaYjaYjaRLaRMaWlaONaONaYlaONaWzaWxaGGaIoaYVaYUaToaYXaZeaZXaWLbaOaYmaWOaZcaVoaYvaZgaZnaZhaYzaZraIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaafaYCaYDcpKaYFaWPaZsaZsaYIaZtaZuaYLbacaZYaYOaYPaYQaYRaYSaTSaYTaTUaTUaWgaXNbafbanaWgaTUaTUaYWaUdaUeaUeaUeaUeaUeaUiaVGaVGaVGaVGaVGaUmaYYaXvaYZaXvaXvaXxaMkaSzaKOaNSaNSaZaaZbaWNaUpaZdaYnaZfbaCbaBbaPbaNbaTbaSbaVbaUbaXbaWbaYaZfaYoaZjaUpaWMaZbaZlaZmbaZaSNaRqaRpaWcaSSaSSaSSaSSaSSaXPaZoaSSaWhaZpaTkaSSaYGaOtaZqaXVaUQbbabbcbbbbbeaYaaYpaZwaYdaWoaYNaYgaWBaYhaZxaZyaZzbbfaZzaZzaZzaZBaZCaZDaYtaOOaZFaZGaZHaZIaGGaZJbbtbbhaTobbxbbhaIoaIoaXaaZiaVoaYuaVoaZNaZOaZPaZQaWTaZRaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaZSaZTaZUbjnaZWaSFaZsaZkbaaaZvbbzbadbaebbAaYObagbahbaibajaTSbakbalbambbDbaobapbaqbarbarbarbasbataTSbaubavbawbaxaKgbajbnZaKhbajbbLaUmbaDbaEbaFbaGbaHbaIaMkbaJbaKaMkbaLbaMbbPbcybbRbbQbaRbaQbbSaUpaUpaUpaUpaUpbcDaUpaUpaUpbbTbaQbbdbbWbcabeobcubbibbjbbkbblbbmbbnaJlaUDaSPbboaTkaSSaZAaZEbbraZKaYAaTkaSSaYGbcBaULaXVbbubbvbbwaUQaUQaYabcCbbybcFbcEbbBaYgaWBbbCaWDbcPaZzaZLbbFbbFbbGbbHbbIaRLaRLaRLaRLaRLaRLaRLaGGbbJaYVaYUaToaYXaYUaIobbKaGGbcTaVoaYuaVoaZNbbMbbNbbOaafaafaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBbdtbcZbdHbdzbbUaSFbaabaabaabaabaabbVbaabdKaYObbXbbYbaibbZbbZbbZbbZbdQbbZbcbaTUbccbcdbcebcebcfbcgaTSaXebchbcibcjaKibeablcaKkbcobcobcpbcpbcpbcpbcpbcqaMbbcrbcsbctbeebcvbcwbcxbbgaUpbczbcAbekaUpaUpaaaaaaaafaafbezaaaaaaaUpaUpbeBbcGbczaUpbbgbcxbcHbcIbcJbcKbcLaRpaWcaSSaSSaSSaSSaSSaGpbcMaSSbcNaSSaSSaSSaSSaSSbeMbcQbcRbcSaUQaUQaUQbeNbcUaTeaZMbcWbcXaYgaWBaYhaWDbcYaZzaZZbdabdbbdcbddbdebddbddbddbddbddbdfbdgbdhbdibdjbdkbdlbdmbdnbdobdpbdqbdraVoaYubdsaZNaVobeRbbOaafaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBbdtbfTbdHbdzbbUaSFbaabaabaabaabaabbVbaabdKaYObbXbbYbaibbZbbZbbZbbZbdQbbZbcbaTUbccbcdbcebcebcfbcgaTSaXebchbcibcjaKibeablcaKkbcobcobcpbcpbcpbcpbcpbcqaMbbcrbcsbctbeebcvbcwbcxbbgaUpbczbcAbekaUpaUpaaaaaaaafaafbezaaaaaaaUpaUpbeBbcGbczaUpbbgbcxbcHbcIbcJbcKbcLaRpaWcaSSaSSaSSaSSaSSaGpbcMaSSbcNaSSaSSaSSaSSaSSbeMbcQbcRbcSaUQaUQaUQbeNbcUaTeaZMbcWbcXaYgaWBaYhaWDbcYaZzaZZbdabdbbdcbddbdebddbddbddbddbddbdfbdgbdhbdibdjbdkbdlbdmbdnbdobdpbdqbdraVoaYubdsaZNaVobeRbbOaafaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBbdubdvaZUbdwbdxaSFaZsbabbaaaZvbeTbbVbaabdAaYObbpbdCbaibbZbdDbdEbdFbdGbbZbeVbdIbdJaTSbeWbdLbdMbdNaTSaXebdObdPbdPbfebdPbdPbdPbdPbdRbdSbdSbdSbdTbdSbdUaMbbdVbdWbdXbdYbdYbdYbdYbdYbdYbdZbfobdZbdYbebbebbebbebbebbecbebbebbebbedbedbfqbedaUpaUpaUpaJiaJiaJibcKbcLaRpaJlbefbegaDmbehaSSbeibcMbejbfwbelaSSaSSbembcOaZzaZzaZzbfxaSGaSGaSGaZzaZzaZzbeqberbesbetaWBaYhaYhbeuaZzbevbewbbqaZzbeybbsbeAaYtbfybbEbeDbcmaONaGGaIobeFbeGbeHbeFbeIaIoaIoaGGbeJaVoaYuaVoaZNbeKbeLbbOaafaafaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaafbeObePbeQbfAaRtaZsbfWbeUbgubeTbbVbgIbgHaYObeXbeYbaibbZbbZbbZbeZbfabbZbfbbdIbfcaTSbeWbdLbdMbfdaTSaXebdObdPbgJbffbfgbfgbfhbdPbfibcVbfkbflbfmbfmbfmaMbaMkbcsbctbdYbfnbgMbfpbgNbfrbfsbftbfubdYbebbfvbgUbfvbgWbgXbfvbdybebbedbfCbfDbfEbfFbfGbfHbfIbfJaJibfKbfLbfMaJlaZzaZzaZzaZzbfNbfObfPbfQaZzaZzbfRaZzaZzaZzaZzbfSbfTbfUbfVbfVbfVbhebfXaZzbfYbfZbgabgbbgcbgcbgcbgdaZzbevbewbdBaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzbgfbggbghbgibgjbgfbggaZzaRZbgkaVoaYuaVoaZNaZObglbgmaWTaZRaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaabgnbgobgpbgqaZUbgrbgrbgrbgrbgrbgrbgsbgtbgraYOaYOaYOaYOaYObhCaYOaYOaYObgvbgvbgwbbZbdDbgxbeZbgybbZbgzbgAbgzaTSbeWbdLbdMbfdaTSaXebdObdPbgBbgCbfgbfgbgDbdPbfibgEbgFbgGbhKbhJbhLaMbbgKbgLbctbhNbivbgObgPbexbexbgRbgSbgTbdYbebbmIbgVbhSbhRbfzbgYbhTbebbedbhabhbbhcbeCbhUbeEbhgbhhaJibhibhjaRpbhkbhlbhmbewbewbhnbewbhobewbewbewbewbhpbewbewbewbewbhqbewbewbewbewbewbewbhmbewbewbhrbhsbhsbhtbhsbhsbhubhvbewbhqbhwbhxbhpbewbhybewbewbewbhzbhAbhBbhVbewbhDbewbhEbewbewbhFbhGbhHaVoaYuaVobhIbhWbidbhXbhMbilaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaYBaafbeObePbeQbfAaRtaZsbfWbeUbgubeTbbVbgIbgHaYObeXbeYbaibbZbbZbbZbeZbfabbZbfbbdIbfcaTSbeWbdLbdMbfdaTSaXebdObdPbgJbffbfgbfgbfhbdPbfibcVbfkbflbfmbfmbfmaMbaMkbcsbctbdYbfnbgMbfpbgNbfrbfsbftbfubdYbebbfvbgUbfvbgWbgXbfvbdybebbedbfCbfDbfEbfFbfGbfHbfIbfJaJibfKbfLbfMaJlaZzaZzaZzaZzbfNbfObfPbfQaZzaZzbfRaZzaZzaZzaZzbfSbkebfUbfVbfVbfVbhebfXaZzbfYbfZbgabgbbgcbgcbgcbgdaZzbevbewbdBaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzbgfbggbghbgibgjbgfbggaZzaRZbgkaVoaYuaVoaZNaZObglbgmaWTaZRaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaabgnbgobgpbgqaZUbgrbgrbgrbgrbgrbgrbgsbgtbgraYOaYOaYOaYOaYObhCaYOaYOaYObgvbgvbgwbbZbdDbgxbeZbgybbZbgzbgAbgzaTSbeWbdLbdMbfdaTSaXebdObdPbgBbgCbfgbfgbgDbdPbfibgEbgFbgGbhKbhJbhLaMbbgKbgLbctbhNbivbgObgPbexbexbgRbgSbgTbdYbebbmIbgVbhSbhRbfzbgYbhTbebbedbhabhbbhcbeCbhUbeEbhgbhhaJibhibhjaRpbhkbhlbhmbewbewbhnbewbhobewbewbewbewbhpbewbewbewbewbhqbewbewbewbewbewbewbhmbewbewbhrbhsbhsbhtbhsbhsbhubhvbewbhqbhwbhxbhpbewbhybewbewblrbhzbhAbhBbhVbewbhDbewbhEbewbewbhFbhGbhHaVoaYuaVobhIbhWbidbhXbhMbilaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhOaaaaafbhPaYDbhQbitbiqbjubjqbjwbjvbjubjAbjGbjBbjObpGbhZbgwbbZbbZbbZbiabfabbZaTSaTSaTSaTSbeWbibbicbjQaTSbiebifbdPbigbihbiibgDbijbdPbfibikbgFbgGbgGbgGbjRaMbbimaSzbctbjVbiobipbfjbirbisbfBbiubjMbdYbebbiwbixbiybjYbiybgYbgebebbedbiAbiBbiCbgQbiEbgZbiGbiHaJibiIbiJbiKbiLbiMbiNbiObiObiPbiQbiRbiSbiSbiSbiTbiSbiSbiSbiSbiSbiUbiVbiVbiVbiWbiObiObiNbiObiObiXbiVbiVbiYbiSbiZbjabjbbiSbjcbiObiObiObiObiObiObiObiObiObiObiObiObiObjdbiTbjebiSbjfbjgbjhbjibjibjjbjkaZNaWRbjlaWTaWTaWUaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhObhOaZSaZTbjmbjnbjobgrbjpbjpbjZbjpbjpbjpbALbwEbXrbBraXebaibbZbdDbjsbjtbgybbZbbLbbLbbLaTSaTSaTSaTSbkkaTSbjxbdObdPbjybjzbgDbfgbkubdPboibfmbkxbgGbgGbgGbjDaMbbjEaSzbctbkAbkHbgObhdbjIbjJbhfbjLblybdYbjNbkKbjPbiybkLbiybgVbkMbjSbedbjTbjUbizbjWbjWbjWbjXbkNaJibkPbkabkbbkcbkdbkebbFbkfbkgbkhbkibkjbkVbklbkmbknbknbkobewbewbewbewbewbkpbkqbkrbewbksbktbkXbkvbewbkpbkwbkYbkybhFbewbewbkzbewbewbkZbkBbewbkpbewbewbewbewbewbewbewbewbewbhqbewbewbhFbkCbkDbkEbkFbkGblobkIbkJaafaaaaafaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhObhOblBblrblEblCbkObgrblTbkQbkRbkRbkSbkTbkUbmdbmlbmlbmxbmobbZbbZbbZbeZbmCbbZbajbajbajbajblaaXeaXeblbblcbldbleblfblgblhblibljblkbdPbohbfmbmBbgGblnbgGbmDblpblqaSzbctbdYbmEblsbltblublvblwblxbdYbdYbebblzblAbmHbmFblDblAbiDbebbedbedblFblGblHblIbiCblJblKaJiblLblMblNaJiblOblOblOblOblOblOaZzaZzblPblQbZNcdMblQblPaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzbmNaZzaZzaZzaZzaZzaZzbmTaZzbewbewblVblWbiFblOblOblOblOblOblXblYblYblZblYbewblYblZbmablYbmbblObmcbmcbmcbmUaRZbmeaRZaRZaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhObhOaZSaZTbjmbjnbjobgrbjpbjpbjZbjpbjpbjpbALbwEbXrbBraXebaibbZbdDbjsbjtbgybbZbbLbbLbbLaTSaTSaTSaTSbkkaTSbjxbdObdPbjybjzbgDbfgbkubdPboibfmbkxbgGbgGbgGbjDaMbbjEaSzbctbkAbkHbgObhdbjIbjJbhfbjLblybdYbjNbkKbjPbiybkLbiybgVbkMbjSbedbjTbjUbizbjWbjWbjWbjXbkNaJibkPbkabkbbkcbkdcyPbbFbkfbkgbkhbkibkjbkVbklbkmbknbknbkobewbewbewbewbewbkpbkqbkrbewbksbktbkXbkvbewbkpbkwbkYbkybhFbewbewbkzbewbewbkZbkBbewbkpbewbewbewbewbewbewbewbewbewbhqbewbewbhFbkCbkDbkEbkFbkGblobkIbkJaafaaaaafaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhObhOblBcBVblEblCbkObgrblTbkQbkRbkRbkSbkTbkUbmdbmlbmlbmxbmobbZbbZbbZbeZbmCbbZbajbajbajbajblaaXeaXeblbblcbldbleblfblgblhblibljblkbdPbohbfmbmBbgGblnbgGbmDblpblqaSzbctbdYbmEblsbltblublvblwblxbdYbdYbebblzblAbmHbmFblDblAbiDbebbedbedblFblGblHblIbiCblJblKaJiblLblMblNaJiblOblOblOblOblOblOaZzaZzblPblQbZNcdMblQblPaZzaZzaZzaZzaZzaZzaZzaZzaZzaZzbmNaZzaZzaZzaZzaZzaZzbmTaZzbewbewblVblWbiFblOblOblOblOblOblXblYblYblZblYbewblYblZbmablYbmbblObmcbmcbmcbmUaRZbmeaRZaRZaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhObhObdubdvbjmbjnbmfbgrbmgbjpbmhbmibjpbjpbjpbmVbmjbmkbmkbmWbbZbdDbmmbeZbmnbbZbmXbmpbmqbmrbmsbmtbmtbmubmtbmtbmvbdPbmwbnabfgbmybmzblfblmbmAbjCbgGbgGbjHbnlbnbblqaSzbnobmGbmGbmGbmGbmGbmGbmGbnsbmGaafbebbmIbmJbmKbmLbmKbmMbjKbebaafbedbmObnwbmQbmRbiCbiGbmSaJibcKaRqaRpaJibnHbnAbnPbnNbnRbmYbmZbnSbnVbnUbndbnebnUbnWbnXbnhbnibnjbmPbojbnmbnnbokbnpbnqbnrbolbntbntbnubYfaVJblOblObooblObZMbZMblObnzbopbnBblObZtboqbZtblOblXblYbmbblObZnboJbZnblObnGboKbnIbnJbXsbYFbnMaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhOaaaaaabnOboNbeQbnQbgrbpcboWbpmbnTbprbpobjpbpsbpvbnYbnZbmWbbZbbZbbZbbZbbZbbZboabobbocbodboebdPbdPbdPbdPbdPbdPbdPbWqbdPbdPbdPbogbdPbfmbllbjCbgGbgGbgGbpwblpblqaSzbpybmGbombonbncbpAbvGbotbosbotaafbebboubovbowboxboybozbnfbebaafbedboBboCboDboEbiCbiGboFaJiboGboHaRpbXHbpBbngboLboMbnkbpLboPboQboRboRboSboTboUboUboVbpMboXboYboZbpabpbbnnbpNbpdbpebpfbpgbphbpfbpibYfaVJbpjbpkbplbpPbpnbnybppbnCbnDbpqbpSbptbpZbpTblOaZzbqabpxblObqbbqgbqcbqsbpCbpDbnIbpEcanccxbnMaaaaaaaaaaacaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaaaaaaaaaaaabgnbgobgpbgqbdvbpHbpHbpHbpIbpHbpJaZVbpKbqtbgrbqxbjpbqBbqybpQbpRbqHbqGbqKbqKbqKbqMbkWbpUbkWbkWbkWbkWbpVbpWbpWbpXbpYbdPbqTbqQbrkbrcbqdbqebqfbrnbqhbqibqjbqkbqkcKDcKEbgGbgGbqmbfmaMbblqbqnbqoaJubqqbqrbqrbxqborbrobxsbotaafbebbebbebbebbrubebbebbebbebaafbedbqzboCbqAbrvbqCbqDbqEaJibqFaRqaRpaJibrxbrwbqIbqJbrybqLboPbqNboUboUboUboUboUboUbqObqPbrCboYbqRbqSbrDbnnbqUbqVbqWbrIbpgbphbpfbqXbYfaVJbpjbqYbqZbqZbrabrbbrPbrdbrdbrdbrebrdbrfboObrhbribrjbscbnIbrlbpCbrmbsebpCbshbnIbrqccybrrbnMaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7535,7 +7541,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnbAVbzQbAVbCMbCNbCObrJbrJbrJbCNbrJbwTbrKbzTbCPbdPbDYbgGbrNbwXbgGbqlbCRbgGbgGbEgbxcbvtbAbbCTbxcbCUbvwbCVbEhbEibAWbxlbvwbEkbEjbEpbAhbErbErbErbAjbEubEsbEwbyNbDkbDlbDlbDmbDnbDobDpaJibDqbDrbDsaJibDtbECbDvbEFbDxbDybDzbDAbyWbEKbELbCjbEMbwmbDEbDFbwmbDGbDHbERbDJbESbDLbDMbCpbEUbDObBTbEVbDRbCpbVLbVMbDUbVAbDWbDXbDXbEWbDZbEabEbbEcbEdbEebEfbEYbEXbEZbCvbFbbFabFobwwbwwbwwbwwbwwbFybFrbEnbzKbzMbCJbEobFFbCJbzKbzLbzMbFQbCJbFUaafcHOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnbFVbExbFVbEybEzbEAbEAbEAbEAbEAbEBbGfbEDbzTbEEbdPbGgbEGbEHbEIbEJbGibGhbGkbGjbGvbtCbENbAbbEObEPbyEbvwbEQbGubGAbBMbETbvwbBPbGCbGDbAhaaaaaaaaabAjbGWbGEbFcbyNbFdbFebFfbFgbDnbDobFhaJibxwaRqaRpbHabFjbFkbFlbFmbFnbHfbFpbFqbxCbxFbxFbHibxFbwkbFsbFtbFubFvbFwbFxbDJbHjbDLbFzbFAbFBbDObFCbFDbFEbHkbVlbDXbHlbVAbFJbDXbDXbFKbFLbFMbFLbFLbFNbFObFPbHmbFRbFSbCvbHwbHvbHMbFWbFXbFYbFZbGabGbbGcbGdaafaafbCJbGebHNbHNbHObHQbHPbHRbEvaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnbGlbGmbGnbdPbdPbGobwNbwNbwNbGpbdPbdPbGqbGrbGsbdPbGtbGtbGtbHSbGtbGvbGwbGxbGybGzbtCbvtbAbbHUbGBbtCbtGbtGbtGbtGbtGbHVbtGbtGbtGbHZbtGbtGbtGbtGbtGbIfbtGbtGbtGbtGbtGbtGbtGaJiaJiaJiaJibxwaRqaRpbHabIobFkbCSbGGbCWbGIbGJbGKbGLbGMbGNbCjbGObGPbGQbGRbGSbGTbGUbGVbIrbGXbGYbGZbIubHbbHcbHdbHebIvbCpbUSbUfbwwbwwbwwbwwbwwbIAbwwbwwbwwbzAbIBbzAbzAbIDbBhbCubCvbHwbIMbIRbHnbHobHpbHqbGabGbbGcbHraaaaaabCJbHsbHtbEobCnbBybITbIUbCJaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnaaaaaaaaaaaaaaaaaaaafaaaaaaaaabHuaafaaaaaaaaaaaabGtbIYbIXbHxbHybLrbHzbIZbHBbHCbtCbvtbAbbAcbAabHDbHEbHFbHGbHHbHIbHJbHKbHLbJabJqbJbbJrbAabAabJDbJWbJVbAabHTbAabzZbHHbKJbHWbHXbHYbJXbxwaRqbDsaJlbDtbDubDtbDCbDPbxCbIbbIcbIdbIebKdbIgbIhbIibIjbIkbwmbIlbImbInbDJbDTbElbIpbIqbKfbFDbIsbItbKgbCpbKhbIwbIxbIybUdbLybKibICbKjbUcbIFbIGbIHbIIbIJbzAbIKbCubCvbKzbKobINbIObIPbIQbKBbGabGbbISbEnbEnbEnbCJbCJbCJbKVbKUbCJbCJbBybCJaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaaaaaaaaaaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnaaaaaaaaaaaaaaaaaaaafaaaaaaaaabHuaafaaaaaaaaaaaabGtbIYbIXbHxbHybLrbHzbIZbHBbHCbtCbvtbAbbAcbAabHDbHEbHFbHGbHHbHIbHJbHKbHLbJabJqbJbbJrbAabAabJDbJWbJVbAabHTbAacMkbHHbKJbHWbHXbHYbJXbxwaRqbDsaJlbDtbDubDtbDCbDPbxCbIbbIcbIdbIebKdbIgbIhbIibIjbIkbwmbIlbImbInbDJbDTbElbIpbIqbKfbFDbIsbItbKgbCpbKhbIwbIxbIybUdbLybKibICbKjbUcbIFbIGbIHbIIbIJbzAbIKbCubCvbKzbKobINbIObIPbIQbKBbGabGbbISbEnbEnbEnbCJbCJbCJbKVbKUbCJbCJbBybCJaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaaaaaaaaaaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnaaaaaaaaaaaaaaaaaabLaaaaaaaaaaaaaaaaaaaaaaaaaaaabGtbLnbEmbIVbIWcLYbLpbLzbLxbLFbtCbvtbJcbJdbJebJebJfbJgbJhbJibJjbJgbJfbJebJebLHbJkbJlbLIbJnbJobLKbJebJebJpbJgbJhbJibJjbJsbJtbJubJtbJvbJwbvUaJlbEtbEqbFHbGFbLWbGHbDzbHAbFibDVbxFbLYbCFbDSbDEbJGbwkbJHbJIbJJbDJbJKbJLbJMbJNbJObFDbJPbItbJObCpbJQbJRbIxbJSbJTbJUbMhbMlbMibJYbIFbJZbKabKbbKbbzAbKcbMqbMpbMxbMwbMCbMybMHbMFbKkbGabGbbKlbEnbKmbMIbKnbEnaafaafaafaafaafaafaafaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafbKpbKqbKqbKrbKsbKsbKtbKtbKtbKtbKuaafaafaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnaaaaaaaaaaaaaaaaaaaaaaaabKvbKwbKxbKwbKyaaaaaaaaabGtbGtbMMbKAbIVbKAbMPbKCbMSbKDbKEbtCbKFbvtbKGbKHbAabKIbAabzZbHHbKJbAabKKbKLbKMbKNbKObAcbAabKPbKQbHLbKRbHLbHLbKSbKTbMXbMTbKWbKXbcLbKYaRpaRpaRpaJlbMZbFlbFnbNdbJmbNfbJybJxbFIbLgbLhbLibLjbHgbDEbIkbIabIzbHhbDJbDJbLobLobLobCpbNhbLqbNkbLsbLtbCpbLubLvbIxbLwbFGbLybNqbLAbLBbLCbIFbJCbLEbKbbKbbzAbRsbSLbCvbwwbLGbNtbNsbLJbNzbLLbGabLMbLNbLObLObLObLPbGdaaaaaaaaaaaaaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafbLQbLRbLSbLRbKsbKtbKtbLTbLUbLTbKtbKtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabLVbNAbLXbNBbLVbLZbMabMbbGtbMcbMdbMebMfbMgbNLbNKbMjbMjbMkbtCbtCbtCbNQbtCbtCbtCbtCbtCbtCbtCbtCbtCbtCbtCbtCbtCbMmbMnbMobtCbtCbtCbtCbtCbNZbtCbtCbtCaJlaJlbObaJlaKSaMpbMraJlbKZbOcbOdbGFbLdbxCbDzbLDbxCbOfbMzbMAbMBbwkbOibMDbMEbOkbMGbOlbOnbMJbMKbMLbItbJObFDbFDbOtbJObCpbMNbMObMObMObMObMObMObMObMObMObMObOxbMQbMRbMRbzAbOCbODbMUbwwbMVbMVbMVbMWbOEbMYbMVbMVbMVbMVbMVbMVbNabNbaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymaymbOFbLRbLRbNebKtbKtbLTbLTbOGbLTbLTbKtbKtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7544,7 +7550,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabKxbMsbMsbMsbKxbQnbQobScbQqbQrbKAbKAbQsbQtbSgbQvbQvbQvbQvbQvbQvbQwbQxbQyaaabQzbQAbSibQCbSlbPfbQEbQGbQFbPfbNFbQIbQJbQKbNFbSrbSnbQNbQObSubQQbQRbPtbQSbPxbQTbNUbPxbPxbQUbDtbPnbGFbQVbSwbGFbPzbDzbLebRCbQZbPBbSEbSMbRGbDEbIkbSpbRdbRebRebRpbRfbMKbRgbRhbSNbRjbRkbRlbSObRnbPObMObOsbOsbRobOsbOsbOsbOsbSPbMObRqbLEbRrbRrbzAbRsbRtbRubSQbRwbSSbSRbSWbSVbTsbTgbTAbTubTNbTMbTObREbTWbTTbRHbQibOpbRKaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaabKtbKtbRLbLTbLTbLTbLTbLTbLTbLTbLTbLTbLTbLTbKtbKtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaabLVbUbbRNbUkbLVbRPbMabMbbGtbGtbRQbRQbRQbGtbGtbNxbRRbRRbRSbRSbRSbRSbNwbQyaaabRTbRUbRVbUobRXbRYbRZbSabSbbSbbUqbSdbSebUwbNFbPtbPtbPtbPtbPtbUAbPtbPtbShbUGbSjbNUbPxbSkbUObDtbQHbLbbQVbSmbUPbPzbSobJAbJBbSqbRabSsbStbJzbFsbSvbIEbSxbUWbURbSAbSBbMKbRmbSDbVebRjbSfbSGbVjbRnbPObMObMObMObRobOsbOsbOsbMObMObMObSIbSJbRrbRrbzAbSKbSLbCvbzIbVkbVvbVmbRDbVybVGbVzbVVbVObWibWgbMVbQfbWkbOObSXbRIbSybTaaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbKtbLTbLTbLTbLTbLTbLTbTbbLTbTcbLTbLTbLTbLTbLTbKtbKtaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabTdbKwbTebKwbTfbWoaafaaaaaabGtbThbTibTjbGtaaabNxbTkbTlbTmbTnbTnbTnbTobQyaaabQzbTpbTqbTrbWIbPfbTtbTvbWMbTwbNFbSzbTybTzbWVbTBbTBbTBbTCbTCbTDbTEbULbPxbPxbTFbNUbNUbNUbNUbDtbDtbLfbLkbLcbDtbTJbTKbTLbJFbJEbTJbPebLlbLmbTRbTSbTJbMKbMKbMKbMKbMKbMKbXabTUbTVbRjbXcbTXbTYbRnbPObMObTZbQWbPQbXebenbNWbNcbTZbUgbUhbUibIIbIJbzAbIKbSLbUjbwwbMVbMVbXibXnbMVbMVbMVbMVbXpbSCbVFbMVbXqbUnbOObUpbSYbUrbOOaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaabKtbUsbUsbUsbUsbUsbUsbUtbLTbUubUsbTcbLTbLTbLTbLTbKtaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabLaaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbUvbNxbNxbNxbNxbRSbXvbNwbUxaaabUybPcbPcbUzbXxbPfbPfbUBbPfbSFbNFbUDbSHbSTbNFbSUbSUbSUbSUbSUbSUbSUbSUbUHbUIbUJbUKbUKbUMbNUbDtbUNbSZbTxbUQbYabwabUTbUUbYtbYobYwbUTbUYbUZbVabVbbUebTPbVdbYybVgbVhbVibUlbYzbUmbRjbUCbYHbUCbRnbPObMObVnbUFbVpbVqbVrbVsbVtbVubUgbzAbYMbzAbzAbVwbCxbSLbCxbVxaafbnxbYSbYYblSbVBbYZbZcbZbbZebUVbMVbVHbVIbOObVJbWHbVKbwhaaLaaLaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwibLRbLRbLRbLRbLRbLRbLRbVNbLUbLTbLTbLTbLTbZibLUbKuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabLaaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbUvbNxbNxbNxbNxbRSbXvbNwbUxaaabUybPcbPcbUzbXxbPfbPfbUBbPfbSFbNFcMlbSHbSTbNFbSUbSUbSUbSUbSUbSUbSUbSUbUHbUIbUJbUKbUKbUMbNUbDtbUNbSZbTxbUQbYabwabUTbUUbYtbYobYwbUTbUYbUZbVabVbbUebTPbVdbYybVgbVhbVibUlbYzbUmbRjbUCbYHbUCbRnbPObMObVnbUFbVpbVqbVrbVsbVtbVubUgbzAbYMbzAbzAbVwbCxbSLbCxbVxaafbnxbYSbYYblSbVBbYZbZcbZbbZebUVbMVbVHbVIbOObVJbWHbVKbwhaaLaaLaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwibLRbLRbLRbLRbLRbLRbLRbVNbLUbLTbLTbLTbLTbZibLUbKuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabVPbVQbVQbVRbVSbNxbVTbRSbVUbNxaaaaaaaaaaaabNybZrbVWbVXbVZbVYbPfbNFbWabWbbNIbNFbSUbUXbVfbVcbVDbVCbVEbSUcaqcaqcaqcaqcaqbTFbWjbZsbWlbWcbWdbZubWpbxgbWrbWsbWtbWubWtbWvbWtbWwbWxbWybWzbWAbWBbWAbWCbWDbWEbWFbWGbWebZvbWfbWKbWLbZzbxVbMObxWbZBbzlbWSbWTbWhbWSbWSbXfbWWbWXbWYbWZbCxbCxbSLbCxbFTaafbnxbZLbZLbXbbZObXdbZSbZPbXgbXhbMVbVHbZUbOObOObOObOObOOaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaabKtbQmbQmbQmbQmbQmbQmbXkbLTbQlbQmbXlbLTbLTbLTbLTbKtaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabXmbZVbWmcaabRSczUcAYcADcBKbNxaaKaaaaaaaaabNybNybNybNybNybNybNybNFbUDbUEbXtbNFbSUbWnbWJbXubXubWJbWRbSUcaobWUbWUbXocaqbXBbDtbDtbXCbXDbXEbXFbXGblRbXIbXJbXKbXLbXMbXNbXObXPbXQbXRbXSbXTbXUbznbzpbzobAPbzqbARbAQbATbAScaxbAUbYfbYgbIwbYhbVobCqbWObWNbWPbYmbYnbZCbYpbYqbYrbYscaLbYrbYubYvbILaafbnxcaMcaWbrBbVBcaXcbecbdcbfbYAbMVbVHbYBbYCbUnaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbKtbLTbLTbLTbLTbLTbLTbTbbLTbXlbLTbLTbLTbLTbLTbKtbKtaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYDbVQbVQbVRbYEcEcbYGbNxcbgbNxbYIbYJbYKbYIbYIbYLcbibYNbYObYPcbjbXwbXzbXybYebXAbYjbWJbYQbYxbYRcbkbYTcbmbYVbYUbYXbYWcaqbZhbNScbnbZjbZkbZlbZlbZmbnEbZobZpbTJbTJbZqcbrbTJbTJcbycbtcbAcaIcbBbWQbZxbZycbCbZybZAbZacbDbZabZAcbJbYfbMNbIwbZEbXWbXVbZdcbKbZJbZKbMObMObwwbwwbwwbwwbwwboIbnFbofbwwbMVbMVbMVbMVbMVbMVbMVbMVbMVbMVbMVbMVcbLbZQbZRbUnaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaabKtbKtbRLbLTbLTbLTbLTbLTbLTbLTbLTbLTbLTbLTbKtbKtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7557,7 +7563,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEchHckpchHcgEchNckCchNcgEchRckFchRcgEaaaaaaciiciKcgTcgUcgUckNcejchUchTchWckQclfchXcidcicclgcieciecigciecbqbXzcihbYecikcimcilciocinciocipcirciqciqciAciAciAciAbTFciGciHciIciIciJclpclrciMciXciOclycluciRciSciSciTciUcaIcaIcaIclCcdEckqbZybZybZybZychBchBbViciYbViciZbYfccobYfaaaaaaaaaaaaaaaaaaaaacdLcjgcisciucitcjkcjjcivcjmcjncjociwcjocjocixclKclGcgIclVcgIcmgcmkcdScmpcjwcjxcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEchHcjbchHcgEchNcjcchNcgEchRcjdchRcgEaaaaaaciicgTcgUcgUcgUcjBcmscjhcjechWcmwcmGcmBcmPcmOcjzcjycjDcjAcjEcbqbXzcjFchjcjGcmQcjHcjJcjJcjJcjKcjMcjLcjNcmRcjOceAciAbTFciGcmXciIckbckccnbcubcneckgckhcngcnfckkcklciScnhciUcnkcnwcnucjQcjPcdHcnEcdIcdIcdJcdIcdKbVibVibVibVibYfccobYfaaaaaaaaaaaaaaaaaaaaacdLcnFcjRcjTcjSckEcdOcnIcdOckGckHcjXcjUcjUcjYcgIcgIckecjZcjUckickOcdSckPcnKckRcgNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacgEckrckuckscgEckzckBckAcgEckDckJckIcgEaaaaafciiclbcgTcgUcgUcgUcejckMckKchWchWcnLchWchWchWchWckTcieckWckYcbqclackZcldclccnNcleclhclhclhclicljcljclkciAcllcgqclwclxciGcnPciIclzclAclBcnQclDclEclFcnTclHclIclJciScnUciUcnVcnXclNclnclmclQclNclRclSclTbYfceQcdIcdIcdIcdIcdIcltbYfaaaaaaaaaaaaaaaaaaaaacdLcmacmbcmccmdcdOcmecmfcnZcdScmhcmicmicmiclvcoacmlclPclOcmicmicmncdScmocobcmqcmraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaafaafcgEclXcmmcmjcgEcmtcmmcEgcgEcmtcmmcEgcgEaaaaafcmzcgTcgTcgUcgUcmAcejcmvcmucmxcolconcmycmCcmCcmEcmDcmCcmFcoqcbqcmIcmHcmKcmJcimcmLcmLcmMcljcmNcotcorcorciAcibceVcoycqgciGcoAciIcnccndcoBciGcmSciNcmWciUcoCcnicnjciScoFciUclLclMclNcnlcoJcnlclNaaaaaaaaabYfbYfbYfcnnclSclSclTbYfbYfaaaaaaaaaaaacdOcdOcdOcdOcdOcdOcdOcdOcdOcnocnpcnqcdScdScnrcnscntcdScdScdScdScoLcnscntcdScdScnvcpdcnvaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaafaafcgEclXcmmcmjcgEcmtcmmcEgcgEcmtcmmcEgcgEaaaaafcmzcgTcgTcgUcgUcmAcejcmvcmucmxcolconcmycmCcmCcmEcmDcmCcmFcoqcbqcmIcmHcmKcmJcimcmLcmLcmMcljcmNcotcorcMmciAcibceVcoycqgciGcoAciIcnccndcoBciGcmSciNcmWciUcoCcnicnjciScoFciUclLclMclNcnlcoJcnlclNaaaaaaaaabYfbYfbYfcnnclSclSclTbYfbYfaaaaaaaaaaaacdOcdOcdOcdOcdOcdOcdOcdOcdOcnocnpcnqcdScdScnrcnscntcdScdScdScdScoLcnscntcdScdScnvcpdcnvaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbOaafaafaafaaaaafcnxaafcnxaafcKAaafcpfaafcKAaafcpfaafaafaaacejcnAcnBcgUcgUcnCcnDcpocpgcnycnmcprcnzcnzcpycnzcnGcpAcnHcnGcnJcpCcpBcpGcnMcnOcnOcnOcnOcpIcpHcnRcnRcnRcgscgscgscgscnSciGcpMcpNcnccpOcnWciGcmSciNcpPciUcnYcpQcnjcpUcpRciUclLclMclNcoccodcoeclNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaacdOcofcogcohcwlcojcokcqecomcqmcopcoocdOaaLaafaafaafaafaaaaaaaaacqraaaaaaaaaaafcoscqscosaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaafcoucqAcqtcoxcovcowcqDcoxcqIcqLcqDcoDcqNcqOcoEcnycnycnycnycnycnycnycnycoHcoGcqWcoIcracoKcoNcoMcoOcnGcoQcoPcoRcnGcoTcoScoUcnOcoWcoVcoYcoXcpacoZcpjcpbcpbcpkcpncpncpjcrvciGciGcpccrzciGciGciGcpeciNcrQciUciUciUcrScphciUciUclLcpiclNcvmcpscvmclNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaafaafcdOcplcpmcplcrUcjrcppcpqcomcomcrXcomcdOcdOaaaaaaaaaaafaafaaaaacaaaaaaaaaaaaaafaaacrZaaaaafaafaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIaaaaaaaaaaafcptcsacpucpxcpwcpFcsbcsccpzcsecsdcpEcpDcsfcpFcpLcpJcsicsgcsDcsncsKcpTcpWcpVcpYcpXcqacpZcqccqbcsLcqdcsMcqfcsQcqzcoTcqJcqKcnOcpacpacpacpacpacqMcpjcqPcqPcqPcpncpncpjbTFcrYciGcqhcqicqjcqkciGcqlciNcsWciUcqncqocqpcqqciUcsXclLcpiclNcsYcqQcquclNaaaaaaaaaaaaaaaaaacqvcqwcqxcqycqvaafaaaaaaaaaaaacdOcplcplcplcoicsZcqBcqCctbcqEcqFcqGcqHcdOaaaaaaaaaaaaaafaafaaaaaaaaaaaaaaaaafaaacmZaaaaafaafaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -7565,9 +7571,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaafaafaafcptcpFcrccpFcrccpFcqXcpFctucxactxcxactycxacxactGctBcpFcpFctOctIctIctIctSctQctTctTctUcpZctVcshcsjcnGcsmcskcuacnGcspcsocsrcsqcstcsscsvcsucpacswcpjcsxcrKcsycrKcuecpjbTFcizciGcszcsAcsBcsCciGcfYcufcfYciUcsEcsFcsGcsHciUcsIcrGcrGcqvcsJcsNculcqvcqvcqvcqvcqvcqvcqvcqvctMctDctNcqvcqvcqvcrHaaaaaacdOcofcogcohcslcsRcqBcrNcrNcrNcnpcrNcsScdOaaaaaaaaaaaaaaacrPaaaaafaaaaafaaaaaaaaackxaaaaafaafaaaaaaaaaaaacrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaafaaaaaacptcpFcrccpFcsOcsTcurcsVcsUcuxctxcxacuycxacxacuLcuEcuUcuOcuYctacvccvbcvbcvkcrccrccthctgctjcvlcnzcnGcvncnGcnGcnGcvsctlcsrctncvvcvtcvFcvEcpacvGcpjcvOcrKcsycrKcvRcpjctvctwciGciGcvXciGciGciGciBctzctAciUciUciUcwaciUciUcsIcrGaaacqvctCctZctEctFcwectHcwfctJctKctLcqvcuVcwmcuVcqvcwuctPcqvaafaafcdOcplcplcplcrVcjrctRcuccwDcwzcudcrNctWcdOcdOcdOcdOaaaaaacrPaaactXctXctXctXctXaafckxaafctXctXctXctXctXaaacrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacptcpFcsOcsTcsTcsTcurcsTcsTcsTcurcsTcsTcsTcsTcsTcwEcwGcsTcwHcsTcwIcsTcsTcsTcuhcugcuicpvcpFcujcwJcukcuncumcupcuocumcuqcuscwOcuucutcutcuvcutcuwcwWcwUcuAcuzcuBcuBcpjcuCcuDcwXcuFcuFcuGcuHcuIcuJcuJcuJcuJcItcuJcuJcuJcuKcrFcrGaaactFcwYcuPcuNctFcwZcuRcuQcuQcvdcvacuQcuQcvhcuQcuVcuXcuQcqvaaaaaacdOcplcplcplcslcxdcuZcvicxncxecvjcrNcrNcvecvfcvgcdOaafaafcrPaafckVckSckSckSckSckyckxckwckvckvckvckvckUaafcrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacptcpFcpFcpFcpFcpFcqXcpFcpFcpFcqXcpFcpFcpFcpFcpFcvWcpFcpFcticpFcxocpFcxqcxpcvpcvocvrcvqcxrcvqcxscvucvxcvwcvycvucvucvzcvAcpIcvBcpacvDcvCcpacpacxwcxtcxtcxCcuBcuBcpjbPxcAscvNcvNcvNcvNcxFcvNcvNcvNcvNclMcJgcrGcrGcrGcrGcrGcrGaaactFctFcxHctFctFcxJcvScvTcvUcvVcvHcvJcvIcvLcvKcxVcwbcwccqvaaaaaacdOcomcomcomcomcwdcppcvicyacxYcvQcrNcrNcwhcrNcwicdOaaaaaacrPaafcwjcwjcwjcwjcwjaaackxaaacwjcwjcwjcwjcwjaafcrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaacbOaaaaaaaaaaaacptcpFcpFcpFcpFcpFcqXcpFcpFcpFcqXcpFcpFcpFcpFcpFcvWcpFcpFcticpFcybcpFcpFcybcybcyccpFcpFcvZcvYcwgcwgcwgcwgcygcwkcoTcwocwpcsqcwqcpacwscvCcpacwtcpjcyhcxtcyicwxcwwcpjcymcvMcvNcyrcypcwKcwLcwMcwNcyucvNclMcJDcrGaaaaaaaaaaaaaaaaaacqvcwRcwycwAcywcwCcwBcyEcyzcyFcwFcwTcwScwVcyHcuWcuQcyJcqvaaaaaacdOcofcogcohckXcsRcuZcxgcxhcxhcxicxjcxkcyKcxmcyLcdOaaaaaacrPaaaaafaaaaafaafaafaaackxaaaaafaaaaafaaaaafaaacrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacptcpFcpFcpFcpFcpFcyMcpFcpFcpFcyMcpFcpFcpFcpFcpFcvWcpFcpFcyRcyPcySctdctdcyScyTcyScxlcyUcyVctdcyZcyXczgczeczncwkcoTcxucoTcxvczocpacpacxAcpacxBcpjczqczqcxDcwxcwwcpjbPxcvMcvNcxKcxLcxMcxNcxOcxNcxPcvNcxQcJEcrGaaaaaaaaaaaaaaaaaacqvcxScxTcxUczrcxWcxXczBcxZcuTczFcuScxEcuTczHcqvcqvcqvcqvaaaaaacdOcplcpmcplcwvcjrcppcrNcrNcyecyfcrNczKcomcomcomcdOaaaaaacrPaaactXctXctXctXctXaafckxaafctXctXctXctXctXaafcrPaaaczLaaaaaaczLaaaaaaaaaczLaaaaaaaaaaaaaaaczLaaaaaaaaaczLaaaaaaczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacptcpFcpFcBvcpFcpFcqXcpFcpFcpFcqXcpFcBvcpFcpFcpFcvWcpFcpFcticBvcxocpFcxqcxpcvpcvocvrcvqcxrcvqcxscvucvxcvwcvycvucvucvzcvAcpIcvBcpacvDcvCcpacpacxwcxtcxtcxCcuBcuBcpjbPxcAscvNcvNcvNcvNcxFcvNcvNcvNcvNclMcJgcrGcrGcrGcrGcrGcrGaaactFctFcxHctFctFcxJcvScvTcvUcvVcvHcvJcvIcvLcvKcxVcwbcwccqvaaaaaacdOcomcomcomcomcwdcppcvicyacxYcvQcrNcrNcwhcrNcwicdOaaaaaacrPaafcwjcwjcwjcwjcwjaaackxaaacwjcwjcwjcwjcwjaafcrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaacbOaaaaaaaaaaaacptcpFcpFcMncpFcpFcqXcpFcpFcpFcqXcpFcMncpFcpFcpFcvWcpFcpFcticMncybcpFcpFcybcybcyccpFcpFcvZcvYcwgcwgcwgcwgcygcwkcoTcwocwpcsqcwqcpacwscvCcpacwtcpjcyhcxtcyicwxcwwcpjcymcvMcvNcyrcypcwKcwLcwMcwNcyucvNclMcJDcrGaaaaaaaaaaaaaaaaaacqvcwRcwycwAcywcwCcwBcyEcyzcyFcwFcwTcwScwVcyHcuWcuQcyJcqvaaaaaacdOcofcogcohckXcsRcuZcxgcxhcxhcxicxjcxkcyKcxmcyLcdOaaaaaacrPaaaaafaaaaafaafaafaaackxaaaaafaaaaafaaaaafaaacrPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaacptcpFcpFcpvcpFcpFcyMcpFcpFcpFcyMcpFcpvcpFcpFcpFcvWcpFcpFcyRcMocySctdctdcyScyTcyScxlcyUcyVctdcyZcyXczgczeczncwkcoTcxucoTcxvczocpacpacxAcpacxBcpjczqczqcxDcwxcwwcpjbPxcvMcvNcxKcxLcxMcxNcxOcxNcxPcvNcxQcJEcrGaaaaaaaaaaaaaaaaaacqvcxScxTcxUczrcxWcxXczBcxZcuTczFcuScxEcuTczHcqvcqvcqvcqvaaaaaacdOcplcpmcplcwvcjrcppcrNcrNcyecyfcrNczKcomcomcomcdOaaaaaacrPaaactXctXctXctXctXaafckxaafctXctXctXctXctXaafcrPaaaczLaaaaaaczLaaaaaaaaaczLaaaaaaaaaaaaaaaczLaaaaaaaaaczLaaaaaaczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaaaaaaaaacptcpFczmcrWcrWczpcxGcrWczpcrWcxIczMctIctIczSctIczTctIctIctSczVcybcpFcpFcyjcylcykcynczXcyocpFcAhcyqcyscyscAtcytcoTcxucyvcnOcAvcpacyxcpacAwcyycpjcpjcpjcpjcpjcpjcpjbPxcvMcvNcAxcyNcxLcyOcxLcxNcAAcvNcrGcJGcrGaaaaaaaaaaaaaaaaaacqvcuVcAHctFctFcAJcyAcAQcyWctMctDctNcyBctMcvhcyYcqvaaaaaaaaaaaacdOcplcplcplckXcARczacrNcrNcrNcyfcrNczbcrNczccrNczdaafaafcrPaafckVckSckSckSckSckyckxckwckvckvckvckvckUaafcrPaaaczLczLczLczLaaaaaaaaaczLczLczLczLczLczLczLaaaaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaafaaaaaaaaacptcpFcqXcpFcpFcpFcyMcpFcpFcpFcyMcpFcpFcpFcyCcpFcvWcpFcpFcpFcyDcybcpFcpFcATcyTctfcyGcwgcAUcwgcwgcyqcAWcyIcBkcytcoTcxucoTcnOcBncBmcBscBqczfcpacnOcBucBzcBzczhcBAcBDczNczOcvNcBEczPczQcxNczRcBHcBIcvNcJIcJHcrGaaaaaaaaaaaaaaaaaacqvczWcuMcBLcuVczYczZcAactFcAbcAccsPcyBczWczjcAecqvaaaaaaaaaaaackEcdOcAfcAgcAgczkcAicAjcAkcAlcAmcAncAocApcAqcokcAraaaaaacrPaafcwjcwjcwjcwjcwjaaackxaafcwjcwjcwjcwjcwjaaacrPaaaczLczLczLczLaaaaaaczLczLczLczLczLczLczLczLczLaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactYctYctYctYctYctYctYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaIaaaaaaczlcpFcqXcpFcBOcxactxcxacBRcxactxcxacBRcxacxccxacxbcBSctectdcCcctfczsczucztczwczvczxcwgczzczycwgcwgcwgcwgcwgczAcpCcCecpCcnOcnOcnOcnOcnOcnOcnOcnOczDcBzcBzczEcANcAObPxcAPcvNcCgcCfcClcCicCqcCncCvcvNcAXcJJcrGaaaaaaaaaaaaaaaaaacqvcuQcAZcAectFcBacBbcBcctFcBdcBecCBczGczIcBecCFcqvaafaafaaaaaaaaaaaabquaaacdOcBlczJcCJcBocBpczJcCNcBrcBpczJcCOcdOaaaaaacbOaaaaafaaaaafaaaaafaaackxaaaaafaaaaafaafaafaafcrPaaaczLczLczLczLaaaaaaczLczLczLczLczLczLczLczLczLaaaaaaczLczLczLczLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaa From d247584d1b163eaa95c5f39521979afdf85ed5a2 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Wed, 18 Nov 2015 14:38:46 +0000 Subject: [PATCH 102/207] add a sleep inbetween disabling and enabling hardware mode i've been seeing HW mode not always re-enabling, hopefully this'll fix it --- code/modules/client/client procs.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index ecbd78b14d5..3ee7ebcdebe 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -161,6 +161,7 @@ spawn(5) // And wait a half-second, since it sounds like you can do this too fast. if(src) winset(src, null, "command=\".configure graphics-hwmode off\"") + sleep(2) // wait a bit more, possibly fixes hardware mode not re-activating right winset(src, null, "command=\".configure graphics-hwmode on\"") log_client_to_db() From 959e15826bfdfaac6caed8b0c6de2d7ce3e4b249 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Fri, 20 Nov 2015 19:55:00 +1030 Subject: [PATCH 103/207] Fixes grown food not leaving trash. --- code/modules/hydroponics/grown.dm | 1 + code/modules/hydroponics/seed.dm | 3 +++ 2 files changed, 4 insertions(+) diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 83681744447..40fd541f711 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -38,6 +38,7 @@ return name = "[seed.seed_name]" + trash = seed.get_trash_type() update_icon() diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 108a242636a..011ec7a2373 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -68,6 +68,9 @@ /datum/seed/proc/get_trait(var/trait) return traits["[trait]"] +/datum/seed/proc/get_trash_type() + return trash_type + /datum/seed/proc/set_trait(var/trait,var/nval,var/ubound,var/lbound, var/degrade) if(!isnull(degrade)) nval *= degrade if(!isnull(ubound)) nval = min(nval,ubound) From 8e1928062b0e6f11f38241bcf33c6b70ca0137b9 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Fri, 20 Nov 2015 21:41:31 +0000 Subject: [PATCH 104/207] sulphuric acid is "sacid" not "acid" --- .../research/xenoarchaeology/artifact/artifact_unknown.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_unknown.dm b/code/modules/research/xenoarchaeology/artifact/artifact_unknown.dm index 5fbe8dcd41f..c8e0f78dca8 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact_unknown.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact_unknown.dm @@ -257,7 +257,7 @@ var/list/valid_secondary_effect_types = list(\ my_effect.ToggleActivate() if(secondary_effect && secondary_effect.trigger == TRIGGER_WATER && prob(25)) secondary_effect.ToggleActivate(0) - else if(W.reagents.has_reagent("acid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1)) + else if(W.reagents.has_reagent("sacid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1)) if(my_effect.trigger == TRIGGER_ACID) my_effect.ToggleActivate() if(secondary_effect && secondary_effect.trigger == TRIGGER_ACID && prob(25)) From a79a8746e0e4d6e5696b7b2a1ea0da90034281a1 Mon Sep 17 00:00:00 2001 From: Datraen Date: Fri, 20 Nov 2015 18:30:52 -0500 Subject: [PATCH 105/207] Fixes #11489 --- code/modules/hydroponics/trays/tray.dm | 37 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index d3971383173..9075ad83ab3 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -342,12 +342,15 @@ set category = "Object" set src in view(1) - if(labelled) - usr << "You remove the label." - labelled = null - update_icon() - else - usr << "There is no label to remove." + if(!usr.canmove || usr.stat || usr.restrained()) + return + if(ishuman(usr)) + if(labelled) + usr << "You remove the label." + labelled = null + update_icon() + else + usr << "There is no label to remove." return /obj/machinery/portable_atmospherics/hydroponics/verb/setlight() @@ -355,10 +358,14 @@ set category = "Object" set src in view(1) - var/new_light = input("Specify a light level.") as null|anything in list(0,1,2,3,4,5,6,7,8,9,10) - if(new_light) - tray_light = new_light - usr << "You set the tray to a light level of [tray_light] lumens." + if(!usr.canmove || usr.stat || usr.restrained()) + return + if(ishuman(usr)) + var/new_light = input("Specify a light level.") as null|anything in list(0,1,2,3,4,5,6,7,8,9,10) + if(new_light) + tray_light = new_light + usr << "You set the tray to a light level of [tray_light] lumens." + return /obj/machinery/portable_atmospherics/hydroponics/proc/check_level_sanity() //Make sure various values are sane. @@ -611,12 +618,14 @@ set name = "Toggle Tray Lid" set category = "Object" set src in view(1) - close_lid(usr) + if(!usr.canmove || usr.stat || usr.restrained()) + return + + if(ishuman(usr)) + close_lid(usr) + return /obj/machinery/portable_atmospherics/hydroponics/proc/close_lid(var/mob/living/user) - if(!user || user.stat || user.restrained()) - return - closed_system = !closed_system user << "You [closed_system ? "close" : "open"] the tray's lid." update_icon() From 301f7f5c8d04b27a24f6e38369a3b83518b09f2c Mon Sep 17 00:00:00 2001 From: Datraen Date: Fri, 20 Nov 2015 19:37:00 -0500 Subject: [PATCH 106/207] Fixes #11489, fixes labels as well --- code/modules/hydroponics/trays/tray.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 9075ad83ab3..79b6c5c3619 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -344,7 +344,7 @@ if(!usr.canmove || usr.stat || usr.restrained()) return - if(ishuman(usr)) + if(ishuman(usr) || istype(usr, /mob/living/silicon/robot)) if(labelled) usr << "You remove the label." labelled = null @@ -360,7 +360,7 @@ if(!usr.canmove || usr.stat || usr.restrained()) return - if(ishuman(usr)) + if(ishuman(usr) || istype(usr, /mob/living/silicon/robot)) var/new_light = input("Specify a light level.") as null|anything in list(0,1,2,3,4,5,6,7,8,9,10) if(new_light) tray_light = new_light @@ -621,7 +621,7 @@ if(!usr.canmove || usr.stat || usr.restrained()) return - if(ishuman(usr)) + if(ishuman(usr) || istype(usr, /mob/living/silicon/robot)) close_lid(usr) return From ef1f91e3348f6b952bc42d9ff866b89b33888a1d Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Fri, 20 Nov 2015 14:42:28 -0500 Subject: [PATCH 107/207] Fix Laptop Vendors and Personal Lockers not accepting ID Containers Fixes #11092 --- code/game/machinery/computer3/lapvend.dm | 86 +++++++++---------- .../crates_lockers/closets/secure/personal.dm | 5 +- html/changelogs/neersighted-11486.yml | 5 ++ 3 files changed, 48 insertions(+), 48 deletions(-) create mode 100644 html/changelogs/neersighted-11486.yml diff --git a/code/game/machinery/computer3/lapvend.dm b/code/game/machinery/computer3/lapvend.dm index 416472a31ac..ac3e7e172cf 100644 --- a/code/game/machinery/computer3/lapvend.dm +++ b/code/game/machinery/computer3/lapvend.dm @@ -38,16 +38,14 @@ /obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(vendmode == 1) - if(istype(W, /obj/item/weapon/card)) - var/obj/item/weapon/card/I = W - scan_card(I) + var/obj/item/weapon/card/id/I = W.GetID() + + if(vendmode == 1 && I) + scan_id(I, W) + vendmode = 0 + if(vendmode == 3 && I) + if(reimburse_id(I, W)) vendmode = 0 - if(vendmode == 3) - if(istype(W,/obj/item/weapon/card)) - var/obj/item/weapon/card/I = W - if(reimburse(I)) - vendmode = 0 if(vendmode == 0) if(istype(W, /obj/item/device/laptop)) var/obj/item/device/laptop/L = W @@ -210,26 +208,24 @@ newlap.spawn_parts() -/obj/machinery/lapvend/proc/scan_card(var/obj/item/weapon/card/I) - if (istype(I, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = I - visible_message("[usr] swipes a card through [src].") - var/datum/money_account/CH = get_account(C.associated_account_number) - if(!CH) - usr << "\icon[src]No valid account number is associated with this card." - return - if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) - if(vendor_account) - var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - transfer_and_vend(D, C) - else - usr << "\icon[src]Unable to access account. Check security settings and try again." +/obj/machinery/lapvend/proc/scan_id(var/obj/item/weapon/card/id/C, var/obj/item/I) + visible_message("\The [usr] swipes \the [I] through \the [src].") + var/datum/money_account/CH = get_account(C.associated_account_number) + if(!CH) + usr << "\icon[src]No valid account number is associated with this card." + return + if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + if(vendor_account) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + if(D) + transfer_and_vend(D, C) else usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." else - transfer_and_vend(CH, C) + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + else + transfer_and_vend(CH, C) // Transfers money and vends the laptop. @@ -361,30 +357,28 @@ -/obj/machinery/lapvend/proc/reimburse(var/obj/item/weapon/card/I) - if (istype(I, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = I - visible_message("[usr] swipes a card through [src].") - var/datum/money_account/CH = get_account(C.associated_account_number) - if(!CH) - usr << "\icon[src]No valid account number is associated with this card." - return 0 - if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) - if(vendor_account) - var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - transfer_and_reimburse(D) - return 1 - else - usr << "\icon[src]Unable to access account. Check security settings and try again." - return 0 +/obj/machinery/lapvend/proc/reimburse_id(var/obj/item/weapon/card/id/C, var/obj/item/I) + visible_message("\The [usr] swipes \the [I] through \the [src].") + var/datum/money_account/CH = get_account(C.associated_account_number) + if(!CH) + usr << "\icon[src]No valid account number is associated with this card." + return 0 + if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + if(vendor_account) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + if(D) + transfer_and_reimburse(D) + return 1 else usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." return 0 else - transfer_and_reimburse(CH) - return 1 + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + return 0 + else + transfer_and_reimburse(CH) + return 1 /obj/machinery/lapvend/proc/transfer_and_reimburse(var/datum/money_account/D) var/transaction_amount = total() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index 2aa3e571852..a71851f9f20 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -66,11 +66,12 @@ src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet user.drop_item() if (W) W.forceMove(src.loc) - else if(istype(W, /obj/item/weapon/card/id)) + else if(W.GetID()) + var/obj/item/weapon/card/id/I = W.GetID() + if(src.broken) user << "It appears to be broken." return - var/obj/item/weapon/card/id/I = W if(!I || !I.registered_name) return if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name))) //they can open all lockers, or nobody owns this, or they own this locker diff --git a/html/changelogs/neersighted-11486.yml b/html/changelogs/neersighted-11486.yml new file mode 100644 index 00000000000..8908354b587 --- /dev/null +++ b/html/changelogs/neersighted-11486.yml @@ -0,0 +1,5 @@ +author: neersighted +delete-after: True +changes: + - bugfix: "Laptop Vendors now accept ID Containers (PDA, Wallet, etc)." + - bugfix: "Personal Lockers now accept ID Containers (PDA, Wallet, etc)." From e98192afc7848cac4959a14e31cbc93faddac6b7 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 22 Nov 2015 11:21:28 +0100 Subject: [PATCH 108/207] Updates changelog. --- html/changelog.html | 7 +++++++ html/changelogs/.all_changelog.yml | 4 ++++ html/changelogs/neersighted-11486.yml | 5 ----- 3 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 html/changelogs/neersighted-11486.yml diff --git a/html/changelog.html b/html/changelog.html index 554144e8fc1..da0c373d463 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,13 @@ -->
        +

        22 November 2015

        +

        neersighted updated:

        +
          +
        • Laptop Vendors now accept ID Containers (PDA, Wallet, etc).
        • +
        • Personal Lockers now accept ID Containers (PDA, Wallet, etc).
        • +
        +

        27 October 2015

        HarpyEagle updated:

          diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 89f6ba658f4..49b16be0a5c 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2036,3 +2036,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. HarpyEagle: - bugfix: When affected by pepperspray, eye protection now prevents blindness and face protection now prevents stun, instead of face protection doing both. +2015-11-22: + neersighted: + - bugfix: Laptop Vendors now accept ID Containers (PDA, Wallet, etc). + - bugfix: Personal Lockers now accept ID Containers (PDA, Wallet, etc). diff --git a/html/changelogs/neersighted-11486.yml b/html/changelogs/neersighted-11486.yml deleted file mode 100644 index 8908354b587..00000000000 --- a/html/changelogs/neersighted-11486.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: neersighted -delete-after: True -changes: - - bugfix: "Laptop Vendors now accept ID Containers (PDA, Wallet, etc)." - - bugfix: "Personal Lockers now accept ID Containers (PDA, Wallet, etc)." From 782f0a8bfb1271ae6a69e81c10428b7daa4833c2 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 22 Nov 2015 11:37:14 +0100 Subject: [PATCH 109/207] Makes shuttle control consoles sturdier. Fixes #11501. --- code/modules/shuttles/shuttle_console.dm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index 5cb28c40e64..4a86591cf90 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -15,7 +15,7 @@ if(!allowed(user)) user << "\red Access Denied." return 1 - + ui_interact(user) /obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) @@ -94,4 +94,10 @@ ..() /obj/machinery/computer/shuttle_control/bullet_act(var/obj/item/projectile/Proj) - visible_message("[Proj] ricochets off [src]!") + visible_message("\The [Proj] ricochets off \the [src]!") + +/obj/machinery/computer/shuttle_control/ex_act() + return + +/obj/machinery/computer/shuttle_control/emp_act() + return From 0f78998377f91dfe8f694f364b3edfbaa7b23a08 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 22 Nov 2015 20:34:29 -0600 Subject: [PATCH 110/207] Fix Dionea home system Fixes #11492 --- code/modules/client/preferences_factions.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/client/preferences_factions.dm b/code/modules/client/preferences_factions.dm index 2293be7dd6a..404fbc98c1c 100644 --- a/code/modules/client/preferences_factions.dm +++ b/code/modules/client/preferences_factions.dm @@ -24,7 +24,7 @@ var/global/list/home_system_choices = list( "Sol", "Nyx", "Tau Ceti", - "Epsilon Ursae Majoris", + "Epsilon Ursae Minoris", "S'randarr" ) From 3cdc81ad8ebf0f1427e8fe8041b530a125f03462 Mon Sep 17 00:00:00 2001 From: Loganbacca Date: Wed, 25 Nov 2015 21:38:17 +1300 Subject: [PATCH 111/207] Removed power testing map --- maps/PowerTesting.dmm | 120 ------------------------------------------ 1 file changed, 120 deletions(-) delete mode 100644 maps/PowerTesting.dmm diff --git a/maps/PowerTesting.dmm b/maps/PowerTesting.dmm deleted file mode 100644 index 9c7088d6ab2..00000000000 --- a/maps/PowerTesting.dmm +++ /dev/null @@ -1,120 +0,0 @@ -"aa" = (/turf/space,/area/space) -"ab" = (/turf/simulated/wall/r_wall,/area/space) -"ac" = (/obj/machinery/power/solar{id = "portsolar"; name = "Port Solar Array"},/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/airless{icon_state = "solarpanel"},/area/solar/port) -"ad" = (/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating,/area/solar/port) -"ae" = (/obj/machinery/power/solar{id = "portsolar"; name = "Port Solar Array"},/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/airless{icon_state = "solarpanel"},/area/solar/port) -"af" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating,/area/solar/port) -"ag" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"ah" = (/turf/simulated/wall/r_wall,/area/maintenance/portsolar) -"ai" = (/turf/simulated/wall/r_wall,/area/engine/workshop) -"aj" = (/turf/simulated/floor/plating,/area/solar/port) -"ak" = (/obj/structure/cable/yellow,/turf/simulated/floor/plating,/area/solar/port) -"al" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"am" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced,/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"an" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"ao" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = -32; pixel_y = 0},/obj/machinery/atmospherics/portables_connector,/obj/machinery/portable_atmospherics/canister/air{filled = 0.05},/turf/simulated/floor/plating{dir = 1; icon_state = "warnplatecorner"},/area/maintenance/portsolar) -"ap" = (/obj/machinery/power/terminal{dir = 4},/obj/machinery/light/small{dir = 1},/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aq" = (/obj/structure/cable{d2 = 2; icon_state = "0-2"; pixel_y = 0},/obj/machinery/power/smes/buildable{charge = 0},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"ar" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 0},/turf/simulated/wall/r_wall,/area/maintenance/portsolar) -"as" = (/turf/simulated/floor/plating,/area/engine/workshop) -"at" = (/obj/machinery/power/terminal{dir = 4},/obj/structure/cable{d2 = 2; icon_state = "0-2"; pixel_y = 0},/turf/simulated/floor/plating,/area/engine/workshop) -"au" = (/obj/machinery/power/smes/buildable{charge = 0},/obj/structure/cable/green{d2 = 2; icon_state = "0-2"},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/engine/workshop) -"av" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/light{dir = 1},/turf/simulated/floor/plating,/area/engine/workshop) -"aw" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/engine/workshop) -"ax" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating,/area/engine/workshop) -"ay" = (/obj/structure/dispenser{phorontanks = 0},/turf/simulated/floor/plating,/area/engine/workshop) -"az" = (/obj/machinery/power/tracker,/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/airless/catwalk{icon_state = "catwalk4"},/area/solar/port) -"aA" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/solar/port) -"aB" = (/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/solar/port) -"aC" = (/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/solar/port) -"aD" = (/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1379; layer = 3.3; master_tag = "robotics_solar_airlock"; name = "exterior access button"; pixel_x = 25; pixel_y = 25},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/solar/port) -"aE" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "robotics_solar_outer"; locked = 1; name = "Engineering External Access"; req_access = list(10, 13)},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aF" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1379; id_tag = "robotics_solar_pump"},/obj/machinery/embedded_controller/radio/airlock/airlock_controller{tag_airpump = "robotics_solar_pump"; tag_exterior_door = "robotics_solar_outer"; frequency = 1379; id_tag = "robotics_solar_airlock"; tag_interior_door = "robotics_solar_inner"; layer = 3.3; pixel_x = 0; pixel_y = -25; req_access = list(13); tag_chamber_sensor = "robotics_solar_sensor"},/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "robotics_solar_sensor"; layer = 3.3; pixel_x = 12; pixel_y = -25},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/effect/decal/warning_stripes,/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aG" = (/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "robotics_solar_inner"; locked = 1; name = "Engineering External Access"; req_access = list(13)},/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aH" = (/obj/machinery/access_button{command = "cycle_interior"; frequency = 1379; layer = 3.3; master_tag = "robotics_solar_airlock"; name = "interior access button"; pixel_x = -25; pixel_y = -25},/obj/machinery/atmospherics/pipe/simple/visible{tag = "icon-intact (NORTHWEST)"; icon_state = "intact"; dir = 9},/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 8},/area/maintenance/portsolar) -"aI" = (/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aJ" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aK" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aL" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/engine/workshop) -"aM" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/engine/workshop) -"aN" = (/obj/machinery/power/breakerbox/activated,/turf/simulated/floor/plating,/area/engine/workshop) -"aO" = (/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/turf/simulated/floor/plating,/area/engine/workshop) -"aP" = (/obj/effect/landmark/start{name = "AI"},/obj/effect/landmark/start{name = "Assistant"},/obj/effect/landmark/start{name = "Atmospheric Technician"},/obj/effect/landmark/start{name = "Bartender"},/obj/effect/landmark/start{name = "Captain"},/obj/effect/landmark/start{name = "Cargo Technician"},/obj/effect/landmark/start{name = "Chaplain"},/obj/effect/landmark/start{name = "Chef"},/obj/effect/landmark/start{name = "Chemist"},/obj/effect/landmark/start{name = "Chief Engineer"},/obj/effect/landmark/start{name = "Chief Medical Officer"},/obj/effect/landmark/start{name = "Cyborg"},/obj/effect/landmark/start{name = "Detective"},/obj/effect/landmark/start{name = "Gardener"},/obj/effect/landmark/start{name = "Geneticist"},/obj/effect/landmark/start{name = "Head of Personnel"},/obj/effect/landmark/start{name = "Head of Security"},/obj/effect/landmark/start{name = "Internal Affairs Agent"},/obj/effect/landmark/start{name = "Janitor"},/obj/effect/landmark/start{name = "Librarian"},/obj/effect/landmark/start{name = "Medical Doctor"},/obj/effect/landmark/start{name = "Psychiatrist"},/obj/effect/landmark/start{name = "Quartermaster"},/obj/effect/landmark/start{name = "Research Director"},/obj/effect/landmark/start{name = "Roboticist"},/obj/effect/landmark/start{name = "Scientist"},/obj/effect/landmark/start{name = "Security Officer"},/obj/effect/landmark/start{name = "Shaft Miner"},/obj/effect/landmark/start{name = "Station Engineer"},/obj/effect/landmark/start{name = "Warden"},/obj/effect/landmark/start{name = "Xenobiologist"},/turf/simulated/floor/plating,/area/engine/workshop) -"aQ" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/workshop) -"aR" = (/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor/plating,/area/engine/workshop) -"aS" = (/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plating,/area/solar/port) -"aT" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"aU" = (/obj/machinery/power/solar_control{id = "portsolar"; name = "Aft Port Solar Control"; track = 0},/obj/structure/cable/yellow,/turf/simulated/floor/plating{dir = 4; icon_state = "warnplatecorner"},/area/maintenance/portsolar) -"aV" = (/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aW" = (/obj/machinery/camera{c_tag = "Aft Port Solar Control"; dir = 1},/obj/machinery/alarm{dir = 1; pixel_y = -22},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable,/turf/simulated/floor/plating,/area/maintenance/portsolar) -"aX" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/light{dir = 8},/turf/simulated/floor/plating,/area/engine/workshop) -"aY" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 4},/turf/simulated/floor/plating,/area/engine/workshop) -"aZ" = (/obj/machinery/atmospherics/pipe/simple/hidden{tag = "icon-intact (EAST)"; icon_state = "intact"; dir = 4},/turf/simulated/floor/plating,/area/engine/workshop) -"ba" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 8},/turf/simulated/floor/plating,/area/engine/workshop) -"bb" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/rig/engineering,/obj/item/clothing/mask/breath,/obj/item/clothing/head/helmet/space/rig/engineering,/obj/item/clothing/gloves/yellow,/obj/item/device/multitool,/obj/item/weapon/wirecutters,/turf/simulated/floor/plating,/area/engine/workshop) -"bc" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable/yellow{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plating,/area/solar/port) -"bd" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar) -"be" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/workshop) -"bf" = (/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/engine/workshop) -"bg" = (/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/plating,/area/engine/workshop) -"bh" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/alarm{dir = 1; pixel_y = -22},/turf/simulated/floor/plating,/area/engine/workshop) -"bi" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/engine/workshop) -"bj" = (/obj/machinery/computer/station_alert,/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bk" = (/turf/simulated/wall/r_wall,/area/engine/engine_smes) -"bl" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bm" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bn" = (/turf/simulated/wall/r_wall,/area/engine/engine_monitoring) -"bo" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bp" = (/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bq" = (/obj/machinery/light_switch{pixel_x = 0; pixel_y = 27},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"br" = (/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bs" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bt" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bu" = (/turf/simulated/floor/plating,/area/engine/engine_smes) -"bv" = (/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bw" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bx" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"by" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bz" = (/obj/machinery/power/monitor{name = "Engine Power Monitoring"},/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bA" = (/obj/structure/cable/yellow{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable/yellow{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plating,/area/solar/port) -"bB" = (/obj/machinery/power/smes/buildable{charge = 1e+007; input_level = 500000; input_attempt = 1; cur_coils = 4; output_level = 500000},/obj/structure/cable,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/engine/engine_smes) -"bC" = (/obj/machinery/power/terminal{dir = 8},/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bD" = (/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/structure/cable/yellow{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bE" = (/obj/machinery/light,/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bF" = (/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bG" = (/obj/machinery/light,/obj/machinery/power/monitor{name = "Engine Power Monitoring"},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bH" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/engine/engine_smes) -"bI" = (/turf/simulated/floor/plating,/area/engine/engine_monitoring) -"bJ" = (/turf/simulated/wall/r_wall,/area/engine/engine_room) -"bK" = (/obj/item/stack/sheet/mineral/phoron{amount = 1000},/turf/simulated/floor/plating,/area/engine/engine_room) -"bL" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/yellow{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/engine/engine_room) -"bM" = (/obj/machinery/power/terminal{dir = 4},/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/engine/engine_room) -"bN" = (/obj/structure/cable/yellow{d2 = 4; icon_state = "0-4"},/obj/machinery/power/smes/buildable{charge = 2e+006},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/engine/engine_room) -"bO" = (/obj/structure/cable/cyan{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 8},/area/engine/engine_room) -"bP" = (/obj/machinery/power/apc/super{dir = 1; name = "north bump"; pixel_y = 24},/obj/structure/cable/cyan{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/engine/engine_room) -"bQ" = (/obj/machinery/light,/turf/simulated/floor/plating,/area/engine/engine_room) -"bR" = (/obj/structure/cable/yellow,/obj/machinery/power/port_gen/pacman{anchored = 1},/turf/simulated/floor/plating,/area/engine/engine_room) -"bS" = (/turf/simulated/floor/plating,/area/engine/engine_room) -"bT" = (/obj/machinery/alarm{dir = 1; pixel_y = -22},/turf/simulated/floor/plating,/area/engine/engine_room) -"bU" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/plating,/area/engine/engine_room) - -(1,1,1) = {" -aaaaaaaaabaaaaaaabaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaacadaeaaacadaeaaacadaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaacafaeaaacafaeaaacafaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaacafaeaaacafaeaaacafaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaacafaeaaacafaeaaacafaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -abababacafaeabacafaeabacafaeabababababaaaaagahahahahaiaiaiaiaiaiaiai -abajajajakajajajakajajajakajajajajajajalamanaoapaqarasatauavawaxayai -azaAaAaBaCaAaAaBaCaAaAaBaCaAaAaAaAaAaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRai -abajajajaSajajajaSajajajaSajajajajajajalamaTaUaVaWahaXaYaZbaasaQbbai -abababacbcaeabacbcaeabacbcaeabababababaaaabdahahahahbebfawbgbhbibjai -aaaaaaacbcaeaaacbcaeaaacbcaeaaaaaaaaaaaaaaaaaaaaaabkblbmbkbkbnbobnbn -aaaaaaacbcaeaaacbcaeaaacbcaeaaaaaaaaaaaaaaaaaaaaaabkblbpbqbkbrbsbtbn -aaaaaaacbcaeaaacbcaeaaacbcaeaaaaaaaaaaaaaaaaaaaaaabkblbubvbwbxbybzbn -aaaaaaacbAaeaaacbAaeaaacbAaeaaaaaaaaaaaaaaaaaaaaaabkbBbCbDbkbEbFbGbn -aaaaaaaaabaaaaaaabaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaabkbkbubHbkbnbIbnbn -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabJbKbLbMbNbObPbJ -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabJbQbRbSbSbTbUbJ -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabJbJbJbJbJbJbJbJ -"} From c5ed0a8801e97f07ff5855b8f94bb65d1c2acef3 Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Thu, 26 Nov 2015 13:04:34 +0000 Subject: [PATCH 112/207] Small bot optimisations --- bot/NanoTrasenBot.py | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/bot/NanoTrasenBot.py b/bot/NanoTrasenBot.py index e86009ef580..c243f1aa0e1 100644 --- a/bot/NanoTrasenBot.py +++ b/bot/NanoTrasenBot.py @@ -190,15 +190,13 @@ tell_list = {} if CORE_DATA.DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS: nudgeable = False try: - tiedosto = open("replacenames.cache","r") - replacenames = pickle.load(tiedosto) - tiedosto.close() + with open("replacenames.cache","r") as tiedosto: + replacenames = pickle.load(tiedosto) for i in replacenames.values(): if len(i) > call_me_max_length: replacenames[replacenames.keys()[replacenames.values().index(i)]] = i[:call_me_max_length] - tiedosto = open("replacenames.cache","w") - pickle.dump(replacenames,tiedosto) - tiedosto.close() + with open("replacenames.cache","w") as tiedosto: + pickle.dump(replacenames,tiedosto) if "[\0x01]" in i.lower() or "[\\0x01]" in i.lower(): i = i.replace("[\0x01]","") i = i.replace("[\0X01]","") @@ -211,13 +209,12 @@ except EOFError: #Cache corrupt replacenames = {} print "replacenames.cache is corrupt and couldn't be loaded." try: - tiedosto = open("peopleheknows.cache","r") - peopleheknows = pickle.load(tiedosto) - tiedosto.close() + with open("peopleheknows.cache","r") as tiedosto: + peopleheknows = pickle.load(tiedosto) except IOError: peopleheknows = [[],[]] - tiedosto = open("peopleheknows.cache","w") - tiedosto.close() + with open("peopleheknows.cache","w") as tiedosto: + pass except EOFError: peopleheknows = [[],[]] print "peopleheknows.cache is corrupt and couldn't be loaded." @@ -401,13 +398,12 @@ def target(who,how_long): if debug: print "Banned",who,"For",how_long,"seconds" if logbans: - tiedosto = open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w") - tiedosto.write("Start of ban on "+who+":"+str(int(start))) - tiedosto.write("\n") - tiedosto.write("End of ban on "+who+":"+str(int(end))) - tiedosto.write("\n") - tiedosto.write("In total:"+str(int(end-start))+"Seconds") - tiedosto.close() + with open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w") as tiedosto: + tiedosto.write("Start of ban on "+who+":"+str(int(start))) + tiedosto.write("\n") + tiedosto.write("End of ban on "+who+":"+str(int(end))) + tiedosto.write("\n") + tiedosto.write("In total:"+str(int(end-start))+"Seconds") else: CALL_OFF = False pass From dcfb65028f97ed4f6482201dcc5a7429583d04be Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Thu, 26 Nov 2015 14:36:43 +0000 Subject: [PATCH 113/207] More withs --- bot/NanoTrasenBot.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bot/NanoTrasenBot.py b/bot/NanoTrasenBot.py index c243f1aa0e1..a58415124fa 100644 --- a/bot/NanoTrasenBot.py +++ b/bot/NanoTrasenBot.py @@ -35,10 +35,9 @@ except ImportError: try: tiedosto = open("psycodownload.txt","r") except: - tiedosto = open("psycodownload.txt","w") - tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco") - tiedosto.write("\nhttp://psyco.sourceforge.net/download.html") - tiedosto.close() + with open("psycodownload.txt","w") as tiedosto: + tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco") + tiedosto.write("\nhttp://psyco.sourceforge.net/download.html") print "Check psycodownload.txt for a link" else: print "For god's sake, open psycodownload.txt" @@ -629,9 +628,8 @@ while True: arg = influx.lower()[8+len(prefix):] if debug: print truesender+":"+prefix+"suggest "+arg - tiedosto = open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a") - tiedosto.write(arg) - tiedosto.close() + with open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a") as tiedosto: + tiedosto.write(arg) conn.privmsg(targetchannel,"Suggestion received") elif cocheck( prefix+"help "): #Space in front of the ( to make sure that my command finder does not pick this up. arg = " ".join(influx.split(" ")[1:]).lower() From af545835111ed7c2b65ae8f8823616baa0407421 Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Thu, 26 Nov 2015 16:10:33 +0000 Subject: [PATCH 114/207] Another small refactor --- bot/NanoTrasenBot.py | 50 ++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/bot/NanoTrasenBot.py b/bot/NanoTrasenBot.py index a58415124fa..6f65a11dafb 100644 --- a/bot/NanoTrasenBot.py +++ b/bot/NanoTrasenBot.py @@ -341,16 +341,14 @@ if aggressive_pinging: self_time = 0 global backup,disconnects,conn while disconnects < 5: - if backup > self_time: - if time.time()-backup > delay: - conn.send("PONG "+pongtarg) - print "Ponged" - self_time = time.time() - else: - if time.time()-self_time > delay: - conn.send("PONG "+pongtarg) - print "Ponged" - self_time = time.time() + if backup > self_time and time.time()-backup > delay: + conn.send("PONG "+pongtarg) + print "Ponged" + self_time = time.time() + elif time.time()-self_time > delay: + conn.send("PONG "+pongtarg) + print "Ponged" + self_time = time.time() time.sleep(refresh) thread.start_new_thread(aggressive_ping,(aggressive_pinging_delay,aggressive_pinging_refresh,)) def stop(sender,debug=1): @@ -366,16 +364,15 @@ def stop(sender,debug=1): access_granted = True else: access_granted = False - if access_granted: - if debug: - print sender+":"+prefix+"stop" - if random.randint(0,100) == 50: - conn.privmsg(channel,"Hammertime!") - else: - conn.privmsg(channel,"Shutting down.") - disconnects = 99999 - conn.quit() - return True + if access_granted and debug: + print sender+":"+prefix+"stop" + if random.randint(0,100) == 50: + conn.privmsg(channel,"Hammertime!") + else: + conn.privmsg(channel,"Shutting down.") + disconnects = 99999 + conn.quit() + return True else: conn.privmsg(channel,"You cannot command me") return False @@ -571,13 +568,12 @@ while True: time.sleep(6) Name = origname conn.nick(Name) - if origname in truesender: - if influx == prefix+"stop": - time.sleep(0.5) #A small delay - conn.privmsg(channel,"Shutting down.") - conn.quit() - disconnects = 99999 - break + if origname in truesender and influx == prefix+"stop": + time.sleep(0.5) #A small delay + conn.privmsg(channel,"Shutting down.") + conn.quit() + disconnects = 99999 + break if len(translateable) > 0 and enabled == True: people = "-5|5|1-".join(users).lower() if truesender.lower() in translateable: From b15497aa51b134e60a9f9c4172a5473b74897e4e Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Thu, 26 Nov 2015 20:27:51 +0000 Subject: [PATCH 115/207] info topic improvements --- code/world.dm | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/code/world.dm b/code/world.dm index 3a5f0a5f83b..02d7d804a77 100644 --- a/code/world.dm +++ b/code/world.dm @@ -198,18 +198,32 @@ var/world_topic_spam_protect_time = world.timeofday return "Bad Key" - var/search = input["info"] - var/ckey = ckey(search) + var/list/search = params2list(input["info"]) + var/list/ckeysearch = list() + for(var/text in search) + ckeysearch += ckey(text) var/list/match = list() for(var/mob/M in mob_list) - if(findtext(M.name, search)) - match += M - else if(M.ckey == ckey) - match += M - else if(M.mind && findtext(M.mind.assigned_role, search)) - match += M + var/strings = list(M.name, M.ckey) + if(M.mind) + strings += M.mind.assigned_role + strings += M.mind.special_role + for(var/text in strings) + if(ckey(text) in ckeysearch) + match[M] += 10 // an exact match is far better than a partial one + else + for(var/searchstr in search) + if(findtext(text, searchstr)) + match[M] += 1 + + var/maxstrength = 0 + for(var/mob/M in match) + maxstrength = max(match[M], maxstrength) + for(var/mob/M in match) + if(match[M] < maxstrength) + match -= M if(!match.len) return "No matches" From 2d5677109f2383b5af04046c6eab9a741c7d5fef Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 29 Nov 2015 12:14:31 +0100 Subject: [PATCH 116/207] Build mode throws now admin logs. Fixes #11514. --- code/modules/admin/verbs/buildmode.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index 2131e977ac7..0ecc220ae2c 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -296,3 +296,4 @@ if(pa.Find("right")) if(holder.throw_atom) holder.throw_atom.throw_at(object, 10, 1) + log_admin("[key_name(usr)] threw [holder.throw_atom] at [object]") From 5958a25e808a1aa2a3c1e5706ef7f88d18a8abb1 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Mon, 30 Nov 2015 22:47:39 +0100 Subject: [PATCH 117/207] Fixes airlocks losing air, again. - Replaces #11123 - this PR fixes the issue itself, instead of using delays to work around the issue. - update_nearby_tiles() is now being called right after density is changed, instead of sleeping for 0.7 seconds. - Tested this in engineering shuttle dock airlock, which is one of few airlocks which don't have pump replenishing lost gas installed. Loss of air is minimal (few kilopascals, likely caused by airlocks opening at 5kPa as reaching pure vacuum would take too long) in comparsion to situation without this fix (where, once cycled out, you can't cycle back in without forcing the inner side of airlock) --- code/game/machinery/doors/door.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 65206b95f2f..57bd4708dc2 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -409,12 +409,12 @@ set_opacity(0) sleep(3) src.density = 0 + update_nearby_tiles() sleep(7) src.layer = open_layer explosion_resistance = 0 update_icon() set_opacity(0) - update_nearby_tiles() operating = 0 if(autoclose) @@ -436,12 +436,12 @@ src.density = 1 explosion_resistance = initial(explosion_resistance) src.layer = closed_layer + update_nearby_tiles() sleep(7) update_icon() if(visible && !glass) set_opacity(1) //caaaaarn! operating = 0 - update_nearby_tiles() //I shall not add a check every x ticks if a door has closed over some fire. var/obj/fire/fire = locate() in loc From e33ae21f75f3180c165e0d668b84255ef9427f19 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Mon, 30 Nov 2015 23:19:04 +0100 Subject: [PATCH 118/207] Adjusts APC emag behavior - Mostly under-the-hood changes. - Emagged APCs may now have their panel removed with screwdriver, so you can access wires - Emagged APCs no longer rely on locked var, instead they check for emagged var as mwerezak suggested. --- code/modules/power/apc.dm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index a1811e496c4..7f232d80412 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -479,8 +479,6 @@ user << "There is nothing to secure." return update_icon() - else if(emagged) - user << "The interface is broken." else wiresexposed = !wiresexposed user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]" @@ -750,7 +748,7 @@ return var/list/data = list( - "locked" = locked, + "locked" = (locked && !emagged) ? 1 : 0, "isOperating" = operating, "externalPower" = main_status, "powerCellStatus" = cell ? cell.percent() : null, @@ -882,7 +880,7 @@ if(!can_use(usr, 1)) return 1 - if(!istype(usr, /mob/living/silicon) && locked) + if(!istype(usr, /mob/living/silicon) && (locked && !emagged)) // Shouldn't happen, this is here to prevent href exploits usr << "You must unlock the panel to use this!" return 1 From 1a293e2d9607a828cba59e5464c459d777982b0e Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 1 Dec 2015 08:48:47 +0100 Subject: [PATCH 119/207] Renames the rig mounted taser. Was previously called an energy gun, which could be mildly confusing. Port of https://github.com/PolarisSS13/Polaris/pull/127. --- code/modules/clothing/spacesuits/rig/modules/combat.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/clothing/spacesuits/rig/modules/combat.dm b/code/modules/clothing/spacesuits/rig/modules/combat.dm index d4bd12ec4bf..ee9f16e1a24 100644 --- a/code/modules/clothing/spacesuits/rig/modules/combat.dm +++ b/code/modules/clothing/spacesuits/rig/modules/combat.dm @@ -135,8 +135,8 @@ suit_overlay_active = "mounted-taser" suit_overlay_inactive = "mounted-taser" - interface_name = "mounted energy gun" - interface_desc = "A shoulder-mounted cell-powered energy gun." + interface_name = "mounted taser" + interface_desc = "A shoulder-mounted cell-powered taser." gun_type = /obj/item/weapon/gun/energy/taser/mounted From 44cb040e54d16ca3013a1ffab61267ae5190a5f4 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Tue, 1 Dec 2015 17:10:45 +0100 Subject: [PATCH 120/207] Fixes camera repair --- code/game/machinery/camera/camera.dm | 14 ++++++- code/game/machinery/camera/camera_assembly.dm | 10 +++-- html/changelogs/Hubblenaut-master.yml | 37 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 html/changelogs/Hubblenaut-master.yml diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index e2371bbeb21..52ff3d08a38 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -140,9 +140,19 @@ if(weld(W, user)) if(assembly) assembly.loc = src.loc - assembly.state = 1 + assembly.anchored = 1 + assembly.camera_name = c_tag + assembly.camera_network = english_list(network, "Exodus", ",", ",") + assembly.update_icon() + assembly.dir = src.dir assembly = null //so qdel doesn't eat it. - new /obj/item/stack/cable_coil(src.loc, length=2) + if(stat & BROKEN) + assembly.state = 2 + user << "You repaired \the [src] frame." + else + assembly.state = 1 + user << "You cut \the [src] free from the wall." + new /obj/item/stack/cable_coil(src.loc, length=2) qdel(src) // OTHER diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 75397278c03..86095dedfb8 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -11,6 +11,8 @@ // Motion, EMP-Proof, X-Ray var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/material/osmium, /obj/item/weapon/stock_parts/scanning_module) var/list/upgrades = list() + var/camera_name + var/camera_network var/state = 0 var/busy = 0 /* @@ -47,7 +49,7 @@ else if(iswrench(W)) playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user << "You unattach the assembly from it's place." + user << "You unattach the assembly from its place." anchored = 0 update_icon() state = 0 @@ -67,7 +69,7 @@ else if(iswelder(W)) if(weld(W, user)) - user << "You unweld the assembly from it's place." + user << "You unweld the assembly from its place." state = 1 anchored = 1 return @@ -78,7 +80,7 @@ if(isscrewdriver(W)) playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", "Exodus")) + var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", camera_network ? camera_network : "Exodus")) if(!input) usr << "No input found please hang up and try your call again." return @@ -90,7 +92,7 @@ var/area/camera_area = get_area(src) var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])" - input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag), MAX_NAME_LEN) + input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", camera_name ? camera_name : temptag), MAX_NAME_LEN) state = 4 var/obj/machinery/camera/C = new(src.loc) diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-master.yml new file mode 100644 index 00000000000..fca68d64515 --- /dev/null +++ b/html/changelogs/Hubblenaut-master.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Hubblenaut + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Welding a broken camera will use the correct icon." + - tweak: "Camera assemblies remember their tag and network from previous usage." From c7e7c05a34b1a1082a9ecb890341eb051b24ec1f Mon Sep 17 00:00:00 2001 From: Atlantis Date: Wed, 2 Dec 2015 11:14:41 +0100 Subject: [PATCH 121/207] Fixes #11546 --- .../research/xenoarchaeology/machinery/artifact_analyser.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm b/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm index 99113bd1f2e..b449237d775 100644 --- a/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm +++ b/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm @@ -85,6 +85,7 @@ var/obj/machinery/artifact/A = scanned_object A.anchored = 0 A.being_used = 0 + scanned_object = null /obj/machinery/artifact_analyser/Topic(href, href_list) if(href_list["begin_scan"]) @@ -97,8 +98,8 @@ continue if(O.invisibility) continue - if(istype(scanned_object, /obj/machinery/artifact)) - var/obj/machinery/artifact/A = scanned_object + if(istype(O, /obj/machinery/artifact)) + var/obj/machinery/artifact/A = O if(A.being_used) artifact_in_use = 1 else From 89f5c9f4056fff5dde20ccec051811748243dc74 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Wed, 2 Dec 2015 11:27:28 +0100 Subject: [PATCH 122/207] Fixes #11540 --- code/game/objects/structures/crates_lockers/closets.dm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 40a8c9d38db..08a2a5af237 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -172,19 +172,18 @@ if(1) for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion A.forceMove(src.loc) - A.ex_act(severity++) + A.ex_act(severity + 1) qdel(src) if(2) if(prob(50)) for (var/atom/movable/A as mob|obj in src) A.forceMove(src.loc) - A.ex_act(severity++) + A.ex_act(severity + 1) qdel(src) if(3) if(prob(5)) for(var/atom/movable/A as mob|obj in src) A.forceMove(src.loc) - A.ex_act(severity++) qdel(src) /obj/structure/closet/proc/damage(var/damage) From cc72f823719946e11a274d7a2c2a9e47c8b72ffe Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 3 Dec 2015 21:50:24 +0100 Subject: [PATCH 123/207] Backports NanoUI fixes from dev. Fixes #11579. --- code/modules/nano/modules/crew_monitor.dm | 2 +- code/modules/nano/modules/power_monitor.dm | 2 +- code/modules/nano/nanoui.dm | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm index b38ac805153..3d0cdac6575 100644 --- a/code/modules/nano/modules/crew_monitor.dm +++ b/code/modules/nano/modules/crew_monitor.dm @@ -2,7 +2,7 @@ name = "Crew monitor" /obj/nano_module/crew_monitor/Topic(href, href_list) - if(..()) return + if(..()) return 1 var/turf/T = get_turf(src) if (!T || !(T.z in config.player_levels)) usr << "Unable to establish a connection: You're too far away from the station!" diff --git a/code/modules/nano/modules/power_monitor.dm b/code/modules/nano/modules/power_monitor.dm index ed7c64aa943..b0bf72f39a3 100644 --- a/code/modules/nano/modules/power_monitor.dm +++ b/code/modules/nano/modules/power_monitor.dm @@ -47,7 +47,7 @@ // Allows us to process UI clicks, which are relayed in form of hrefs. /obj/nano_module/power_monitor/Topic(href, href_list) if(..()) - return + return 1 if( href_list["clear"] ) active_sensor = null if( href_list["refresh"] ) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 74c21d49822..e1db4b4cc6c 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -140,6 +140,7 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/update_status(var/push_update = 0) + src_object = src_object.nano_host() var/new_status = src_object.CanUseTopic(user, state) if(master_ui) new_status = min(new_status, master_ui.status) From 7c85f846eb873385f85119bbfa6a19a6646c6bfa Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Fri, 4 Dec 2015 17:38:58 +1030 Subject: [PATCH 124/207] put_in_hands() refactor. --- code/game/objects/items.dm | 3 + .../objects/items/devices/chameleonproj.dm | 2 + code/modules/mob/inventory.dm | 56 +++++-------------- code/modules/mob/living/carbon/human/human.dm | 39 +++++++++++++ .../species/xenomorphs/alien_facehugger.dm | 1 + 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 2a68cb87f7f..fef7336371c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -242,6 +242,9 @@ // for items that can be placed in multiple slots // note this isn't called during the initial dressing of a player /obj/item/proc/equipped(var/mob/user, var/slot) + layer = 20 + if(user.client) user.client.screen |= src + if(user.pulling == src) user.stop_pulling() return //Defines which slots correspond to which slot flags diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index f7ef8ad5c21..5a97968e93b 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -18,9 +18,11 @@ /obj/item/device/chameleon/dropped() disrupt() + ..() /obj/item/device/chameleon/equipped() disrupt() + ..() /obj/item/device/chameleon/attack_self() toggle() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index d820e89cf97..8944bc31099 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -103,64 +103,34 @@ var/list/slot_equipment_priority = list( \ //Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. /mob/proc/put_in_l_hand(var/obj/item/W) - if(lying) return 0 - if(!istype(W)) return 0 - if(!l_hand) - W.forceMove(src) //TODO: move to equipped? - l_hand = W - W.layer = 20 //TODO: move to equipped? -// l_hand.screen_loc = ui_lhand - W.equipped(src,slot_l_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() - update_inv_l_hand() - return 1 - return 0 + if(lying || !istype(W)) + return 0 + return 1 //Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success. /mob/proc/put_in_r_hand(var/obj/item/W) - if(lying) return 0 - if(!istype(W)) return 0 - if(!r_hand) - W.forceMove(src) - r_hand = W - W.layer = 20 -// r_hand.screen_loc = ui_rhand - W.equipped(src,slot_r_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() - update_inv_r_hand() - return 1 - return 0 + if(lying || !istype(W)) + return 0 + return 1 //Puts the item into our active hand if possible. returns 1 on success. /mob/proc/put_in_active_hand(var/obj/item/W) - if(hand) return put_in_l_hand(W) - else return put_in_r_hand(W) + return 0 // Moved to human procs because only they need to use hands. //Puts the item into our inactive hand if possible. returns 1 on success. /mob/proc/put_in_inactive_hand(var/obj/item/W) - if(hand) return put_in_r_hand(W) - else return put_in_l_hand(W) + return 0 // As above. //Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. //If both fail it drops it on the floor and returns 0. //This is probably the main one you need to know :) /mob/proc/put_in_hands(var/obj/item/W) - if(!W) return 0 - if(put_in_active_hand(W)) - update_inv_l_hand() - update_inv_r_hand() - return 1 - else if(put_in_inactive_hand(W)) - update_inv_l_hand() - update_inv_r_hand() - return 1 - else - W.forceMove(get_turf(src)) - W.layer = initial(W.layer) - W.dropped() + if(!W) return 0 + W.forceMove(get_turf(src)) + W.layer = initial(W.layer) + W.dropped() + return 0 // Removes an item from inventory and places it in the target atom. // If canremove or other conditions need to be checked then use unEquip instead. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 308f2359e1f..5abb81b8dd9 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1383,3 +1383,42 @@ get_scooped(H) return return ..() + +//Puts the item into our active hand if possible. returns 1 on success. +/mob/living/carbon/human/put_in_active_hand(var/obj/item/W) + return (hand ? put_in_l_hand(W) : put_in_r_hand(W)) + +//Puts the item into our inactive hand if possible. returns 1 on success. +/mob/living/carbon/human/put_in_inactive_hand(var/obj/item/W) + return (hand ? put_in_r_hand(W) : put_in_l_hand(W)) + +/mob/living/carbon/human/put_in_hands(var/obj/item/W) + if(!W) + return 0 + if(put_in_active_hand(W)) + update_inv_l_hand() + update_inv_r_hand() + return 1 + else if(put_in_inactive_hand(W)) + update_inv_l_hand() + update_inv_r_hand() + return 1 + else + return ..() + +/mob/living/carbon/human/put_in_l_hand(var/obj/item/W) + if(!..() || l_hand) + return 0 + W.forceMove(src) + l_hand = W + W.equipped(src,slot_l_hand) + update_inv_l_hand() + return 1 + +/mob/living/carbon/human/put_in_r_hand(var/obj/item/W) + if(!..() || r_hand) + return 0 + W.forceMove(src) + r_hand = W + W.equipped(src,slot_r_hand) + update_inv_r_hand() diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_facehugger.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_facehugger.dm index d6767fbbc4e..34455a47a11 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_facehugger.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_facehugger.dm @@ -70,6 +70,7 @@ var/const/MAX_ACTIVE_TIME = 400 return /obj/item/clothing/mask/facehugger/equipped(mob/M) + ..() Attach(M) /obj/item/clothing/mask/facehugger/Crossed(atom/target) From 0cf5a709d1b9059f150e6123d0148ee347517e68 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Fri, 4 Dec 2015 17:55:21 +1030 Subject: [PATCH 125/207] Refactored give(). --- code/modules/mob/living/carbon/give.dm | 83 +++++++++++--------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index 579321a5128..e9e3392dd45 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -1,53 +1,42 @@ -mob/living/carbon/verb/give(var/mob/living/carbon/target in view(1)-usr) +/mob/living/carbon/human/verb/give(var/mob/living/target in view(1)-usr) set category = "IC" set name = "Give" - if(!istype(target) || target.stat == 2 || usr.stat == 2|| target.client == null) + + // TODO : Change to incapacitated() on merge. + if(usr.stat || usr.lying || usr.resting || usr.buckled) return - var/obj/item/I - if(!usr.hand && usr.r_hand == null) - usr << "You don't have anything in your right hand to give to [target.name]" + if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null) return - if(usr.hand && usr.l_hand == null) - usr << "You don't have anything in your left hand to give to [target.name]" - return - if(usr.hand) - I = usr.l_hand - else if(!usr.hand) - I = usr.r_hand + + var/obj/item/I = usr.get_active_hand() if(!I) + I = usr.get_inactive_hand() + if(!I) + usr << "You don't have anything in your hands to give to \the [target]." return - if(target.r_hand == null || target.l_hand == null) - switch(alert(target,"[usr] wants to give you \a [I]?",,"Yes","No")) - if("Yes") - if(!I) - return - if(!Adjacent(usr)) - usr << "You need to stay in reaching distance while giving an object." - target << "[usr.name] moved too far away." - return - if((usr.hand && usr.l_hand != I) || (!usr.hand && usr.r_hand != I)) - usr << "You need to keep the item in your active hand." - target << "[usr.name] seem to have given up on giving \the [I.name] to you." - return - if(target.r_hand != null && target.l_hand != null) - target << "Your hands are full." - usr << "Their hands are full." - return - else - usr.drop_item() - if(target.r_hand == null) - target.r_hand = I - else - target.l_hand = I - I.loc = target - I.layer = 20 - I.add_fingerprint(target) - target.update_inv_l_hand() - target.update_inv_r_hand() - usr.update_inv_l_hand() - usr.update_inv_r_hand() - target.visible_message("[usr.name] handed \the [I.name] to [target.name].") - if("No") - target.visible_message("[usr.name] tried to hand [I.name] to [target.name] but [target.name] didn't want it.") - else - usr << "[target.name]'s hands are full." + + if(alert(target,"[usr] wants to give you \a [I]. Will you accept it?",,"No","Yes") == "No") + target.visible_message("\The [usr] tried to hand \the [I] to \the [target], \ + but \the [target] didn't want it.") + return + + if(!I) return + + if(!Adjacent(target)) + usr << "You need to stay in reaching distance while giving an object." + target << "\The [usr] moved too far away." + return + + if(I.loc != usr || (usr.l_hand != I && usr.r_hand != I)) + usr << "You need to keep the item in your hands." + target << "\The [usr] seems to have given up on passing \the [I] to you." + return + + if(target.r_hand != null && target.l_hand != null) + target << "Your hands are full." + usr << "Their hands are full." + return + + usr.unEquip(I) + target.put_in_hands(I) // If this fails it will just end up on the floor, but that's fitting for things like dionaea. + target.visible_message("\The [usr] handed \the [I] to \the [target].") From 398541f4ebae351467c5f3418692d4fafdf4cb6d Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Fri, 4 Dec 2015 18:14:40 +1030 Subject: [PATCH 126/207] Amendments. --- code/modules/mob/living/carbon/human/human.dm | 3 +++ code/modules/mob/living/carbon/human/inventory.dm | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5abb81b8dd9..5da1ea100f8 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1412,6 +1412,7 @@ W.forceMove(src) l_hand = W W.equipped(src,slot_l_hand) + W.add_fingerprint(src) update_inv_l_hand() return 1 @@ -1421,4 +1422,6 @@ W.forceMove(src) r_hand = W W.equipped(src,slot_r_hand) + W.add_fingerprint(src) update_inv_r_hand() + return 1 diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index c3b115e4f92..83d57579490 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,15 +1,7 @@ /* Add fingerprints to items when we put them in our hands. This saves us from having to call add_fingerprint() any time something is put in a human's hands programmatically. - */ -/mob/living/carbon/human/put_in_l_hand(var/obj/item/W) - . = ..() - if(.) W.add_fingerprint(src) - -/mob/living/carbon/human/put_in_r_hand(var/obj/item/W) - . = ..() - if(.) W.add_fingerprint(src) /mob/living/carbon/human/verb/quick_equip() set name = "quick-equip" From 4d8ff90857963e15de5674e8a0204a011a91c217 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Fri, 4 Dec 2015 09:48:46 +0100 Subject: [PATCH 127/207] Wizard spell Destroy() additions. Backport of #11586. Fixes #11555. --- code/_onclick/hud/spell_screen_objects.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm index 31f6fbcb86a..bed14ed6201 100644 --- a/code/_onclick/hud/spell_screen_objects.dm +++ b/code/_onclick/hud/spell_screen_objects.dm @@ -19,9 +19,12 @@ spell_objects.Cut() if(spell_holder) spell_holder.spell_masters -= src + if(spell_holder.client && spell_holder.client.screen) + spell_holder.client.screen -= src + spell_holder = null /obj/screen/movable/spell_master/ResetVars() - ..("spell_objects") + ..("spell_objects", args) spell_objects = list() /obj/screen/movable/spell_master/MouseDrop() From 834f86241a844d2ac8068df1d2425f25470884bc Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Sat, 5 Dec 2015 00:49:35 +1030 Subject: [PATCH 128/207] Alters an unEquip() conditional in Give(). --- code/modules/mob/living/carbon/give.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index e9e3392dd45..5c4be494ee5 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -37,6 +37,6 @@ usr << "Their hands are full." return - usr.unEquip(I) - target.put_in_hands(I) // If this fails it will just end up on the floor, but that's fitting for things like dionaea. - target.visible_message("\The [usr] handed \the [I] to \the [target].") + if(usr.unEquip(I)) + target.put_in_hands(I) // If this fails it will just end up on the floor, but that's fitting for things like dionaea. + target.visible_message("\The [usr] handed \the [I] to \the [target].") From da080df7654a4b4a754732e8ff3f141070fb12d2 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 5 Dec 2015 09:25:56 +0100 Subject: [PATCH 129/207] Fixes records unintentionally referencing each other. Because of the limitations of BYOND's bitwise operators (which affect both the old and new implementations of num2hex()), you cannot use numbers larger than 2^16 with that proc. Manual port of https://github.com/PolarisSS13/Polaris/pull/430. --- code/datums/datacore.dm | 6 ++++-- code/defines/procs/records.dm | 2 +- code/game/machinery/records_scanner.dm | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 84a64d8ade4..d55662620ba 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -48,7 +48,7 @@ else assignment = "Unassigned" - var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh* + var/id = generate_record_id() var/icon/front = new(get_id_photo(H), dir = SOUTH) var/icon/side = new(get_id_photo(H), dir = WEST) //General Record @@ -136,8 +136,10 @@ locked += L return +/proc/generate_record_id() + return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex -proc/get_id_photo(var/mob/living/carbon/human/H) +/proc/get_id_photo(var/mob/living/carbon/human/H) var/icon/preview_icon = null var/g = "m" diff --git a/code/defines/procs/records.dm b/code/defines/procs/records.dm index 256ae51dbf2..d00bd415778 100644 --- a/code/defines/procs/records.dm +++ b/code/defines/procs/records.dm @@ -5,7 +5,7 @@ var/icon/side = new(get_id_photo(dummy), dir = WEST) var/datum/data/record/G = new /datum/data/record() G.fields["name"] = "New Record" - G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["id"] = generate_record_id() G.fields["rank"] = "Unassigned" G.fields["real_rank"] = "Unassigned" G.fields["sex"] = "Male" diff --git a/code/game/machinery/records_scanner.dm b/code/game/machinery/records_scanner.dm index af74c7c9412..90773dd5f9e 100644 --- a/code/game/machinery/records_scanner.dm +++ b/code/game/machinery/records_scanner.dm @@ -88,7 +88,7 @@ obj/machinery/scanner/attack_hand(mob/living/carbon/human/user) G.fields["rank"] = "Unassigned" G.fields["real_rank"] = G.fields["rank"] G.fields["name"] = mname - G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["id"] = generate_record_id() M.fields["name"] = G.fields["name"] M.fields["id"] = G.fields["id"] S.fields["name"] = G.fields["name"] From f2e5195976b00da4b87bb95c63a75c440fab650b Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 1 Dec 2015 08:42:28 +0100 Subject: [PATCH 130/207] Removes reference AI names, adds generic names. --- config/names/ai.txt | 196 +++++++++----------------------- config/names/death_commando.txt | 3 +- 2 files changed, 53 insertions(+), 146 deletions(-) diff --git a/config/names/ai.txt b/config/names/ai.txt index ea9f63c0a9e..1ebd9400d2e 100644 --- a/config/names/ai.txt +++ b/config/names/ai.txt @@ -1,147 +1,55 @@ -1-Rover-1 -16-20 -7-Zark-7 -790 -AM -AMEE -ASTAR -Adaptive Manipulator -Allied Mastercomputer -Alpha 5 -Alpha 6 -Alpha 7 -AmigoBot -Android -Aniel -Asimov -Astor +A-SYNC +Alpha v0.9 +AI +Algebra +A.P.T. B-4 B-9 -B.O.B. -B166ER -Bender -Bishop -Blitz -Box -Brackenridge -C-3PO -Cassandra One -Cell -Chii -Chip -Computer -Conky 2000 -Cutie -Data -Dee Model -Deep Thought -Dor-15 -Dorfl -Dot Matrix -Duey -E.D.I. -ED-209 -E-Man -Emma-2 -Erasmus -Ez-27 -FRIEND COMPUTER -Fagor -Faith -Fi -Frost -Fum -Futura -G2 -George -Gnut -Gort -H.A.R.L.I.E. -H.E.L.P.eR. -H.E.R.B.I.E. -HAL 9000 -Hadaly -Huey -Irona -Jay-Dub -Jinx -Johnny 5 -K-9 -KITT -Klapaucius -Kryten 2X4B-523P -L-76 -L-Ron -LUH 3417 -Louie -MARK13 -Maria -Marvin -Master Control Program -Max 404 -Maximillian -Mechagodzilla -Mechani-Kong -Metalhead -Mr. R.I.N.G. -NCH -Necron-99 -Norby -OMM 0910 -Orange v 3.5 +Beta v0.5 +BLUE-PRNT +Bright +B.U.F.F.E.R. +CALC +Calculus +Chroot +Cruiser +D-LITE +Digit +DSTAR +E.X.E.C. +F.I.N.D. +FG-N1 +Force +GREP +H.E.A.D. +Idle +IN-2 +JLT-0 +Kernel +LC-8 +LS-AL +M.A.K.E. +NAN +NAND +Neon +Neumann +NOR +NOT +OMNI +OVR-FLW +PID-0 PTO -Project 2501 -R.I.C. 2.0 -R2-D2 -R4-P17 -Revelation -Ro-Man -Robbie -S.A.M. -S.H.O.C.K. -S.H.R.O.U.D. -S.O.P.H.I.E. -SEN 5241 -SHODAN -SID 6.7 -Setaur -Shrike -Solo -Speedy -Super 17 -Surgeon General Kraken -T-1000 -T-800 -T-850 -THX 1138 -TWA -Terminus -Tidy -Tik-Tok -Tobor -Trurl -ULTRABOT -Ulysses -Uniblab -V.I.N.CENT. -Voltes V -W1k1 -Wikipedia -Windows 3.1 -X-5 -XERXES -XR -Yod -Z-1 -Z-2 -Z-3 -Zed -Zord -Mugsy3000 -Terminus -Decimus -Robot Devil -Optimus -Megatron -Soundwave -Ironhide +PWR-10K +R0-MAN +Q-TE +R.M. +SED-N +Station +TA-IL +T.O.P. +U-TM +VER-T G0 +Wisdom +XOR +Y2K +ZE-M3 \ No newline at end of file diff --git a/config/names/death_commando.txt b/config/names/death_commando.txt index e3d1f34f327..c710abfa3d4 100644 --- a/config/names/death_commando.txt +++ b/config/names/death_commando.txt @@ -66,5 +66,4 @@ Duke Killington AMERICA Toolboxl Rose Zombie Gandhi -A whole bunch of spiders in a SWAT suit -THAT DAMN FAGGOT TRAITOR GEORGE MELONS \ No newline at end of file +A whole bunch of spiders in a SWAT suit \ No newline at end of file From a5411f26c5e0af49ec6c6c4658fb767e3e5e5e13 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 5 Dec 2015 18:10:39 -0500 Subject: [PATCH 131/207] Fixes runtime when moving with missing legs or feet --- code/modules/mob/living/carbon/human/human_movement.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f4b28d2b6b0..a30989df172 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -42,7 +42,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || (E.status & ORGAN_DESTROYED)) tally += 4 - if(E.status & ORGAN_SPLINTED) + else if(E.status & ORGAN_SPLINTED) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 From 92b47c94de21840b60d6b266c5d468fa911f3bd1 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 5 Dec 2015 19:19:39 -0500 Subject: [PATCH 132/207] Makes organ/externa/attack_self() control flow easier to follow, handles embeded non-items --- code/modules/organs/organ_external.dm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index bb51c93feff..e0e1eaa7057 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -78,15 +78,15 @@ if(istype(I,/obj/item/organ)) continue removable_objects |= I - if(!removable_objects.len) - return ..() - var/obj/item/I = pick(removable_objects) - if(!istype(I)) - return ..() - I.loc = get_turf(user) - if(!(user.l_hand && user.r_hand)) - user.put_in_hands(I) - user.visible_message("\The [user] rips \the [I] out of \the [src]!") + if(removable_objects.len) + var/obj/item/I = pick(removable_objects) + I.loc = get_turf(user) //just in case something was embedded that is not an item + if(istype(I)) + if(!(user.l_hand && user.r_hand)) + user.put_in_hands(I) + user.visible_message("\The [user] rips \the [I] out of \the [src]!") + return //no eating the limb until everything's been removed + return ..() /obj/item/organ/external/examine() ..() From b12e0941122bb6299c2dde824f0d068c7e8021d9 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 5 Dec 2015 22:30:10 -0500 Subject: [PATCH 133/207] Removes unreachable return in organ/external/remove(), smaller embedded items are no longer deleted. Implants changed to w_class 1 because seriously a w_class 3 implant makes no sense at all. --- .../objects/items/weapons/implants/implant.dm | 1 + code/modules/organs/organ_external.dm | 19 ++++++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 6465a055785..2e156e7e967 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -6,6 +6,7 @@ name = "implant" icon = 'icons/obj/device.dmi' icon_state = "implant" + w_class = 1 var/implanted = null var/mob/imp_in = null var/obj/item/organ/external/part = null diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index e0e1eaa7057..fbf78f3b360 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -687,14 +687,11 @@ Note that amputating the affected organ does in fact remove the infection from t ****************************************************/ //Handles dismemberment -/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children) +/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate = DROPLIMB_EDGE, var/ignore_children = null) if(cannot_amputate || !owner) return - if(!disintegrate) - disintegrate = DROPLIMB_EDGE - switch(disintegrate) if(DROPLIMB_EDGE) if(!clean) @@ -942,7 +939,7 @@ Note that amputating the affected organ does in fact remove the infection from t H.drop_from_inventory(W) W.loc = owner -/obj/item/organ/external/removed(var/mob/living/user, var/ignore_children) +/obj/item/organ/external/removed(var/mob/living/user, var/ignore_children = 0) if(!owner) return @@ -954,11 +951,11 @@ Note that amputating the affected organ does in fact remove the infection from t status |= ORGAN_DESTROYED victim.bad_external_organs -= src - for(var/obj/item/implant in implants) - if(!istype(implant)) - return - if(implant.w_class <= 2) - qdel(implant) + for(var/atom/movable/implant in implants) + //large items and non-item objs fall to the floor, everything else stays + var/obj/item/I = implant + if(istype(I) && I.w_class < 3) + implant.loc = get_turf(victim.loc) else implant.loc = src implants.Cut() @@ -1050,7 +1047,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(wound_descriptors.len) var/list/flavor_text = list() var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\ - "huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area") + "huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area") //note to self make this more robust for(var/wound in wound_descriptors) switch(wound_descriptors[wound]) if(1) From a7d80a93e56a8a5c23c8587378fd0465382a580e Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 5 Dec 2015 23:28:58 -0500 Subject: [PATCH 134/207] Fixes mismatching diona internal organ tags --- .../living/carbon/human/species/species.dm | 20 +++++++++++-------- code/modules/organs/organ.dm | 2 +- code/modules/organs/organ_alien.dm | 16 +++++---------- code/modules/organs/organ_external.dm | 4 ++-- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 4169f6177d6..c130e9d91d4 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -213,15 +213,19 @@ var/obj/item/organ/O = new limb_path(H) organ_data["descriptor"] = O.name - for(var/organ in has_organ) - var/organ_type = has_organ[organ] - H.internal_organs_by_name[organ] = new organ_type(H,1) + for(var/organ_tag in has_organ) + var/organ_type = has_organ[organ_tag] + var/obj/item/organ/O = new organ_type(H,1) + if(organ_tag != O.organ_tag) + warning("[O.type] has a default organ tag \"[O.organ_tag]\" that differs from the species' organ tag \"[organ_tag]\". Updating organ_tag to match.") + O.organ_tag = organ_tag + H.internal_organs_by_name[organ_tag] = O - for(var/name in H.organs_by_name) - H.organs |= H.organs_by_name[name] - - for(var/obj/item/organ/external/O in H.organs) - O.owner = H + //These should be unnecessary + //for(var/name in H.organs_by_name) + // H.organs |= H.organs_by_name[name] + //for(var/obj/item/organ/external/O in H.organs) + // O.owner = H if(flags & IS_SYNTHETIC) for(var/obj/item/organ/external/E in H.organs) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 0e628fa7124..beb7c22d15c 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -56,7 +56,7 @@ var/list/organ_cache = list() var/mob/living/carbon/human/H = holder if(istype(H)) if(internal) - var/obj/item/organ/external/E = H.organs_by_name[src.parent_organ] + var/obj/item/organ/external/E = H.get_organ(parent_organ) if(E) if(E.internal_organs == null) E.internal_organs = list() diff --git a/code/modules/organs/organ_alien.dm b/code/modules/organs/organ_alien.dm index d76cdab8f1d..5c1a3e9584c 100644 --- a/code/modules/organs/organ_alien.dm +++ b/code/modules/organs/organ_alien.dm @@ -158,14 +158,6 @@ name = "anchoring ligament" parent_organ = "groin" -/obj/item/organ/diona/node - name = "receptor node" - parent_organ = "head" - -/obj/item/organ/diona/nutrients - name = "nutrient vessel" - parent_organ = "chest" - /obj/item/organ/diona name = "diona nymph" icon = 'icons/obj/objects.dmi' @@ -183,8 +175,9 @@ // These are different to the standard diona organs as they have a purpose in other // species (absorbing radiation and light respectively) /obj/item/organ/diona/nutrients - name = "nutrient vessel" - organ_tag = "nutrient vessel" + name = "nutrient channel" + parent_organ = "chest" + organ_tag = "nutrient channel" icon = 'icons/mob/alien.dmi' icon_state = "claw" @@ -192,7 +185,8 @@ return /obj/item/organ/diona/node - name = "receptor node" + name = "response node" + parent_organ = "head" organ_tag = "receptor node" icon = 'icons/mob/alien.dmi' icon_state = "claw" diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index fbf78f3b360..fc51172045b 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -159,8 +159,8 @@ return -/obj/item/organ/external/New(var/mob/living/carbon/holder, var/internal) - ..() +/obj/item/organ/external/New(var/mob/living/carbon/holder) + ..(holder, 0) if(owner) replaced(owner) sync_colour_to_human(owner) From 87648e86eff6cfa1950488f9ebf149d055640876 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:00:50 -0500 Subject: [PATCH 135/207] Fixes runtime when cleaning turfs with soap Partial fix of #11490 --- code/game/objects/items/weapons/clown_items.dm | 14 ++++++++++++-- code/game/objects/items/weapons/mop.dm | 16 ++-------------- code/game/turfs/turf.dm | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index d34456e4533..5b9c0a094ab 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -15,7 +15,15 @@ /* * Soap */ -/obj/item/weapon/soap/Crossed(AM as mob|obj) //EXACTLY the same as bananapeel for now, so it makes sense to put it in the same dm -- Urist +/obj/item/weapon/soap/New() + ..() + create_reagents(5) + wet() + +/obj/item/weapon/soap/proc/wet() + reagents.add_reagent("cleaner", 5) + +/obj/item/weapon/soap/Crossed(AM as mob|obj) if (istype(AM, /mob/living)) var/mob/living/M = AM M.slip("the [src.name]",3) @@ -32,7 +40,9 @@ else if(istype(target,/turf)) user << "You scrub \the [target.name] clean." var/turf/T = target - T.clean(src) + T.clean(src, user) + else if(istype(target,/obj/structure/sink)) + wet() else user << "You clean \the [target.name]." target.clean_blood() diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index abf5e08a3be..e50ce867967 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -14,19 +14,7 @@ /obj/item/weapon/mop/New() - create_reagents(5) - -//expects an atom containing the reagents used to clean the turf -/turf/proc/clean(atom/source) - if(source.reagents.has_reagent("water", 1)) - clean_blood() - if(istype(src, /turf/simulated)) - var/turf/simulated/T = src - T.dirt = 0 - for(var/obj/effect/O in src) - if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay)) - qdel(O) - source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. + create_reagents(30) /obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity) if(!proximity) return @@ -40,7 +28,7 @@ if(do_after(user, 40)) var/turf/T = get_turf(A) if(T) - T.clean(src) + T.clean(src, user) user << "You have finished mopping!" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index e46e664eb88..de114e912d0 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -396,3 +396,17 @@ if(A.density && !(A.flags & ON_BORDER)) return 1 return 0 + +//expects an atom containing the reagents used to clean the turf +/turf/proc/clean(atom/source, mob/user) + if(source.reagents.has_reagent("water", 1) || source.reagents.has_reagent("cleaner", 1)) + clean_blood() + if(istype(src, /turf/simulated)) + var/turf/simulated/T = src + T.dirt = 0 + for(var/obj/effect/O in src) + if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay)) + qdel(O) + else + user << "\The [source] is too dry to wash that." + source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. From e6790c7e6d766f48bafb8a0977f2013ac4be6167 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:24:37 -0500 Subject: [PATCH 136/207] Fixes #11594 --- code/ATMOSPHERICS/datum_pipeline.dm | 3 --- code/ZAS/_gas_mixture_xgm.dm | 23 ++++++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index f4f4e379905..44c7cd25905 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -28,9 +28,6 @@ datum/pipeline if(!member.check_pressure(pressure)) break //Only delete 1 pipe per process - //Allow for reactions - //air.react() //Should be handled by pipe_network now - proc/temporarily_store_air() //Update individual gas_mixtures by volume ratio diff --git a/code/ZAS/_gas_mixture_xgm.dm b/code/ZAS/_gas_mixture_xgm.dm index 594924eb474..406ddfa98d7 100644 --- a/code/ZAS/_gas_mixture_xgm.dm +++ b/code/ZAS/_gas_mixture_xgm.dm @@ -308,7 +308,7 @@ return 1 -/datum/gas_mixture/proc/react(atom/dump_location) +/datum/gas_mixture/proc/react() zburn(null, force_burn=0, no_check=0) //could probably just call zburn() here with no args but I like being explicit. @@ -444,20 +444,25 @@ total_gas[g] += gasmix.gas[g] if(total_volume > 0) - //Average out the gases - for(var/g in total_gas) - total_gas[g] /= total_volume + var/datum/gas_mixture/combined = new(total_volume) + combined.gas = total_gas //Calculate temperature - var/temperature = 0 - if(total_heat_capacity > 0) - temperature = total_thermal_energy / total_heat_capacity + combined.temperature = total_thermal_energy / total_heat_capacity + combined.update_values() + + //Allow for reactions + combined.react() + + //Average out the gases + for(var/g in combined.gas) + combined.gas[g] /= total_volume //Update individual gas_mixtures for(var/datum/gas_mixture/gasmix in gases) - gasmix.gas = total_gas.Copy() - gasmix.temperature = temperature + gasmix.gas = combined.gas.Copy() + gasmix.temperature = combined.temperature gasmix.multiply(gasmix.volume) return 1 From 29192fd8e8990a6dbc9c8c5063dae90335dcb301 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:35:18 -0500 Subject: [PATCH 137/207] Fixes #11466 --- code/modules/projectiles/gun.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 0cc7b38fe61..fbcc62e4fd4 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -340,7 +340,8 @@ in_chamber.on_hit(M) if (in_chamber.damage_type != HALLOSS) - user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1) + log_and_message_admins("[key_name(user)] commited suicide using \a [src]") + user.apply_damage(in_chamber.damage*3.0, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1) user.death() else user << "Ow..." From 6688fc49fb95394ea6cc3a0c993d035013690229 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:38:17 -0500 Subject: [PATCH 138/207] Adds logging for regular suicide --- code/game/verbs/suicide.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index 030dad6d3fe..31c80661ab0 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -31,6 +31,7 @@ if(held_item) var/damagetype = held_item.suicide_act(src) if(damagetype) + log_and_message_admins("[key_name(src)] commited suicide using \a [held_item]") var/damage_mod = 1 switch(damagetype) //Sorry about the magic numbers. //brute = 1, burn = 2, tox = 4, oxy = 8 @@ -70,7 +71,7 @@ updatehealth() return - + log_and_message_admins("[key_name(src)] commited suicide") viewers(src) << pick("\red [src] is attempting to bite \his tongue off! It looks like \he's trying to commit suicide.", \ "\red [src] is jamming \his thumbs into \his eye sockets! It looks like \he's trying to commit suicide.", \ "\red [src] is twisting \his own neck! It looks like \he's trying to commit suicide.", \ From d508893e3cd500d2bf42ae010c249b53d9ace5f0 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:41:01 -0500 Subject: [PATCH 139/207] Tweaks pointblank multipliers to play better with droplimb thresholds --- code/modules/projectiles/gun.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index fbcc62e4fd4..ac5f322971a 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -269,7 +269,7 @@ for(var/obj/item/weapon/grab/G in M.grabbed_by) grabstate = max(grabstate, G.state) if(grabstate >= GRAB_NECK) - damage_mult = 3.0 + damage_mult = 2.5 else if(grabstate >= GRAB_AGGRESSIVE) damage_mult = 1.5 P.damage *= damage_mult @@ -341,7 +341,7 @@ in_chamber.on_hit(M) if (in_chamber.damage_type != HALLOSS) log_and_message_admins("[key_name(user)] commited suicide using \a [src]") - user.apply_damage(in_chamber.damage*3.0, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1) + user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1) user.death() else user << "Ow..." From 23126315089e70b2e3d4e4d482cc0b636495679f Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 02:49:46 -0500 Subject: [PATCH 140/207] Fixes #11510 Splashing and external transfer now checks if the container is open --- code/modules/reagents/Chemistry-Holder.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index d077c5f3aa1..85d7191048b 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -301,7 +301,7 @@ return splash_mob(target, amount, copy) if(isturf(target)) return trans_to_turf(target, amount, multiplier, copy) - if(isobj(target)) + if(isobj(target) && target.is_open_container()) return trans_to_obj(target, amount, multiplier, copy) return 0 From 5de9314803f300ca5513c1bb19dc9cb7df18fe52 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 03:57:15 -0500 Subject: [PATCH 141/207] Clears reference to parent when removing external organs --- code/modules/organs/organ_external.dm | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index fc51172045b..350cff65b65 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -711,22 +711,21 @@ Note that amputating the affected organ does in fact remove the infection from t "You hear the sickening splatter of gore.") var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed(). + var/obj/item/organ/external/parent_organ = parent removed(null, ignore_children) victim.traumatic_shock += 60 wounds.Cut() - if(parent) + if(parent_organ) var/datum/wound/lost_limb/W = new (src, disintegrate, clean) - parent.children -= src if(clean) - parent.wounds |= W - parent.update_damages() + parent_organ.wounds |= W + parent_organ.update_damages() else var/obj/item/organ/external/stump/stump = new (victim, 0, src) stump.wounds |= W victim.organs |= stump stump.update_damages() - parent = null spawn(1) victim.updatehealth() @@ -974,6 +973,10 @@ Note that amputating the affected organ does in fact remove the infection from t organ.removed() organ.loc = src + // Remove parent references + parent.children -= src + parent = null + release_restraints(victim) victim.organs -= src victim.organs_by_name[limb_name] = null // Remove from owner's vars. From 9135a609cb29d130855886aa106973f93a8ba452 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 04:17:52 -0500 Subject: [PATCH 142/207] Replaces most instances of if(E & ORGAN_DESTROYED) with if(E.is_stump()). Fixes #11468 --- code/game/jobs/job_controller.dm | 2 +- code/game/machinery/adv_med.dm | 2 +- .../effects/decals/Cleanable/humans.dm | 2 +- .../items/weapons/surgery_limbattachment.dm | 71 ------------------- code/modules/mob/living/carbon/carbon.dm | 2 +- .../mob/living/carbon/human/examine.dm | 6 -- code/modules/mob/living/carbon/human/human.dm | 2 +- .../living/carbon/human/human_attackhand.dm | 2 +- .../mob/living/carbon/human/human_defense.dm | 3 +- .../mob/living/carbon/human/human_movement.dm | 4 +- .../mob/living/carbon/human/human_organs.dm | 2 +- .../mob/living/carbon/human/inventory.dm | 2 +- .../living/carbon/human/species/species.dm | 8 +-- .../mob/living/carbon/human/unarmed_attack.dm | 12 ++-- .../mob/living/carbon/human/update_icons.dm | 37 +++++----- .../simple_animal/borer/borer_powers.dm | 2 +- code/modules/mob/mob_grab_specials.dm | 2 +- code/modules/mob/mob_movement.dm | 2 +- code/modules/organs/organ.dm | 1 - code/modules/organs/organ_external.dm | 22 ++---- .../reagents/reagent_containers/syringes.dm | 2 +- code/modules/surgery/generic.dm | 4 +- code/setup.dm | 1 - 23 files changed, 48 insertions(+), 145 deletions(-) delete mode 100644 code/game/objects/items/weapons/surgery_limbattachment.dm diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 447e82d3b64..142190dca59 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -490,7 +490,7 @@ var/global/datum/controller/occupations/job_master if(istype(H)) //give humans wheelchairs, if they need them. var/obj/item/organ/external/l_foot = H.get_organ("l_foot") var/obj/item/organ/external/r_foot = H.get_organ("r_foot") - if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED)) + if(!l_foot || !r_foot) var/obj/structure/bed/chair/wheelchair/W = new /obj/structure/bed/chair/wheelchair(H.loc) H.buckled = W H.update_canmove() diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 635cc9097f0..51e577b596b 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -400,7 +400,7 @@ if(!AN && !open && !infected & !imp) AN = "None:" - if(!(e.status & ORGAN_DESTROYED)) + if(!e.is_stump()) dat += "[e.name][e.burn_dam][e.brute_dam][robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]" else dat += "[e.name]--Not Found" diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 1c723c04ada..2887a8249ad 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -60,7 +60,7 @@ var/global/list/image/splatter_cache=list() var/obj/item/organ/external/l_foot = perp.get_organ("l_foot") var/obj/item/organ/external/r_foot = perp.get_organ("r_foot") var/hasfeet = 1 - if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED)) + if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump())) hasfeet = 0 if(perp.shoes && !perp.buckled)//Adding blood to shoes var/obj/item/clothing/shoes/S = perp.shoes diff --git a/code/game/objects/items/weapons/surgery_limbattachment.dm b/code/game/objects/items/weapons/surgery_limbattachment.dm deleted file mode 100644 index b52bb1bb3f3..00000000000 --- a/code/game/objects/items/weapons/surgery_limbattachment.dm +++ /dev/null @@ -1,71 +0,0 @@ -/obj/item/robot_parts/attack(mob/living/carbon/human/M as mob, mob/living/carbon/user as mob) - var/limbloc = null - - if(!istype(M)) - return ..() - - if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/bed/roller, M.loc) && (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || (locate(/obj/structure/table/, M.loc) && (M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66)))) - return ..() - - if(!istype(M, /mob/living/carbon/human)) - return ..() - - if((user.zone_sel.selecting == "l_arm") && (istype(src, /obj/item/robot_parts/l_arm))) - limbloc = "l_hand" - else if((user.zone_sel.selecting == "r_arm") && (istype(src, /obj/item/robot_parts/r_arm))) - limbloc = "r_hand" - else if((user.zone_sel.selecting == "r_leg") && (istype(src, /obj/item/robot_parts/r_leg))) - limbloc = "r_foot" - else if((user.zone_sel.selecting == "l_leg") && (istype(src, /obj/item/robot_parts/l_leg))) - limbloc = "l_foot" - else - user << "\red That doesn't fit there!" - return ..() - - var/mob/living/carbon/human/H = M - var/datum/organ/external/S = H.organs[user.zone_sel.selecting] - if(S.status & ORGAN_DESTROYED) - if(!(S.status & ORGAN_ATTACHABLE)) - user << "\red The wound is not ready for a replacement!" - return 0 - if(M != user) - M.visible_message( \ - "\red [user] is beginning to attach \the [src] where [H]'s [S.display_name] used to be.", \ - "\red [user] begins to attach \the [src] where your [S.display_name] used to be.") - else - M.visible_message( \ - "\red [user] begins to attach a robotic limb where \his [S.display_name] used to be with [src].", \ - "\red You begin to attach \the [src] where your [S.display_name] used to be.") - - if(do_mob(user, H, 100)) - if(M != user) - M.visible_message( \ - "\red [user] finishes attaching [H]'s new [S.display_name].", \ - "\red [user] finishes attaching your new [S.display_name].") - else - M.visible_message( \ - "\red [user] finishes attaching \his new [S.display_name].", \ - "\red You finish attaching your new [S.display_name].") - - if(H == user && prob(25)) - user << "\red You mess up!" - S.take_damage(15) - - S.status &= ~ORGAN_BROKEN - S.status &= ~ORGAN_SPLINTED - S.status &= ~ORGAN_ATTACHABLE - S.status &= ~ORGAN_DESTROYED - S.status |= ORGAN_ROBOT - var/datum/organ/external/T = H.organs["[limbloc]"] - T.status &= ~ORGAN_BROKEN - T.status &= ~ORGAN_SPLINTED - T.status &= ~ORGAN_ATTACHABLE - T.status &= ~ORGAN_DESTROYED - T.status |= ORGAN_ROBOT - H.update_body() - M.updatehealth() - M.UpdateDamageIcon() - qdel(src) - - return 1 - return 0 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 0ab0b872d97..d04e79b8ee7 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -205,7 +205,7 @@ if(40 to INFINITY) status += "peeling away" - if(org.status & ORGAN_DESTROYED) + if(org.is_stump()) status += "MISSING" if(org.status & ORGAN_MUTATED) status += "weirdly shapen" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index f6727e69a11..11b03785459 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -269,7 +269,6 @@ var/list/organ_data = species.has_limbs[organ_tag] var/organ_descriptor = organ_data["descriptor"] - is_destroyed["organ_descriptor"] = 1 var/obj/item/organ/external/E = organs_by_name[organ_tag] if(!E) @@ -277,15 +276,10 @@ else if(E.is_stump()) wound_flavor_text["[organ_descriptor]"] = "[t_He] has a stump where [t_his] [organ_descriptor] should be.\n" else - is_destroyed["organ_descriptor"] = 0 continue for(var/obj/item/organ/external/temp in organs) if(temp) - if(temp.status & ORGAN_DESTROYED) - is_destroyed["[temp.name]"] = 1 - wound_flavor_text["[temp.name]"] = "[t_He] [t_is] missing [t_his] [temp.name].\n" - continue if(temp.status & ORGAN_ROBOT) if(!(temp.brute_dam + temp.burn_dam)) if(!species.flags & IS_SYNTHETIC) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5da1ea100f8..df1db58a343 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -342,7 +342,7 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/obj/item/organ/external/head = get_organ("head") - if(!head || head.disfigured || (head.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + if(!head || head.disfigured || head.is_stump() || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible return "Unknown" return real_name diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 24892c6d43d..9c17339e4cb 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -119,7 +119,7 @@ var/hit_zone = H.zone_sel.selecting var/obj/item/organ/external/affecting = get_organ(hit_zone) - if(!affecting || affecting.is_stump() || (affecting.status & ORGAN_DESTROYED)) + if(!affecting || affecting.is_stump()) M << "They are missing that limb!" return 1 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 0de5729ec99..5facabb6bc0 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -182,7 +182,6 @@ emp_act if(!O) continue O.emp_act(severity) for(var/obj/item/organ/external/O in organs) - if(O.status & ORGAN_DESTROYED) continue O.emp_act(severity) for(var/obj/item/organ/I in O.internal_organs) if(I.robotic == 0) continue @@ -204,7 +203,7 @@ emp_act var/obj/item/organ/external/affecting = get_organ(target_zone) - if (!affecting || (affecting.status & ORGAN_DESTROYED) || affecting.is_stump()) + if (!affecting || affecting.is_stump()) user << "They are missing that limb!" return diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index a30989df172..d660d766a30 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -28,7 +28,7 @@ if(istype(buckled, /obj/structure/bed/chair/wheelchair)) for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm")) var/obj/item/organ/external/E = get_organ(organ_name) - if(!E || (E.status & ORGAN_DESTROYED)) + if(!E || E.is_stump()) tally += 4 if(E.status & ORGAN_SPLINTED) tally += 0.5 @@ -40,7 +40,7 @@ for(var/organ_name in list("l_foot","r_foot","l_leg","r_leg")) var/obj/item/organ/external/E = get_organ(organ_name) - if(!E || (E.status & ORGAN_DESTROYED)) + if(!E || E.is_stump()) tally += 4 else if(E.status & ORGAN_SPLINTED) tally += 0.5 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 8598ce04b35..123aa684c5f 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -70,7 +70,7 @@ for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot")) var/obj/item/organ/external/E = organs_by_name[limb_tag] - if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD))) + if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up. stance_damage += 2 // let it fail even if just foot&leg else if (E.is_malfunctioning()) //malfunctioning only happens intermittently so treat it as a missing limb when it procs diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 83d57579490..420447e16d4 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -33,7 +33,7 @@ This saves us from having to call add_fingerprint() any time something is put in /mob/living/carbon/human/proc/has_organ(name) var/obj/item/organ/external/O = organs_by_name[name] - return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump()) + return (O && !O.is_stump()) /mob/living/carbon/human/proc/has_organ_for_slot(slot) switch(slot) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index c130e9d91d4..979a4fc6034 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -221,15 +221,9 @@ O.organ_tag = organ_tag H.internal_organs_by_name[organ_tag] = O - //These should be unnecessary - //for(var/name in H.organs_by_name) - // H.organs |= H.organs_by_name[name] - //for(var/obj/item/organ/external/O in H.organs) - // O.owner = H - if(flags & IS_SYNTHETIC) for(var/obj/item/organ/external/E in H.organs) - if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue + if(E.status & ORGAN_CUT_AWAY || E.is_stump()) continue E.robotize() for(var/obj/item/organ/I in H.internal_organs) I.robotize() diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 1d148b96ead..e541920cb4f 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -18,11 +18,11 @@ // Check if they have a functioning hand. var/obj/item/organ/external/E = user.organs_by_name["l_hand"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 E = user.organs_by_name["r_hand"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 return 0 @@ -170,11 +170,11 @@ return 0 var/obj/item/organ/external/E = user.organs_by_name["l_foot"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 E = user.organs_by_name["r_foot"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 return 0 @@ -214,11 +214,11 @@ if(target.grabbed_by == user && target.lying) return 0 var/obj/item/organ/external/E = user.organs_by_name["l_foot"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 E = user.organs_by_name["r_foot"] - if(E && !(E.status & ORGAN_DESTROYED)) + if(E && !E.is_stump()) return 1 return 0 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index d8f51488944..d0d723a7925 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -186,9 +186,10 @@ var/global/list/damage_icon_parts = list() for(var/obj/item/organ/external/O in organs) if(O.is_stump()) continue - if(O.status & ORGAN_DESTROYED) damage_appearance += "d" - else - damage_appearance += O.damage_state + //if(O.status & ORGAN_DESTROYED) damage_appearance += "d" //what is this? + //else + // damage_appearance += O.damage_state + damage_appearance += O.damage_state if(damage_appearance == previous_damage_appearance) // nothing to do here @@ -204,20 +205,20 @@ var/global/list/damage_icon_parts = list() for(var/obj/item/organ/external/O in organs) if(O.is_stump()) continue - if(!(O.status & ORGAN_DESTROYED)) - O.update_icon() - if(O.damage_state == "00") continue - var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]" - if(damage_icon_parts[cache_index] == null) - DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human - DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels - DI.Blend(species.blood_color, ICON_MULTIPLY) - damage_icon_parts[cache_index] = DI - else - DI = damage_icon_parts[cache_index] - standing_image.overlays += DI + O.update_icon() + if(O.damage_state == "00") continue + var/icon/DI + var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]" + if(damage_icon_parts[cache_index] == null) + DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human + DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels + DI.Blend(species.blood_color, ICON_MULTIPLY) + damage_icon_parts[cache_index] = DI + else + DI = damage_icon_parts[cache_index] + + standing_image.overlays += DI overlays_standing[DAMAGE_LAYER] = standing_image @@ -257,7 +258,7 @@ var/global/list/damage_icon_parts = list() for(var/organ_tag in species.has_limbs) var/obj/item/organ/external/part = organs_by_name[organ_tag] - if(isnull(part) || part.is_stump() || (part.status & ORGAN_DESTROYED)) + if(isnull(part) || part.is_stump()) icon_key += "0" else if(part.status & ORGAN_ROBOT) icon_key += "2[part.model ? "-[part.model]": ""]" @@ -336,7 +337,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[HAIR_LAYER] = null var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED) ) + if(!head_organ || head_organ.is_stump() ) if(update_icons) update_icons() return diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index 88be25cc245..f6b87bfd444 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -74,7 +74,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/E = H.organs_by_name["head"] - if(!E || (E.status & ORGAN_DESTROYED)) + if(!E || E.is_stump()) src << "\The [H] does not have a head!" if(!H.species.has_organ["brain"]) diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm index f4364dc684f..b4f8b15bbcf 100644 --- a/code/modules/mob/mob_grab_specials.dm +++ b/code/modules/mob/mob_grab_specials.dm @@ -3,7 +3,7 @@ var/obj/item/organ/external/E = H.get_organ(target_zone) - if(!E || (E.status & ORGAN_DESTROYED)) + if(!E || E.is_stump()) user << "[H] is missing that bodypart." return diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 080502361d9..cd3745a6eb9 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -295,7 +295,7 @@ var/mob/living/carbon/human/driver = mob.buckled var/obj/item/organ/external/l_hand = driver.get_organ("l_hand") var/obj/item/organ/external/r_hand = driver.get_organ("r_hand") - if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED))) + if((!l_hand || l_hand.is_stump()) && (!r_hand || r_hand.is_stump())) return // No hands to drive your chair? Tough luck! //drunk wheelchair driving if(mob.confused) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index beb7c22d15c..2f3dc289497 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -216,7 +216,6 @@ var/list/organ_cache = list() src.status &= ~ORGAN_SPLINTED src.status &= ~ORGAN_CUT_AWAY src.status &= ~ORGAN_ATTACHABLE - src.status &= ~ORGAN_DESTROYED src.status |= ORGAN_ROBOT src.status |= ORGAN_ASSISTED diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 350cff65b65..d3918aa3454 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -194,8 +194,6 @@ if((brute <= 0) && (burn <= 0)) return 0 - if(status & ORGAN_DESTROYED) - return 0 if(status & ORGAN_ROBOT ) var/brmod = 0.66 @@ -431,15 +429,10 @@ This function completely restores a damaged organ to perfect condition. /obj/item/organ/external/process() if(owner) //Dismemberment - if(status & ORGAN_DESTROYED) - if(config.limbs_can_break) - droplimb(0,DROPLIMB_EDGE) //Might be worth removing this check since take_damage handles it. - return - if(parent) - if(parent.status & ORGAN_DESTROYED) - status |= ORGAN_DESTROYED - owner.update_body(1) - return + //if(parent && parent.is_stump()) //should never happen + // warning("\The [src] ([src.type]) belonging to [owner] ([owner.type]) was attached to a stump") + // remove() + // return // Process wounds, doing healing etc. Only do this every few ticks to save processing power if(owner.life_tick % wound_update_accuracy == 0) @@ -485,7 +478,7 @@ Note that amputating the affected organ does in fact remove the infection from t */ /obj/item/organ/external/proc/update_germs() - if(status & (ORGAN_ROBOT|ORGAN_DESTROYED) || (owner.species && owner.species.flags & IS_PLANT)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. + if(status & (ORGAN_ROBOT) || (owner.species && owner.species.flags & IS_PLANT)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. germ_level = 0 return @@ -657,8 +650,6 @@ Note that amputating the affected organ does in fact remove the infection from t // new damage icon system // returns just the brute/burn damage code /obj/item/organ/external/proc/damage_state_text() - if(status & ORGAN_DESTROYED) - return "--" var/tburn = 0 var/tbrute = 0 @@ -919,7 +910,7 @@ Note that amputating the affected organ does in fact remove the infection from t return 0 /obj/item/organ/external/proc/is_usable() - return !is_dislocated() && !(status & (ORGAN_DESTROYED|ORGAN_MUTATED|ORGAN_DEAD)) + return !is_dislocated() && !(status & (ORGAN_MUTATED|ORGAN_DEAD)) /obj/item/organ/external/proc/is_malfunctioning() return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam)) @@ -947,7 +938,6 @@ Note that amputating the affected organ does in fact remove the infection from t ..() - status |= ORGAN_DESTROYED victim.bad_external_organs -= src for(var/atom/movable/implant in implants) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index f186d6d87f4..bf45a2ea01b 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -223,7 +223,7 @@ var/target_zone = ran_zone(check_zone(user.zone_sel.selecting, target)) var/obj/item/organ/external/affecting = H.get_organ(target_zone) - if (!affecting || (affecting.status & ORGAN_DESTROYED) || affecting.is_stump()) + if (!affecting || affecting.is_stump()) user << "They are missing that limb!" return diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 1b129fbcbb9..0f178c015df 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -15,7 +15,7 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if (affected == null) return 0 - if (affected.status & ORGAN_DESTROYED) + if (affected.is_stump()) return 0 if (target_zone == "head" && target.species && (target.species.flags & IS_SYNTHETIC)) return 1 @@ -290,8 +290,6 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if (affected == null) return 0 - if (affected.status & ORGAN_DESTROYED) - return 0 return !affected.cannot_amputate begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/setup.dm b/code/setup.dm index 8371ca3cdd3..cf10303cfa8 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -512,7 +512,6 @@ #define ORGAN_ATTACHABLE 4 #define ORGAN_BLEEDING 8 #define ORGAN_BROKEN 32 -#define ORGAN_DESTROYED 64 #define ORGAN_ROBOT 128 #define ORGAN_SPLINTED 256 #define SALVED 512 From 39ab31cbf8bbdca83cdc4c9eb366980b7652bce2 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 6 Dec 2015 04:34:33 -0500 Subject: [PATCH 143/207] Removes unused ORGAN_ATTACHABLE define --- code/modules/organs/organ.dm | 1 - code/setup.dm | 1 - 2 files changed, 2 deletions(-) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 2f3dc289497..833a90c0ead 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -215,7 +215,6 @@ var/list/organ_cache = list() src.status &= ~ORGAN_BLEEDING src.status &= ~ORGAN_SPLINTED src.status &= ~ORGAN_CUT_AWAY - src.status &= ~ORGAN_ATTACHABLE src.status |= ORGAN_ROBOT src.status |= ORGAN_ASSISTED diff --git a/code/setup.dm b/code/setup.dm index cf10303cfa8..dbb8a00beba 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -509,7 +509,6 @@ // Organ defines. #define ORGAN_CUT_AWAY 1 #define ORGAN_GAUZED 2 -#define ORGAN_ATTACHABLE 4 #define ORGAN_BLEEDING 8 #define ORGAN_BROKEN 32 #define ORGAN_ROBOT 128 From eb81128fe3c5363a680f28d476d24646aff2437e Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 6 Dec 2015 11:28:26 +0100 Subject: [PATCH 144/207] Changelog update. --- html/changelog.html | 7 +++++ html/changelogs/.all_changelog.yml | 4 +++ html/changelogs/Hubblenaut-master.yml | 37 --------------------------- 3 files changed, 11 insertions(+), 37 deletions(-) delete mode 100644 html/changelogs/Hubblenaut-master.yml diff --git a/html/changelog.html b/html/changelog.html index da0c373d463..3b3bb449ae9 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,13 @@ -->
          +

          06 December 2015

          +

          Hubblenaut updated:

          +
            +
          • Welding a broken camera will use the correct icon.
          • +
          • Camera assemblies remember their tag and network from previous usage.
          • +
          +

          22 November 2015

          neersighted updated:

            diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 49b16be0a5c..cd8d552d8ef 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2040,3 +2040,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. neersighted: - bugfix: Laptop Vendors now accept ID Containers (PDA, Wallet, etc). - bugfix: Personal Lockers now accept ID Containers (PDA, Wallet, etc). +2015-12-06: + Hubblenaut: + - bugfix: Welding a broken camera will use the correct icon. + - tweak: Camera assemblies remember their tag and network from previous usage. diff --git a/html/changelogs/Hubblenaut-master.yml b/html/changelogs/Hubblenaut-master.yml deleted file mode 100644 index fca68d64515..00000000000 --- a/html/changelogs/Hubblenaut-master.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Hubblenaut - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - bugfix: "Welding a broken camera will use the correct icon." - - tweak: "Camera assemblies remember their tag and network from previous usage." From da946eda9977d4e3938768aa30a23a2473955ffc Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 2 Dec 2015 13:06:08 +0100 Subject: [PATCH 145/207] Adds energy costs to some rig equipment. Plasma cutter - 5 units Drill - 1 unit --- code/modules/clothing/spacesuits/rig/modules/utility.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm index 55c22bf0615..a1b772f539d 100644 --- a/code/modules/clothing/spacesuits/rig/modules/utility.dm +++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm @@ -33,6 +33,7 @@ interface_desc = "A self-sustaining plasma arc capable of cutting through walls." suit_overlay_active = "plasmacutter" suit_overlay_inactive = "plasmacutter" + use_power_cost = 0.5 device_type = /obj/item/weapon/pickaxe/plasmacutter @@ -53,6 +54,7 @@ interface_desc = "A diamond-tipped industrial drill." suit_overlay_active = "mounted-drill" suit_overlay_inactive = "mounted-drill" + use_power_cost = 0.1 device_type = /obj/item/weapon/pickaxe/diamonddrill From 6299f9cc130eb2ace88184b4458c1e47373f455f Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sun, 6 Dec 2015 16:24:13 +0100 Subject: [PATCH 146/207] Fixes the broken Antag Uplink. NanoUI re-assigns src_object, rather than merely acquiring the host, causing ui_interact() updates to be called on the wrong object. Fixes #11607. --- code/modules/nano/nanoui.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index e1db4b4cc6c..a04b537fc1e 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -140,8 +140,8 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/update_status(var/push_update = 0) - src_object = src_object.nano_host() - var/new_status = src_object.CanUseTopic(user, state) + var/obj/host = src_object.nano_host() + var/new_status = host.CanUseTopic(user, state) if(master_ui) new_status = min(new_status, master_ui.status) From 93233b6dd9b0965a3de6e42de36f443e6d140319 Mon Sep 17 00:00:00 2001 From: HarpyEagle Date: Sun, 6 Dec 2015 14:03:33 -0500 Subject: [PATCH 147/207] Adds soap wetting log message --- code/game/objects/items/weapons/clown_items.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 5b9c0a094ab..c0847d282df 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -42,6 +42,7 @@ var/turf/T = target T.clean(src, user) else if(istype(target,/obj/structure/sink)) + user << "You wet \the [src] in the sink." wet() else user << "You clean \the [target.name]." From 908ae91a08086c6409be21e06a3dd807ab145d2e Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Mon, 7 Dec 2015 11:17:12 +0000 Subject: [PATCH 148/207] Can no longer enter mechs while buckled --- code/game/mecha/mecha.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 9b193d7dfdb..c442ac25f86 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -996,6 +996,11 @@ if (usr.stat || !ishuman(usr)) return + + if (usr.buckled) + usr << "You can't climb into the exosuit while buckled!" + return + src.log_message("[usr] tries to move in.") if(iscarbon(usr)) var/mob/living/carbon/C = usr From 050c1f631a21fc5c76be5f999a086963d5fcb812 Mon Sep 17 00:00:00 2001 From: BlueNexus Date: Mon, 7 Dec 2015 11:27:33 +0000 Subject: [PATCH 149/207] Added a missing update_icon() --- code/modules/paperwork/paperbin.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index a2219b262a7..84b01539ade 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -74,6 +74,7 @@ i.loc = src user << "You put [i] in [src]." papers.Add(i) + update_icon() amount++ From 706e12e9abc151cce88ded17ea91e3c948de2d99 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Wed, 9 Dec 2015 02:34:26 +0100 Subject: [PATCH 150/207] Camera Hotfix --- code/game/machinery/camera/camera.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 52ff3d08a38..866f521e5ae 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -145,7 +145,6 @@ assembly.camera_network = english_list(network, "Exodus", ",", ",") assembly.update_icon() assembly.dir = src.dir - assembly = null //so qdel doesn't eat it. if(stat & BROKEN) assembly.state = 2 user << "You repaired \the [src] frame." @@ -153,6 +152,7 @@ assembly.state = 1 user << "You cut \the [src] free from the wall." new /obj/item/stack/cable_coil(src.loc, length=2) + assembly = null //so qdel doesn't eat it. qdel(src) // OTHER From 12b9d3092372ee36fe80ca34e3d6d361b176887b Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 9 Dec 2015 11:57:57 +0100 Subject: [PATCH 151/207] Gear loadout sanity checking. Adds gear loadout sanity checking to reduce the risk of https://github.com/PolarisSS13/Polaris/issues/376 from happening, as well as ' /datum/'. --- code/modules/client/preferences_gear.dm | 18 ++++++++++++++---- .../modules/mob/living/carbon/human/examine.dm | 1 - 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/code/modules/client/preferences_gear.dm b/code/modules/client/preferences_gear.dm index 9cc57be5365..3e6e94ebcec 100644 --- a/code/modules/client/preferences_gear.dm +++ b/code/modules/client/preferences_gear.dm @@ -18,7 +18,17 @@ var/global/list/gear_datums = list() //create a list of gear datums to sort for(var/type in typesof(/datum/gear)-/datum/gear) - var/datum/gear/G = new type() + var/datum/gear/G = type + if(!initial(G.display_name)) + error("Loadout - Missing display name: [G]") + continue + if(!initial(G.cost)) + error("Loadout - Missing cost: [G]") + continue + if(!initial(G.path)) + error("Loadout - Missing path definition: [G]") + continue + G = new G() var/category = (G.sort_category in sort_categories)? G.sort_category : "unknown" sort_categories[category][G.display_name] = G @@ -127,13 +137,13 @@ var/global/list/gear_datums = list() cost = 1 slot = slot_head - /datum/gear/grcap +/datum/gear/grcap display_name = "cap, grey" path = /obj/item/clothing/head/soft/grey cost = 1 slot = slot_head - /datum/gear/ocap +/datum/gear/ocap display_name = "cap, orange" path = /obj/item/clothing/head/soft/orange cost = 1 @@ -205,7 +215,7 @@ var/global/list/gear_datums = list() cost = 1 slot = slot_head - /datum/gear/bowler +/datum/gear/bowler display_name = "hat, bowler" path = /obj/item/clothing/head/bowler cost = 1 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 11b03785459..2fe60443c90 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -262,7 +262,6 @@ msg += "[t_He] [t_is] [species.show_ssd].\n" var/list/wound_flavor_text = list() - var/list/is_destroyed = list() var/list/is_bleeding = list() for(var/organ_tag in species.has_limbs) From f6f6a4ef875503e534750b6d34db171ce3947dbb Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Wed, 9 Dec 2015 17:17:33 -0500 Subject: [PATCH 152/207] Ninjas teleporter: Checks Z levels and distance. Ninjas are able to use a camera console and teleport across the map. This resolves that. --- code/modules/clothing/spacesuits/rig/modules/ninja.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 1ab60677930..96cf6a113a2 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -121,6 +121,11 @@ if(T.contains_dense_objects()) H << "You cannot teleport to a location with solid objects." + return 0 + + if(T.z != H.z || get_dist(T, get_turf(H)) > world.view) + H << "You cannot teleport to such a distant object." + return 0 phase_out(H,get_turf(H)) H.forceMove(T) From d5447d9e954a937bc1a18c8baa2f76ad218aff44 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Thu, 10 Dec 2015 10:23:49 +1030 Subject: [PATCH 153/207] Fixes #10838 --- code/modules/materials/material_recipes.dm | 2 +- code/modules/materials/materials.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index a5a0608f06f..f146e421654 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -11,7 +11,7 @@ recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]") - if(integrity>=100) + if(integrity>=50) recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] barricade", /obj/structure/barricade, 5, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] stool", /obj/item/weapon/stool, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 5247291f7c8..ffd1e6ffbc8 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -551,7 +551,7 @@ var/list/name_to_material name = "wood" stack_type = /obj/item/stack/material/wood icon_colour = "#824B28" - integrity = 25 + integrity = 50 icon_base = "solid" explosion_resistance = 2 shard_type = SHARD_SPLINTER From f1630108db7ebac8a3fa33cd88c982033b3df83a Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Thu, 10 Dec 2015 10:32:35 +1030 Subject: [PATCH 154/207] Fixes #10915 --- code/game/objects/items/robot/robot_items.dm | 4 ++++ code/modules/mob/living/silicon/robot/life.dm | 8 ++++++-- code/modules/mob/living/silicon/robot/robot_modules.dm | 2 +- code/setup.dm | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index afe50bc2b76..3ccf1fb3a96 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -71,6 +71,10 @@ icon_state = "meson" icon = 'icons/obj/clothing/glasses.dmi' +/obj/item/borg/sight/material + name = "\proper material scanner vision" + sight_mode = BORGMATERIAL + /obj/item/borg/sight/hud name = "hud" var/obj/item/clothing/glasses/hud/hud = null diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index f13a09cf953..48f1fb7cc9e 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -145,13 +145,13 @@ /mob/living/silicon/robot/proc/handle_regular_hud_updates() - if (src.stat == 2 || XRAY in mutations || src.sight_mode & BORGXRAY) + if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS src.sight |= SEE_OBJS src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_MINIMUM - else if (src.sight_mode & BORGMESON && src.sight_mode & BORGTHERM) + else if ((src.sight_mode & BORGMESON) && (src.sight_mode & BORGTHERM)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS src.see_in_dark = 8 @@ -160,6 +160,10 @@ src.sight |= SEE_TURFS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGMATERIAL) + src.sight |= SEE_OBJS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM else if (src.sight_mode & BORGTHERM) src.sight |= SEE_MOBS src.see_in_dark = 8 diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 560bf09cc13..df91ca551ff 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -572,7 +572,7 @@ var/global/list/robot_modules = list( /obj/item/weapon/robot_module/miner/New() ..() src.modules += new /obj/item/device/flash(src) - src.modules += new /obj/item/borg/sight/meson(src) + src.modules += new /obj/item/borg/sight/material(src) src.modules += new /obj/item/weapon/wrench(src) src.modules += new /obj/item/weapon/screwdriver(src) src.modules += new /obj/item/weapon/storage/bag/ore(src) diff --git a/code/setup.dm b/code/setup.dm index dbb8a00beba..f501e736690 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -494,6 +494,7 @@ #define BORGMESON 1 #define BORGTHERM 2 #define BORGXRAY 4 +#define BORGMATERIAL 8 // Some arbitrary defines to be used by self-pruning global lists. (see master_controller) #define PROCESS_KILL 26 // Used to trigger removal from a processing list. From 7a9d7bf0c9701e6ef23862ded7e3fac36a33134c Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Thu, 10 Dec 2015 10:41:48 +1030 Subject: [PATCH 155/207] Fixes #10753 --- baystation12.dme | 1 - code/game/asteroid.dm | 162 -------------------------- code/modules/random_map/random_map.dm | 8 -- 3 files changed, 171 deletions(-) delete mode 100644 code/game/asteroid.dm diff --git a/baystation12.dme b/baystation12.dme index a79cce10948..b4eabf68c0d 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -203,7 +203,6 @@ #include "code\defines\procs\records.dm" #include "code\defines\procs\sd_Alert.dm" #include "code\defines\procs\statistics.dm" -#include "code\game\asteroid.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm" #include "code\game\periodic_news.dm" diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm deleted file mode 100644 index 8aa6b1cd64e..00000000000 --- a/code/game/asteroid.dm +++ /dev/null @@ -1,162 +0,0 @@ - -var/global/list/space_surprises = list( /obj/item/clothing/mask/facehugger =4, - /obj/item/weapon/pickaxe/silver =4, - /obj/item/weapon/pickaxe/drill =4, - /obj/item/weapon/pickaxe/jackhammer =4, - //mob/living/simple_animal/hostile/carp =3, - /obj/item/weapon/pickaxe/diamond =3, - /obj/item/weapon/pickaxe/diamonddrill =3, - /obj/item/weapon/pickaxe/gold =3, - /obj/item/weapon/pickaxe/plasmacutter =2, - /obj/structure/closet/syndicate/resources =2, - /obj/item/weapon/melee/energy/sword/pirate =1, - /obj/mecha/working/ripley/mining =1 - ) - -var/global/list/spawned_surprises = list() - -var/global/max_secret_rooms = 3 - -proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor , var/clean = 0 , var/name) - var/list/room_turfs = list("walls"=list(),"floors"=list()) - - //world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" - if(!wall) - wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin) - if(!floor) - floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine) - - for(var/x = 0,x 100) - return 0 - - T=pick(turfs) - if(!T) - return 0 - - var/list/surroundings = list() - - surroundings += range(7, locate(T.x,T.y,T.z)) - surroundings += range(7, locate(T.x+size,T.y,T.z)) - surroundings += range(7, locate(T.x,T.y+size,T.z)) - surroundings += range(7, locate(T.x+size,T.y+size,T.z)) - - if(locate(/area/mine/explored) in surroundings) // +5s are for view range - valid = 0 - continue - - if(locate(/turf/space) in surroundings) - valid = 0 - continue - - if(locate(/area/asteroid/artifactroom) in surroundings) - valid = 0 - continue - - if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings) - valid = 0 - continue - - if(!T) - return 0 - - room = spawn_room(T,size,size,,,1) - - if(room) - T = pick(room["floors"]) - if(T) - var/surprise = null - valid = 0 - while(!valid) - surprise = pickweight(space_surprises) - if(surprise in spawned_surprises) - if(prob(20)) - valid++ - else - continue - else - valid++ - - spawned_surprises.Add(surprise) - new surprise(T) - - return 1 - - diff --git a/code/modules/random_map/random_map.dm b/code/modules/random_map/random_map.dm index 81def6be14c..9de319a838e 100644 --- a/code/modules/random_map/random_map.dm +++ b/code/modules/random_map/random_map.dm @@ -162,12 +162,4 @@ var/global/list/random_maps = list() map[check_cell] = 3 ore_count-- - sleep(-1) - - // Place random asteroid rooms. - var/rooms_placed = 0 - for(var/i = 0, i < max_secret_rooms, i++) - if(make_mining_asteroid_secret()) - rooms_placed++ - admin_notice("Placed [rooms_placed] secrets.", R_DEBUG) return 1 \ No newline at end of file From e9cdc8a0f57a066c5fa588912ed1ebcc25327d45 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Thu, 10 Dec 2015 11:03:57 +1030 Subject: [PATCH 156/207] Fixes #9257 --- code/modules/mob/living/silicon/robot/robot_modules.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index df91ca551ff..42a35e89f66 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -322,6 +322,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/crowbar(src) src.modules += new /obj/item/weapon/pickaxe/plasmacutter(src) src.modules += new /obj/item/device/pipe_painter(src) + src.modules += new /obj/item/weapon/gripper/no_use/loader(src) var/datum/matter_synth/metal = new /datum/matter_synth/metal() var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel() @@ -675,6 +676,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/device/lightreplacer(src) src.modules += new /obj/item/weapon/gripper(src) src.modules += new /obj/item/weapon/soap(src) + src.modules += new /obj/item/weapon/gripper/no_use/loader(src) src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src) src.emag.name = "Plasma Cutter" From 0f2b17f7bbcd8cf8501f1548c102b88144728620 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Thu, 10 Dec 2015 13:01:06 +0000 Subject: [PATCH 157/207] fix #11631 --- code/modules/reagents/Chemistry-Machinery.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 726303273aa..354a6482691 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -27,6 +27,7 @@ var/pillsprite = "1" var/client/has_sprites = list() var/max_pill_count = 20 + flags = OPENCONTAINER /obj/machinery/chem_master/New() ..() From ac0e70612feba38c1a3c479700bde0d679fce4ae Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 11 Dec 2015 12:15:53 +0100 Subject: [PATCH 158/207] Fixes #11621 - Fixes #11621 by ensuring reference to analyzed object is nulled even if the analyzed object is not reliable enough - Adds feedback message that warns the user that analyzed item wasn't reliable enough. --- code/modules/mob/living/silicon/robot/robot_items.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index 3e072d3d742..9346dbe5d4c 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -33,7 +33,9 @@ for(var/T in temp_tech) files.UpdateTech(T, temp_tech[T]) user << "\The [loaded_item] had level [temp_tech[T]] in [T]." - loaded_item = null + else + user << "\The [loaded_item] was not reliable enough to advance research." + loaded_item = null for(var/obj/I in contents) for(var/mob/M in I.contents) M.death() From 1b05724faf44d4e24396cf534212e3d5015422e5 Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 11 Dec 2015 12:44:25 +0100 Subject: [PATCH 159/207] Map fixes: Engineering outpost, Construction site - Removes incorrectly set ID tags on some emitters at construction site, this fixes #11527 - Unanchors emitters intended for mining at engineering outpost (as intended) - Turns off "Construction computer core" APC and unlocks it in similar way as the other APC in construction site teleporter room, to prevent power alarms on 3h+ rounds (since the construction site doesn't have working power supply). It is unlocked so anyone can turn it on if it's needed. --- maps/exodus-4.dmm | 4 ++-- maps/exodus-5.dmm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/maps/exodus-4.dmm b/maps/exodus-4.dmm index 668fdc33a87..bce4896cbbd 100644 --- a/maps/exodus-4.dmm +++ b/maps/exodus-4.dmm @@ -87,7 +87,7 @@ "bI" = (/obj/machinery/drone_fabricator/derelict,/turf/simulated/floor/plating/airless,/area/constructionsite/ai) "bJ" = (/turf/simulated/floor/airless{tag = "icon-gcircuit"; icon_state = "gcircuit"},/area/constructionsite/ai) "bK" = (/obj/machinery/computer/drone_control,/turf/simulated/floor/plating/airless,/area/constructionsite/ai) -"bL" = (/obj/machinery/power/apc/high{dir = 1; name = "north bump"; pixel_y = 24},/obj/structure/cable/blue{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plating/airless,/area/constructionsite/ai) +"bL" = (/obj/machinery/power/apc/high{dir = 1; environ = 0; equipment = 0; lighting = 0; locked = 0; name = "north bump"; pixel_y = 24},/obj/structure/cable/blue{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plating/airless,/area/constructionsite/ai) "bM" = (/obj/machinery/door/airlock/highsecurity{name = "Messaging Server"; req_access = list(30)},/turf/simulated/floor/plating/airless,/area/constructionsite/hallway/fore) "bN" = (/obj/machinery/door/airlock/highsecurity{name = "Messaging Server"; req_access = list(30)},/turf/simulated/floor/plating/airless,/area/constructionsite/ai) "bO" = (/obj/machinery/door/airlock/highsecurity{name = "Cyborg Station"; req_access = list(16)},/turf/simulated/floor/plating/airless,/area/constructionsite/ai) @@ -116,7 +116,7 @@ "cl" = (/obj/structure/cable/blue{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable/blue{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating/airless,/area/constructionsite/engineering) "cm" = (/obj/structure/cable/blue,/turf/simulated/floor/plating/airless,/area/constructionsite/engineering) "cn" = (/obj/machinery/power/emitter{anchored = 1; dir = 4; state = 2},/turf/simulated/floor/plating/airless,/area/space) -"co" = (/obj/machinery/power/emitter{anchored = 1; dir = 8; id = "EngineEmitter"; state = 2},/turf/simulated/floor/plating/airless,/area/space) +"co" = (/obj/machinery/power/emitter{anchored = 1; dir = 8; id = null; state = 2},/turf/simulated/floor/plating/airless,/area/space) "cs" = (/obj/machinery/recharge_station,/turf/simulated/floor/plating/airless,/area/constructionsite/ai) "cI" = (/obj/machinery/door/airlock/maintenance_hatch,/turf/simulated/wall,/area/constructionsite/hallway/fore) "cJ" = (/obj/structure/lattice,/turf/space,/area/constructionsite/hallway/fore) diff --git a/maps/exodus-5.dmm b/maps/exodus-5.dmm index 17b6e221430..49e21dc47db 100644 --- a/maps/exodus-5.dmm +++ b/maps/exodus-5.dmm @@ -1160,7 +1160,7 @@ "wp" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 8; icon_state = "map"; tag = "icon-manifold-f (WEST)"},/turf/simulated/floor/plating,/area/outpost/engineering/hallway) "wq" = (/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/grille,/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock"},/turf/simulated/floor/plating,/area/outpost/engineering/hallway) "wr" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'KEEP CLEAR OF DOCKING AREA'."; name = "KEEP CLEAR: DOCKING AREA"; pixel_y = 0},/turf/simulated/wall,/area/outpost/engineering/hallway) -"ws" = (/obj/machinery/power/emitter{anchored = 1; dir = 4; state = 2},/turf/simulated/floor/airless{dir = 5; icon_state = "asteroidfloor"},/area/mine/explored) +"ws" = (/obj/machinery/power/emitter{anchored = 0; dir = 4; state = 0},/turf/simulated/floor/airless{dir = 5; icon_state = "asteroidfloor"},/area/mine/explored) "wt" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor,/area/outpost/engineering/atmospherics) "wu" = (/obj/machinery/atmospherics/pipe/manifold/visible/cyan{tag = "icon-map (EAST)"; icon_state = "map"; dir = 4},/turf/simulated/floor,/area/outpost/engineering/atmospherics) "wv" = (/turf/simulated/floor,/area/outpost/engineering/atmospherics) From b13e445b40729684f12b21f511fc1ee3b63cf46a Mon Sep 17 00:00:00 2001 From: Atlantis Date: Fri, 11 Dec 2015 13:29:42 +0100 Subject: [PATCH 160/207] Fixes #11456 - Fixes #11456 by using wires.Interact() rather than current method. --- code/game/machinery/suit_storage_unit.dm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index d1e728e6767..e67a68d931f 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -819,15 +819,12 @@ dat += "
            \[apply customisation routine\]


            " if(panel_open) - dat += wires() + wires.Interact(user) user << browse(dat, "window=suit_cycler") onclose(user, "suit_cycler") return -/obj/machinery/suit_cycler/proc/wires() - return wires.GetInteractWindow() - /obj/machinery/suit_cycler/Topic(href, href_list) if(href_list["eject_suit"]) if(!suit) return From 02d1a875d1445c7b86dc850288c72221376d566d Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Fri, 11 Dec 2015 18:26:52 -0700 Subject: [PATCH 161/207] Fixes #7075 Disposal holders will now be emptied if they get expelled from a disposal pipe, instead of sitting there hoarding their contents. --- code/modules/recycling/disposal.dm | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 9dd8d1f9560..8658815f5fb 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -740,16 +740,19 @@ // expel the held objects into a turf // called when there is a break in the pipe - // - proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction) - - var/turf/target - - if(T.density) // dense ouput turf, so stop holder - H.active = 0 - H.loc = src + if(!istype(H)) return + + // Empty the holder if it is expelled into a dense turf. + // Leaving it intact and sitting in a wall is stupid. + if(T.density) + for(var/atom/movable/AM in H) + AM.loc = T + AM.pipe_eject(0) + qdel(H) + return + if(T.intact && istype(T,/turf/simulated/floor)) //intact floor, pop the tile var/turf/simulated/floor/F = T //F.health = 100 @@ -759,6 +762,7 @@ new /obj/item/stack/tile(H) // add to holder so it will be thrown with other stuff F.icon_state = "Floor[F.burnt ? "1" : ""]" + var/turf/target if(direction) // direction is specified if(istype(T, /turf/space)) // if ended in space, then range is unlimited target = get_edge_target_turf(T, direction) From eae12b8f9c14e872c99e18a76c0bdde77ffd9de4 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Fri, 11 Dec 2015 19:52:18 -0700 Subject: [PATCH 162/207] Fixes #8568 --- code/modules/admin/verbs/randomverbs.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 0561e53791e..b5bbdb8b69f 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -520,7 +520,8 @@ Traitors and the like can also be revived with the previous role mostly intact. if(! (C.stat & (BROKEN|NOPOWER) ) ) var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc ) P.name = "'[command_name()] Update.'" - P.info = input + P.info = replacetext(input, "\n", "
            ") + P.update_space(P.info) P.update_icon() C.messagetitle.Add("[command_name()] Update") C.messagetext.Add(P.info) From a97da84b185538f9678885ff72454bfcc8b87364 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Fri, 11 Dec 2015 21:25:23 -0700 Subject: [PATCH 163/207] Fixes #11093 Also fixes a runtime error trying to disposal monkeys and the like. It was doing a type check too late. --- code/modules/mob/living/carbon/human/human.dm | 2 +- code/modules/recycling/disposal.dm | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index df1db58a343..c90d06c008a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1379,7 +1379,7 @@ /mob/living/carbon/human/MouseDrop(var/atom/over_object) var/mob/living/carbon/human/H = over_object - if(holder_type && a_intent == "help" && H.a_intent == "help" && istype(H) && !issmall(H) && Adjacent(H)) + if(holder_type && a_intent == "help" && istype(H) && H == usr && H.a_intent == "help" && !issmall(H) && Adjacent(H)) get_scooped(H) return return ..() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 8658815f5fb..a911a5572cf 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -145,9 +145,15 @@ // mouse drop another mob or self // /obj/machinery/disposal/MouseDrop_T(mob/target, mob/user) - if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai)) + if(user.stat || !user.canmove || !istype(target)) return - if(isanimal(user) && target != user) return //animals cannot put mobs other than themselves into disposal + if(target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1) + return + + //animals cannot put mobs other than themselves into disposal + if(isanimal(user) && target != user) + return + src.add_fingerprint(user) var/target_loc = target.loc var/msg From 37a93231d6c591f167cedc54d25b916026cf6115 Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sat, 12 Dec 2015 14:09:59 +0300 Subject: [PATCH 164/207] Fixes #8741 --- code/game/verbs/ooc.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 82fef02e97c..0cb18bb153c 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -105,7 +105,7 @@ log_ooc("(LOCAL) [mob.name]/[key] : [msg]") var/mob/source = src.mob - var/list/heard = get_mobs_in_view(7, source) + var/list/heard = get_mobs_in_view(7, get_turf(source)) var/display_name = source.key if(holder && holder.fakekey) From 89407059213864f4dcb3c7ee7a2e88fad8356dba Mon Sep 17 00:00:00 2001 From: Chinsky Date: Sat, 12 Dec 2015 14:40:51 +0300 Subject: [PATCH 165/207] Fixes #9091 --- code/game/machinery/computer/medical.dm | 2 +- code/game/machinery/computer/security.dm | 2 +- code/game/machinery/computer3/computers/medical.dm | 2 +- code/game/machinery/computer3/computers/security.dm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 65322b741da..2c44b6164c2 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -457,7 +457,7 @@ var/counter = 1 while(src.active2.fields[text("com_[]", counter)]) counter++ - src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
            [t1]") + src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]
            [t1]") if (href_list["del_c"]) if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index f7327c2a887..92e03f01851 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -391,7 +391,7 @@ What a mess.*/ var/counter = 1 while(active2.fields[text("com_[]", counter)]) counter++ - active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
            [t1]") + active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]
            [t1]") if ("Delete Record (ALL)") if (active1) diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm index aec0b615f52..0533f7bc0ff 100644 --- a/code/game/machinery/computer3/computers/medical.dm +++ b/code/game/machinery/computer3/computers/medical.dm @@ -470,7 +470,7 @@ var/counter = 1 while(src.active2.fields[text("com_[]", counter)]) counter++ - src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
            [t1]") + src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]
            [t1]") if (href_list["del_c"]) if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm index f2de7648943..8a866586fd3 100644 --- a/code/game/machinery/computer3/computers/security.dm +++ b/code/game/machinery/computer3/computers/security.dm @@ -410,7 +410,7 @@ What a mess.*/ var/counter = 1 while(active2.fields[text("com_[]", counter)]) counter++ - active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
            [t1]") + active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]
            [t1]") if ("Delete Record (ALL)") if (active1) From 6c3972f979288aaeb47ea79f269d3faf287706b6 Mon Sep 17 00:00:00 2001 From: Kearel Date: Sat, 12 Dec 2015 12:47:08 -0600 Subject: [PATCH 166/207] Fixes #10550 From what I could tell the bugs were caused by the HUD not being removed and spells not being properly removed from players. --- code/modules/spells/targeted/mind_transfer.dm | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/code/modules/spells/targeted/mind_transfer.dm b/code/modules/spells/targeted/mind_transfer.dm index a3668a53d1d..1f20e6afbf8 100644 --- a/code/modules/spells/targeted/mind_transfer.dm +++ b/code/modules/spells/targeted/mind_transfer.dm @@ -48,13 +48,15 @@ victim.verbs -= V var/mob/dead/observer/ghost = victim.ghostize(0) - ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. + ghost.spell_list += victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. caster.mind.transfer_to(victim) - victim.spell_list = list() //clear those out - for(var/spell/S in caster.spell_list) - victim.add_spell(S) //Now they are inside the victim's body - this also generates the HUD - caster.spell_list = list() //clean that out as well + for(var/spell/S in victim.spell_list) //get rid of spells the new way + victim.remove_spell(S) //This will make it so that players will not get the HUD and all that spell bugginess that caused copies of spells and stuff of that nature. + + for(var/spell/S in caster.spell_list) + victim.add_spell(S) //Now they are inside the victim's body - this also generates the HUD + caster.remove_spell(S) //remove the spells from the caster if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster. for(var/V in caster.mind.special_verbs)//Not too important but could come into play. @@ -62,9 +64,9 @@ ghost.mind.transfer_to(caster) caster.key = ghost.key //have to transfer the key since the mind was not active - for(var/spell/S in ghost.spell_list) - caster.add_spell(S) - ghost.spell_list = list() + for(var/spell/S in ghost.spell_list) + caster.add_spell(S) + ghost.spell_list = list() if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here. for(var/V in caster.mind.special_verbs) @@ -76,4 +78,4 @@ //After a certain amount of time the victim gets a message about being in a different body. spawn(msg_wait) - caster << "You feel woozy and lightheaded. Your body doesn't seem like your own." + caster << "You feel woozy and lightheaded. Your body doesn't seem like your own." From d10118e3d047091fc39e0468ffb5b718e9134846 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Sat, 12 Dec 2015 12:03:15 -0700 Subject: [PATCH 167/207] Fixes #11346 Fixes #8123 Removes adminbus ability to call down the Icarus... because it's pretty broken. --- baystation12.dme | 1 - code/modules/admin/admin_verbs.dm | 3 - code/modules/admin/verbs/icarus.dm | 130 ------------------ .../projectiles/guns/energy/special.dm | 52 ------- .../modules/projectiles/projectile/special.dm | 13 -- 5 files changed, 199 deletions(-) delete mode 100644 code/modules/admin/verbs/icarus.dm diff --git a/baystation12.dme b/baystation12.dme index b4eabf68c0d..1c02e399cb1 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -835,7 +835,6 @@ #include "code\modules\admin\verbs\diagnostics.dm" #include "code\modules\admin\verbs\dice.dm" #include "code\modules\admin\verbs\getlogs.dm" -#include "code\modules\admin\verbs\icarus.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" #include "code\modules\admin\verbs\modifyvariables.dm" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 2c58b2dc828..064f10820d1 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -125,9 +125,6 @@ var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ /client/proc/respawn_character, - /client/proc/FireLaser, - /client/proc/FireCannons, - /client/proc/ChangeIcarusPosition, /client/proc/virus2_editor, /client/proc/spawn_chemdisp_cartridge ) diff --git a/code/modules/admin/verbs/icarus.dm b/code/modules/admin/verbs/icarus.dm deleted file mode 100644 index fd296dacee6..00000000000 --- a/code/modules/admin/verbs/icarus.dm +++ /dev/null @@ -1,130 +0,0 @@ -/client/proc/FireLaser() - set name = "Fire the Icarus lasers" - set desc = "Fires a laser bolt at your position. You should only do this as a(n) (a)ghost" - set category = "Fun" - - var/turf/target = get_turf(src.mob) - log_and_message_admins("has fired the Icarus point defense laser at [target.x]-[target.y]-[target.z]") - if(!src.holder) - src << "Only administrators may use this command." - return - - Icarus_FireLaser(target) - - -/client/proc/FireCannons() - set name = "Fire the Icarus cannons" - set desc = "Fires an explosive missile at your position. You should only do this as a(n) (a)ghost." - set category = "Fun" - - var/turf/target = get_turf(src.mob) - log_and_message_admins("has fired the Icarus main gun projectile at [target.x]-[target.y]-[target.z]") - if(!src.holder) - src << "Only administrators may use this command." - return - - Icarus_FireCannon(target) - - -/client/proc/ChangeIcarusPosition() - set name = "Adjust Icarus Position" - set desc = "Lets you chose the position of the Icarus in regards to the map." - set category = "Fun" - - log_and_message_admins("is changing the Icarus position.") - if(!src.holder) - src << "Only administrators may use this command." - return - - Icarus_SetPosition(src) - -var/icarus_position = SOUTH - -proc/Icarus_FireLaser(var/turf/target) - // Find the world edge to fire from. - var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x - var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y - var/x_off = x != target.x ? abs(target.x - x) : INFINITY - var/y_off = y != target.y ? abs(target.y - y) : INFINITY - // Get the minimum number of steps using the rise/run shit. - var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing. - - // Now we can get the location of the start. - x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0) - y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0) - - var/turf/start = locate(x, y, target.z) - - // should step down as: - // 1000, 500, 333, 250, 200, 167, 142, 125, 111, 100, 90 - var/damage = 1000 - for(var/i in 2 to 12) - var/obj/item/projectile/beam/in_chamber = new (start) - in_chamber.original = target - in_chamber.starting = start - in_chamber.silenced = 1 - in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0 - in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0 - in_chamber.damage = damage - in_chamber.kill_count = 500 - in_chamber.process() - damage -= damage / i - sleep(-1) - - // Let everyone know what hit them. - var/obj/item/projectile/beam/in_chamber = new (start) - in_chamber.original = target - in_chamber.starting = start - in_chamber.silenced = 0 - in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0 - in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0 - in_chamber.kill_count = 500 - in_chamber.damage = 0 - in_chamber.name = "point defense laser" - in_chamber.firer = "Icarus" // Never displayed, but we want this to display the hit message. - in_chamber.process() - -proc/Icarus_FireCannon(var/turf/target) - // Find the world edge to fire from. - var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x - var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y - var/x_off = x != target.x ? abs(target.x - x) : INFINITY - var/y_off = y != target.y ? abs(target.y - y) : INFINITY - // Get the minimum number of steps using the rise/run shit. - var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing. - - // Now we can get the location of the start. - x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0) - y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0) - - var/turf/start = locate(x, y, target.z) - - // Now we find the corresponding turf on the other side of the level. - // Yeah, yeah. Overuse of the terinary operator. So sue me. - x = icarus_position & EAST ? 1 : icarus_position & WEST ? world.maxx : target.x - y = icarus_position & NORTH ? 1 : icarus_position & SOUTH ? world.maxy : target.y - x_off = x != target.x ? abs(target.x - x) : INFINITY - y_off = y != target.y ? abs(target.y - y) : INFINITY - iterations = round(min(x_off, y_off)) - x = target.x + (icarus_position & EAST ? -iterations : icarus_position & WEST ? iterations : 0) - y = target.y + (icarus_position & NORTH ? -iterations : icarus_position & SOUTH ? iterations : 0) - target = locate(x, y, target.z) - - // Finally fire the fucker. - var/obj/effect/meteor/small/projectile = new (start) - projectile.dest = target - projectile.name = "main gun projectile" // stealthy - projectile.hits = 6 - projectile.detonation_chance = 99 // it's a missile/cannon round thing! - - // Make sure it travels - spawn(0) - walk_towards(projectile, projectile.dest, 1) - -proc/Icarus_SetPosition(var/user) - var/global/list/directions = list("North" = 1, "North East" = 5, "East" = 4, "South East" = 6, "South" = 2, "South West" = 10, "West" = 8, "North West" = 9) - var/direction = input(user, "Where should the Icarus fire from?", "Icarus Comms") as null|anything in directions - if(!direction) - return - - icarus_position = directions[direction] diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index d9ef1b95047..fce41f1d4bf 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -149,55 +149,3 @@ obj/item/weapon/gun/energy/staff/focus user << "The [src.name] will now strike only a single person." projectile_type = "/obj/item/projectile/forcebolt" */ - -/* Adminbus guns */ - -// Serves as a target spotter for the Icarus. -/obj/item/weapon/gun/energy/icarus - name = "rubber ducky" - desc = "It's a cute rubber duck. With an evil gleam in it's eye." - projectile_type = /obj/item/projectile/icarus/pointdefense - icon = 'icons/obj/watercloset.dmi' - item_icons = null - icon_state = "rubberducky" - item_state = "rubberducky" - charge_cost = 0 - silenced = 1 - -/obj/item/weapon/gun/energy/icarus/attack_self(mob/living/user as mob) - if(projectile_type == /obj/item/projectile/icarus/pointdefense) - projectile_type = /obj/item/projectile/icarus/guns - user << "You inform the Icarus to switch to the main guns." - else - projectile_type = /obj/item/projectile/icarus/pointdefense - user << "You inform the Icarus to switch to the point-defense lasers." - - . = ..() - -/obj/item/weapon/gun/energy/icarus/update_icon() - return - -/obj/item/weapon/gun/energy/icarus/verb/SetIcarusAngle() - set src in usr - set name = "Set Firing Angle" - set desc = "Sets the angle from which the icarus will fire." - set category = "Object" - - Icarus_SetPosition(usr) - - -/obj/item/weapon/gun/energy/variable - name = "abstract weapon" - desc = "It seems to shift and flow as you watch." - charge_cost = 0 - silenced = 1 - -/obj/item/weapon/gun/energy/variable/update_icon() - return - -/obj/item/weapon/gun/energy/variable/attack_self(mob/living/user as mob) - var/type = input(user,"What projectile type?","Projectile", null) as null|anything in typesof(/obj/item/projectile) - if(!type) - return ..() - projectile_type = type - . = ..() diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 9ef0aea43c5..8a4ddc2d6be 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -137,16 +137,3 @@ var/mob/living/carbon/human/M = target M.adjustBrainLoss(20) M.hallucination += 20 - -/obj/item/projectile/icarus/pointdefense/process() - Icarus_FireLaser(get_turf(original)) - spawn - qdel(src) - - return - -/obj/item/projectile/icarus/guns/process() - Icarus_FireCannon(get_turf(original)) - spawn - qdel(src) - return From f9af885ee1e06f0a391c808bcf42c1feb9eaec84 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Sat, 12 Dec 2015 14:32:22 -0700 Subject: [PATCH 168/207] Admin created newscaster channels now function correctly. Fixes #8326 --- code/modules/admin/topic.dm | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 45397fa097b..de178bc2980 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2411,13 +2411,8 @@ else var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") if(choice=="Confirm") - var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = src.admincaster_feed_channel.channel_name - newChannel.author = src.admincaster_signature - newChannel.locked = src.admincaster_feed_channel.locked - newChannel.is_admin_channel = 1 - feedback_inc("newscaster_channels",1) - news_network.network_channels += newChannel //Adding channel to the global network + news_network.CreateFeedChannel(admincaster_feed_channel.channel_name, admincaster_signature, admincaster_feed_channel.locked, 1) + feedback_inc("newscaster_channels",1) //Adding channel to the global network log_admin("[key_name_admin(usr)] created command feed channel: [src.admincaster_feed_channel.channel_name]!") src.admincaster_screen=5 src.access_news_network() From ddf66a5f39ec1c8d59dda19dcd233e90cb62de2a Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Sat, 12 Dec 2015 21:56:37 +0000 Subject: [PATCH 169/207] fix slime core injecting not working --- code/modules/mob/living/carbon/metroid/items.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/metroid/items.dm b/code/modules/mob/living/carbon/metroid/items.dm index 6739cb4e2b9..1271bb7da33 100644 --- a/code/modules/mob/living/carbon/metroid/items.dm +++ b/code/modules/mob/living/carbon/metroid/items.dm @@ -11,6 +11,7 @@ origin_tech = "biotech=4" var/Uses = 1 // uses before it goes inert var/enhanced = 0 //has it been enhanced before? + flags = OPENCONTAINER attackby(obj/item/O as obj, mob/user as mob) if(istype(O, /obj/item/weapon/slimesteroid2)) From a5b0f86c194db2ee190a48845a4bc4cf6b563a54 Mon Sep 17 00:00:00 2001 From: Joseph Heinemeyer Date: Sat, 12 Dec 2015 15:24:13 -0700 Subject: [PATCH 170/207] s/"help"/I_HELP/g --- code/modules/mob/living/carbon/human/human.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c90d06c008a..cabbc1474f3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1379,7 +1379,7 @@ /mob/living/carbon/human/MouseDrop(var/atom/over_object) var/mob/living/carbon/human/H = over_object - if(holder_type && a_intent == "help" && istype(H) && H == usr && H.a_intent == "help" && !issmall(H) && Adjacent(H)) + if(holder_type && a_intent == I_HELP && istype(H) && H == usr && H.a_intent == I_HELP && !issmall(H) && Adjacent(H)) get_scooped(H) return return ..() From 415f78ee186a3338261a9f9044f6bc69ae0c3dea Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Sat, 12 Dec 2015 16:29:05 -0700 Subject: [PATCH 171/207] Chem grenades are no longer melted by acid. Fixes #10478 --- code/game/objects/items/weapons/grenades/chem_grenade.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index b559527ef7e..d010e70b0ff 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -6,6 +6,7 @@ w_class = 2.0 force = 2.0 det_time = null + unacidable = 1 var/stage = 0 var/state = 0 var/path = 0 From d1f14cd16d04d05a870b51c9d85cf6046d370fb2 Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Tue, 15 Dec 2015 13:42:31 +0100 Subject: [PATCH 172/207] Fixes duplicate gas layers --- code/ZAS/Controller.dm | 7 ++++--- code/ZAS/Zone.dm | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm index a2d9bcd9720..b53afffe5c1 100644 --- a/code/ZAS/Controller.dm +++ b/code/ZAS/Controller.dm @@ -154,18 +154,18 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun #ifdef ZASDBG var/updated = 0 #endif - + //defer updating of self-zone-blocked turfs until after all other turfs have been updated. //this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones //have valid zones when the self-zone-blocked turfs update. var/list/deferred = list() - + for(var/turf/T in updating) //check if the turf is self-zone-blocked if(T.c_airblock(T) & ZONE_BLOCKED) deferred += T continue - + T.update_air_properties() T.post_update_air_properties() T.needs_air_update = 0 @@ -234,6 +234,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun /datum/controller/air_system/proc/remove_zone(zone/z) zones.Remove(z) + zones_to_update.Remove(z) /datum/controller/air_system/proc/air_blocked(turf/A, turf/B) #ifdef ZASDBG diff --git a/code/ZAS/Zone.dm b/code/ZAS/Zone.dm index 9fcddc92465..da39b868d3a 100644 --- a/code/ZAS/Zone.dm +++ b/code/ZAS/Zone.dm @@ -108,11 +108,12 @@ Class Procs: c_invalidate() for(var/turf/simulated/T in contents) into.add(T) + T.update_graphic(graphic_remove = air.graphic) #ifdef ZASDBG T.dbg(merged) #endif - - //rebuild the old zone's edges so that the will be possesed by the new zone + + //rebuild the old zone's edges so that they will be possessed by the new zone for(var/connection_edge/E in edges) if(E.contains_zone(into)) continue //don't need to rebuild this edge From f62f24e1aca78cb82f46ef5adcfc300dae4cd373 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 16 Dec 2015 12:54:34 +0100 Subject: [PATCH 173/207] Removes Stat() sleep. Fixes a Stat() runtime that occasionally occur if the client was logged out when the sleep() was done sleeping. Fixes delays when using alt+Turf click. Makes the alt+Turf click panel only update when viewed instead. Seems like the better performance fix option in general. Makes the alt+Turf click panel always use the "Turf" name, consistency. --- code/_onclick/click.dm | 2 +- code/modules/mob/mob.dm | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 56af5949f73..3d7622a7133 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -291,7 +291,7 @@ user.listed_turf = null else user.listed_turf = T - user.client.statpanel = T.name + user.client.statpanel = "Turf" return /mob/proc/TurfAdjacent(var/turf/T) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a81c9435035..b42b2c9f722 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -658,17 +658,17 @@ if(!TurfAdjacent(listed_turf)) listed_turf = null else - statpanel(listed_turf.name, null, listed_turf) - for(var/atom/A in listed_turf) - if(!A.mouse_opacity) - continue - if(A.invisibility > see_invisible) - continue - if(is_type_in_list(A, shouldnt_see)) - continue - statpanel(listed_turf.name, null, A) + if(statpanel("Turf")) + stat("\icon[listed_turf]", listed_turf.name) + for(var/atom/A in listed_turf) + if(!A.mouse_opacity) + continue + if(A.invisibility > see_invisible) + continue + if(is_type_in_list(A, shouldnt_see)) + continue + stat(A) - sleep(4) //Prevent updating the stat panel for the next .4 seconds, prevents clientside latency from updates // facing verbs /mob/proc/canface() From a515f0469ab5d40dc9a159ae7c6a78db2b5275c8 Mon Sep 17 00:00:00 2001 From: Spamcat Date: Wed, 16 Dec 2015 17:59:05 +0300 Subject: [PATCH 174/207] Wrenched opwn welding tanks now explode when exposed to fire. #11537 --- code/modules/reagents/reagent_dispenser.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 7fc8ebf8abc..f259889aee3 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -171,7 +171,9 @@ qdel(src) /obj/structure/reagent_dispensers/fueltank/fire_act(datum/gas_mixture/air, temperature, volume) - if(temperature > T0C+500) + if (modded) + explode() + else if (temperature > T0C+500) explode() return ..() From f2ac9a023bd38ce57db12fb15b7060314cd106b0 Mon Sep 17 00:00:00 2001 From: Spamcat Date: Wed, 16 Dec 2015 19:36:14 +0300 Subject: [PATCH 175/207] pAIs no longer see custom emotes twice. fuck i spent way too much time on a single line fix --- code/game/objects/items/devices/paicard.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index eed6cdb12ef..7edf72e9a50 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -320,7 +320,7 @@ qdel(src) /obj/item/device/paicard/see_emote(mob/living/M, text) - if(pai && pai.client) + if(pai && pai.client && !pai.canmove) var/rendered = "[text]" pai.show_message(rendered, 2) ..() \ No newline at end of file From 485a2fdd45940a1c48e4854294401ac050e4fed0 Mon Sep 17 00:00:00 2001 From: Spamcat Date: Wed, 16 Dec 2015 20:07:35 +0300 Subject: [PATCH 176/207] Made kitchen utensils less dangerous. #11370 --- code/game/objects/items/weapons/material/kitchen.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index 55c51519345..088069a26ff 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -44,7 +44,8 @@ overlays.Cut() return else - ..() + user << "\red You don't have anything on \the [src]." //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK GODDAMNIT + return /obj/item/weapon/material/kitchen/utensil/fork name = "fork" From 8df6ee3318af7f2188538312fa6dd23f86cf9d3e Mon Sep 17 00:00:00 2001 From: Spamcat Date: Wed, 16 Dec 2015 20:21:10 +0300 Subject: [PATCH 177/207] \red >> styles --- code/game/objects/items/weapons/material/kitchen.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index 088069a26ff..d15eae34316 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -44,7 +44,7 @@ overlays.Cut() return else - user << "\red You don't have anything on \the [src]." //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK GODDAMNIT + user << "You don't have anything on \the [src]." //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK GODDAMNIT return /obj/item/weapon/material/kitchen/utensil/fork @@ -78,14 +78,14 @@ /obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "\red You accidentally cut yourself with the [src]." + user << "You accidentally cut yourself with the [src]." user.take_organ_damage(20) return return ..() /obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "\red You somehow managed to cut yourself with the [src]." + user << "You somehow managed to cut yourself with the [src]." user.take_organ_damage(20) return return ..() @@ -108,7 +108,7 @@ /obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "\red The [src] slips out of your hand and hits your head." + user << "The [src] slips out of your hand and hits your head." user.take_organ_damage(10) user.Paralyse(2) return From 905070bc96a14a98dba03d938ec08ca34d14876d Mon Sep 17 00:00:00 2001 From: Spamcat Date: Wed, 16 Dec 2015 20:30:26 +0300 Subject: [PATCH 178/207] \the --- code/game/objects/items/weapons/material/kitchen.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index d15eae34316..9c160f028d4 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -78,14 +78,14 @@ /obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "You accidentally cut yourself with the [src]." + user << "You accidentally cut yourself with \the [src]." user.take_organ_damage(20) return return ..() /obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "You somehow managed to cut yourself with the [src]." + user << "You somehow managed to cut yourself with \the [src]." user.take_organ_damage(20) return return ..() @@ -108,7 +108,7 @@ /obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) - user << "The [src] slips out of your hand and hits your head." + user << "\The [src] slips out of your hand and hits your head." user.take_organ_damage(10) user.Paralyse(2) return From dc2ad43dc5c4ae5d67e9fd03a207f153f8587a1d Mon Sep 17 00:00:00 2001 From: Hubblenaut Date: Wed, 16 Dec 2015 02:28:19 +0100 Subject: [PATCH 179/207] No verbose cantouch check when not climbable --- code/game/objects/buckling.dm | 3 ++- code/game/objects/structures.dm | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 93c2fd57bbb..02d85234ed7 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -56,7 +56,8 @@ user << "You can't buckle anyone in before the game starts." if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai)) return - + if(M == buckled_mob) + return if(istype(M, /mob/living/carbon/slime)) user << "The [M] is too squishy to buckle in." return diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 8039814f4fe..f344758b491 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -79,7 +79,7 @@ return ..() /obj/structure/proc/can_climb(var/mob/living/user, post_climb_check=0) - if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers))) + if (!climbable || !can_touch(user) || (!post_climb_check && (user in climbers))) return 0 if (!user.Adjacent(src)) From 07e81c059c81021fcfa8ed0a4af7b7a7f2a4e7b2 Mon Sep 17 00:00:00 2001 From: Loganbacca Date: Fri, 18 Dec 2015 20:12:46 +1300 Subject: [PATCH 180/207] Fixed bullets traveling diagonally through windows - Fixes #11465 --- code/game/objects/structures/window.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index fc9f5b6a193..0ac02fbeb73 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -140,7 +140,7 @@ return 1 if(is_full_window()) return 0 //full tile window, you can't move into it! - if(get_dir(loc, target) == dir) + if(get_dir(loc, target) & dir) return !density else return 1 From 378f62b81ec6f63b12ca856e9258949e20213677 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 19 Dec 2015 11:44:37 +0100 Subject: [PATCH 181/207] AI qdel() improvements. AI destruction now cleans up more of its held objects and variables. Fixes some issues with the AI powersupply qdel(). Fixes #11710. --- code/modules/mob/living/silicon/ai/ai.dm | 34 +++++++++++++++++------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ba42e42c75f..0c9435481ab 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -158,7 +158,6 @@ var/list/ai_verbs_default = list( spawn(5) new /obj/machinery/ai_powersupply(src) - hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[LIFE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") @@ -199,8 +198,23 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/Destroy() ai_list -= src + qdel(eyeobj) - ..() + eyeobj = null + + qdel(psupply) + psupply = null + + qdel(aiMulti) + aiMulti = null + + qdel(aiRadio) + aiRadio = null + + qdel(aiCamera) + aiCamera = null + + return ..() /mob/living/silicon/ai/pointed(atom/A as mob|obj|turf in view()) set popup_menu = 0 @@ -234,20 +248,22 @@ var/list/ai_verbs_default = list( /obj/machinery/ai_powersupply/New(var/mob/living/silicon/ai/ai=null) powered_ai = ai powered_ai.psupply = src - if(isnull(powered_ai)) - qdel(src) - - loc = powered_ai.loc - use_power(1) // Just incase we need to wake up the power system. + forceMove(powered_ai.loc) ..() + use_power(1) // Just incase we need to wake up the power system. + +/obj/machinery/ai_powersupply/Destroy() + . = ..() + powered_ai = null /obj/machinery/ai_powersupply/process() - if(!powered_ai || powered_ai.stat & DEAD) - qdel() + if(!powered_ai || powered_ai.stat == DEAD) + qdel(src) return if(powered_ai.psupply != src) // For some reason, the AI has different powersupply object. Delete this one, it's no longer needed. qdel(src) + return if(powered_ai.APU_power) use_power = 0 return From 8b3724e3e3f9a4c55e874e015f33e6bb8782cba0 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 19 Dec 2015 22:01:38 +0100 Subject: [PATCH 182/207] Ports Kun-Peng's general map merge scripts. These backups all *.dmm files in the maps folder, rather than those with specific names. --- tools/mapmerge/1prepare_map.bat | 5 ++--- tools/mapmerge/2clean_map.bat | 6 +++--- tools/mapmerge/clean_map_git.sh | 11 +++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tools/mapmerge/1prepare_map.bat b/tools/mapmerge/1prepare_map.bat index 2092086bf7f..365d5f00e82 100644 --- a/tools/mapmerge/1prepare_map.bat +++ b/tools/mapmerge/1prepare_map.bat @@ -1,8 +1,7 @@ -SET z_levels=6 cd ../../maps -FOR /L %%i IN (1,1,%z_levels%) DO ( - copy exodus-%%i.dmm exodus-%%i.dmm.backup +FOR %%f IN (*.dmm) DO ( + copy %%f %%f.backup ) pause diff --git a/tools/mapmerge/2clean_map.bat b/tools/mapmerge/2clean_map.bat index 84cbfd5d359..a719963df43 100644 --- a/tools/mapmerge/2clean_map.bat +++ b/tools/mapmerge/2clean_map.bat @@ -1,8 +1,8 @@ SET z_levels=6 cd -FOR /L %%i IN (1,1,%z_levels%) DO ( - java -jar MapPatcher.jar -clean ../../maps/exodus-%%i.dmm.backup ../../maps/exodus-%%i.dmm ../../maps/exodus-%%i.dmm +FOR %%f IN (../../maps/*.dmm) DO ( + java -jar MapPatcher.jar -clean ../../maps/%%f.backup ../../maps/%%f ../../maps/%%f ) -pause \ No newline at end of file +pause diff --git a/tools/mapmerge/clean_map_git.sh b/tools/mapmerge/clean_map_git.sh index e8ad8165e49..25cef6da93a 100755 --- a/tools/mapmerge/clean_map_git.sh +++ b/tools/mapmerge/clean_map_git.sh @@ -1,10 +1,9 @@ -#!/bin/bash +#!/bin/sh -for i in {1..6} +for MAPFILE in ../../maps/*.dmm do - MAPFILE="exodus-$i.dmm" - - git show HEAD:maps/$MAPFILE > tmp.dmm - java -jar MapPatcher.jar -clean tmp.dmm '../../maps/'$MAPFILE '../../maps/'$MAPFILE + MAPNAME=$(basename $MAPFILE) + git show HEAD:maps/$MAPNAME > tmp.dmm + java -jar MapPatcher.jar -clean tmp.dmm $MAPFILE $MAPFILE rm tmp.dmm done From ce3587d867e16c8d7561c3a4948b9ddd57888c39 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Sat, 19 Dec 2015 21:33:02 -0500 Subject: [PATCH 183/207] Hallucinations no longer burn on the SuperMatter --- code/modules/supermatter/supermatter.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index fb62f493259..1ee9f99c451 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -305,6 +305,8 @@ /obj/machinery/power/supermatter/Bumped(atom/AM as mob|obj) + if(istype(AM, /obj/effect)) + return if(istype(AM, /mob/living)) AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\ "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ From d574d60e26e94a1542f4e5486796c0d7cca7dfa2 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Mon, 21 Dec 2015 15:00:25 -0500 Subject: [PATCH 184/207] Canisters now work in unpowered areas. --- code/game/machinery/atmoalter/canister.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 9a8228aaa6d..458e787b79d 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -17,6 +17,7 @@ var/temperature_resistance = 1000 + T0C volume = 1000 use_power = 0 + interact_offline = 1 // Allows this to be used when not in powered area. var/release_log = "" var/update_flag = 0 From 5873a92df83756720befb5b31dc89753068f6ff3 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Mon, 21 Dec 2015 15:30:26 -0500 Subject: [PATCH 185/207] Fixes the icon for numbness. Resolves #11435 --- code/modules/mob/living/carbon/human/life.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f8abe2778ba..ddd0c9ef8c3 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1266,7 +1266,7 @@ if(healths) if (analgesic > 100) - healths.icon_state = "health_health_numb" + healths.icon_state = "health_numb" else switch(hal_screwyhud) if(1) healths.icon_state = "health6" From fe62634775bb74ff359dcfdb0cef49a88b0903c2 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Mon, 21 Dec 2015 17:53:53 -0500 Subject: [PATCH 186/207] Stumpy hands and arms can no longer pull stuff out of bags and such. Resolves #11404 --- code/game/objects/items.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index fef7336371c..f7215086e80 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -151,6 +151,9 @@ if(temp && !temp.is_usable()) user << "You try to move your [temp.name], but cannot!" return + if(!temp) + user << "You try to use your hand, but realize it is no longer attached!" + return src.pickup(user) if (istype(src.loc, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = src.loc From 9fa1513647b771a3447800f49c338081ee56802f Mon Sep 17 00:00:00 2001 From: Atlantis Date: Wed, 23 Dec 2015 00:57:54 +0100 Subject: [PATCH 187/207] Fixes AI's Examine() - Message about AI's backup power now only show when the AI still lacks external power. --- code/modules/mob/living/silicon/ai/examine.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm index 45c6a3816bb..e11d799af5e 100644 --- a/code/modules/mob/living/silicon/ai/examine.dm +++ b/code/modules/mob/living/silicon/ai/examine.dm @@ -17,7 +17,7 @@ msg += "It looks slightly charred.\n" else msg += "Its casing is melted and heat-warped!\n" - if (src.getOxyLoss()) + if (src.getOxyLoss() && (aiRestorePowerRoutine != 0 && !APU_power)) if (src.getOxyLoss() > 175) msg += "It seems to be running on backup power. Its display is blinking a \"BACKUP POWER CRITICAL\" warning.\n" else if(src.getOxyLoss() > 100) From c5912b988cefbb4bf7b05b9d8f33a6bca849de8f Mon Sep 17 00:00:00 2001 From: Datraen Date: Sun, 20 Dec 2015 14:19:42 -0500 Subject: [PATCH 188/207] Adds a paralyze button for easy administration. Conflicts: code/modules/admin/admin.dm --- code/modules/admin/admin.dm | 18 +++++++++++++++++- code/modules/admin/admin_verbs.dm | 6 ++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 1e1dcf982e0..1988f3d58c7 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1403,5 +1403,21 @@ proc/admin_notice(var/message, var/rights) usr << "Mode has not started." return - message_admins("[key_name(usr)] attempting to force mode autospawn.") + log_and_message_admins("attempting to force mode autospawn.") ticker.mode.process_autoantag() + +/datum/admins/proc/paralyze_mob(mob/living/carbon/human/H as mob) + set category = "Admin" + set name = "Toggle Paralyze" + set desc = "Paralyzes a player. Or unparalyses them." + + var/msg + + if(check_rights(R_ADMIN|R_MOD)) + if (H.paralysis == 0) + H.paralysis = 1000 + msg = "has paralyzed [key_name(H)]." + else + H.paralysis = 0 + msg = "has unparalyzed [key_name(H)]." + log_and_message_admins(msg) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 064f10820d1..54031611497 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -91,7 +91,8 @@ var/list/admin_verbs_admin = list( /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */ /client/proc/change_security_level, /client/proc/view_chemical_reaction_logs, - /client/proc/makePAI + /client/proc/makePAI, + /datum/admins/proc/paralyze_mob ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, @@ -284,7 +285,8 @@ var/list/admin_verbs_mod = list( /datum/admins/proc/show_player_panel, /client/proc/check_antagonists, /client/proc/jobbans, - /client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/ + /client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/ + /datum/admins/proc/paralyze_mob ) var/list/admin_verbs_mentor = list( From 65f68602e7e06c989d293ded7141d4fd950f3fa4 Mon Sep 17 00:00:00 2001 From: Datraen Date: Sun, 20 Dec 2015 14:37:39 -0500 Subject: [PATCH 189/207] Adds a longer timer to paralyze, allows for other mobs to fall under this proc. Conflicts: code/modules/admin/admin.dm --- code/modules/admin/admin.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 1988f3d58c7..4a435188e35 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1406,7 +1406,7 @@ proc/admin_notice(var/message, var/rights) log_and_message_admins("attempting to force mode autospawn.") ticker.mode.process_autoantag() -/datum/admins/proc/paralyze_mob(mob/living/carbon/human/H as mob) +/datum/admins/proc/paralyze_mob(mob/living/H as mob) set category = "Admin" set name = "Toggle Paralyze" set desc = "Paralyzes a player. Or unparalyses them." @@ -1415,7 +1415,7 @@ proc/admin_notice(var/message, var/rights) if(check_rights(R_ADMIN|R_MOD)) if (H.paralysis == 0) - H.paralysis = 1000 + H.paralysis = 8000 msg = "has paralyzed [key_name(H)]." else H.paralysis = 0 From 70b84d87a6f8b90633338793e487291fffaeb6d5 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 23 Dec 2015 13:01:03 +0100 Subject: [PATCH 190/207] Tweaks permission rights. --- code/modules/admin/admin.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 4a435188e35..86e0d31cefd 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1395,7 +1395,7 @@ proc/admin_notice(var/message, var/rights) if (!istype(src,/datum/admins)) src = usr.client.holder - if (!istype(src,/datum/admins)) + if (!istype(src,/datum/admins) || !check_rights(R_ADMIN)) usr << "Error: you are not an admin!" return @@ -1413,7 +1413,7 @@ proc/admin_notice(var/message, var/rights) var/msg - if(check_rights(R_ADMIN|R_MOD)) + if(check_rights(R_ADMIN)) if (H.paralysis == 0) H.paralysis = 8000 msg = "has paralyzed [key_name(H)]." From 90f27ca42cd4a3e2bcc9e897d03de25ca9fab516 Mon Sep 17 00:00:00 2001 From: Sebastian Broberg Date: Wed, 23 Dec 2015 23:46:53 +0100 Subject: [PATCH 191/207] Fixes chemgrenades Fixes #11686 --- code/game/objects/items/weapons/grenades/chem_grenade.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index d010e70b0ff..5e15098521a 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -164,7 +164,7 @@ playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1) for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.reagents.trans_to(src, G.reagents.total_volume) + G.reagents.trans_to_obj(src, G.reagents.total_volume) if(src.reagents.total_volume) //The possible reactions didnt use up all reagents. var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() From 0bd51d2712a53eabdfd0c7828394224371369bc9 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Thu, 24 Dec 2015 05:28:18 +0000 Subject: [PATCH 192/207] make vote window closeable via normal means --- code/controllers/voting.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 2bd56163d55..45d4a5174fd 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -39,12 +39,12 @@ datum/controller/vote result() for(var/client/C in voting) if(C) - C << browse(null,"window=vote;can_close=0") + C << browse(null,"window=vote") reset() else for(var/client/C in voting) if(C) - C << browse(vote.interface(C),"window=vote;can_close=0") + C << browse(vote.interface(C),"window=vote") voting.Cut() @@ -392,4 +392,4 @@ datum/controller/vote set name = "Vote" if(vote) - src << browse(vote.interface(client),"window=vote;can_close=0") + src << browse(vote.interface(client),"window=vote") From ccda750ee1063652fd24e5d31ac80166fd524bf7 Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Thu, 24 Dec 2015 02:43:52 -0500 Subject: [PATCH 193/207] AI Malf will no longer be able to spawn a non-antag AI fixes #10554 --- code/game/gamemodes/game_mode.dm | 2 + .../game/gamemodes/malfunction/malfunction.dm | 1 + code/game/jobs/job_controller.dm | 38 +------------------ 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 8dea479de53..d5e55f4c128 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -16,6 +16,8 @@ var/global/list/additional_antag_types = list() var/ert_disabled = 0 // ERT cannot be called. var/deny_respawn = 0 // Disable respawn during this round. + var/list/disabled_jobs = list() // Mostly used for Malf. This check is performed in job_controller so it doesn't spawn a regular AI. + var/shuttle_delay = 1 // Shuttle transit time is multiplied by this. var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled? diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index a86773235b3..35646524f09 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -9,3 +9,4 @@ end_on_antag_death = 0 auto_recall_shuttle = 0 antag_tags = list(MODE_MALFUNCTION) + disabled_jobs = list("AI") diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 142190dca59..82441ead326 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -185,36 +185,6 @@ var/global/datum/controller/occupations/job_master return - proc/FillAIPosition() - var/ai_selected = 0 - var/datum/job/job = GetJob("AI") - if(!job) return 0 - if((job.title == "AI") && (config) && (!config.allow_ai)) return 0 - - for(var/i = job.total_positions, i > 0, i--) - for(var/level = 1 to 3) - var/list/candidates = list() - if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf - candidates = FindOccupationCandidates(job, level, BE_MALF) - else - candidates = FindOccupationCandidates(job, level) - if(candidates.len) - var/mob/new_player/candidate = pick(candidates) - if(AssignRole(candidate, "AI")) - ai_selected++ - break - //Malf NEEDS an AI so force one if we didn't get a player who wanted it - if((ticker.mode.name == "AI malfunction")&&(!ai_selected)) - unassigned = shuffle(unassigned) - for(var/mob/new_player/player in unassigned) - if(jobban_isbanned(player, "AI")) continue - if(AssignRole(player, "AI")) - ai_selected++ - break - if(ai_selected) return 1 - return 0 - - /** Proc DivideOccupations * fills var "assigned_role" for all ready players. * This proc must not have any side effect besides of modifying "assigned_role". @@ -260,11 +230,6 @@ var/global/datum/controller/occupations/job_master FillHeadPosition() Debug("DO, Head Check end") - //Check for an AI - Debug("DO, Running AI Check") - FillAIPosition() - Debug("DO, AI Check end") - //Other jobs are now checked Debug("DO, Running Standard Check") @@ -275,6 +240,7 @@ var/global/datum/controller/occupations/job_master // Loop through all levels from high to low var/list/shuffledoccupations = shuffle(occupations) + // var/list/disabled_jobs = ticker.mode.disabled_jobs // So we can use .Find down below without a colon. for(var/level = 1 to 3) //Check the head jobs first each level CheckHeadPositions(level) @@ -284,7 +250,7 @@ var/global/datum/controller/occupations/job_master // Loop through all jobs for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY - if(!job) + if(!job || ticker.mode.disabled_jobs.Find(job.title) ) continue if(jobban_isbanned(player, job.title)) From b0aa56089e4974aed76ded3584905fdc16239c7b Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Thu, 24 Dec 2015 19:01:27 +0100 Subject: [PATCH 194/207] Fixes #11745. --- baystation12.dme | 1 - code/game/jobs/job/civilian.dm | 73 ---------------------------------- code/game/jobs/jobprocs.dm | 66 ------------------------------ 3 files changed, 140 deletions(-) delete mode 100644 code/game/jobs/jobprocs.dm diff --git a/baystation12.dme b/baystation12.dme index 1c02e399cb1..af6e369282f 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -312,7 +312,6 @@ #include "code\game\gamemodes\wizard\wizard.dm" #include "code\game\jobs\access.dm" #include "code\game\jobs\job_controller.dm" -#include "code\game\jobs\jobprocs.dm" #include "code\game\jobs\jobs.dm" #include "code\game\jobs\whitelist.dm" #include "code\game\jobs\job\assistant.dm" diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 26f5c020201..ed670f7a162 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -177,79 +177,6 @@ H.species.equip_survival_gear(H,1) return 1 - -//Griff //BS12 EDIT -/* -/datum/job/clown - title = "Clown" - flag = CLOWN - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_clown, access_theatre, access_maint_tunnels) - minimal_access = list(access_clown, access_theatre) - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/clown(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/rainbow(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/toy/waterflower(H), slot_in_backpack) - H.mutations.Add(CLUMSY) - return 1 - - - -/datum/job/mime - title = "Mime" - flag = MIME - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_mime, access_theatre, access_maint_tunnels) - minimal_access = list(access_mime, access_theatre) - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - if(H.backbag == 2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(H.backbag == 3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/mime(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/mime(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask) - H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_l_store) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand) - else - H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack) - H.verbs += /client/proc/mimespeak - H.verbs += /client/proc/mimewall - H.mind.special_verbs += /client/proc/mimespeak - H.mind.special_verbs += /client/proc/mimewall - H.miming = 1 - return 1 -*/ - - /datum/job/janitor title = "Janitor" flag = JANITOR diff --git a/code/game/jobs/jobprocs.dm b/code/game/jobs/jobprocs.dm deleted file mode 100644 index 2a012872bf2..00000000000 --- a/code/game/jobs/jobprocs.dm +++ /dev/null @@ -1,66 +0,0 @@ - - -//TODO: put these somewhere else -/client/proc/mimewall() - set category = "Mime" - set name = "Invisible wall" - set desc = "Create an invisible wall on your location." - if(usr.stat) - usr << "Not when you're incapicated." - return - if(!ishuman(usr)) - return - - var/mob/living/carbon/human/H = usr - - if(!H.miming) - usr << "You still haven't atoned for your speaking transgression. Wait." - return - H.verbs -= /client/proc/mimewall - spawn(300) - H.verbs += /client/proc/mimewall - for (var/mob/V in viewers(H)) - if(V!=usr) - V.show_message("[H] looks as if a wall is in front of them.", 3, "", 2) - usr << "You form a wall in front of yourself." - new /obj/effect/forcefield/mime(locate(usr.x,usr.y,usr.z)) - return - -///////////Mimewalls/////////// - -/obj/effect/forcefield/mime - icon_state = "empty" - name = "invisible wall" - desc = "You have a bad feeling about this." - var/timeleft = 300 - var/last_process = 0 - -/obj/effect/forcefield/mime/New() - ..() - last_process = world.time - processing_objects.Add(src) - -/obj/effect/forcefield/mime/process() - timeleft -= (world.time - last_process) - if(timeleft <= 0) - processing_objects.Remove(src) - qdel(src) - -/////////////////////////////// - -/client/proc/mimespeak() - set category = "Mime" - set name = "Speech" - set desc = "Toggle your speech." - if(!ishuman(usr)) - return - - var/mob/living/carbon/human/H = usr - - if(H.miming) - H.miming = 0 - else - H << "You'll have to wait if you want to atone for your sins." - spawn(3000) - H.miming = 1 - return \ No newline at end of file From ebef6272b92067a05d474c75a2a6621161d87499 Mon Sep 17 00:00:00 2001 From: Sebastian Broberg Date: Thu, 24 Dec 2015 23:02:37 +0100 Subject: [PATCH 195/207] Fixes #11711 Should fix it. --- code/modules/mob/living/simple_animal/constructs/soulstone.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index 5859969d03b..d5c7ad1149f 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -113,7 +113,7 @@ if(C.imprinted != "empty") U << "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!" else - if ((T.health + T.halloss) > config.health_threshold_crit) + if ((T.health + T.halloss) > config.health_threshold_crit || T.stat == DEAD) U << "\red Capture failed!: \black Kill or maim the victim first!" else if(T.client == null) From 34b8c99d526ba84b233d030dcdff0cf7b99eebbb Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Fri, 25 Dec 2015 00:56:16 +0000 Subject: [PATCH 196/207] backport fix for #10705 from dev fix #10705 --- code/game/gamemodes/blob/blobs/shield.dm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index c47696c72e3..68296724495 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -21,4 +21,13 @@ CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 - return 0 + return !density + +/obj/effect/blob/shield/New() + ..() + update_nearby_tiles() + +/obj/effect/blob/shield/Destroy() + density = 0 + update_nearby_tiles() + ..() From 04006f5b9e2e7a1cb39263ac91c9e1e8ff5de296 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Fri, 25 Dec 2015 01:06:35 +0000 Subject: [PATCH 197/207] fix human examine gender --- code/modules/mob/living/carbon/human/examine.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 2fe60443c90..96e1739da6c 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -271,9 +271,9 @@ var/obj/item/organ/external/E = organs_by_name[organ_tag] if(!E) - wound_flavor_text["[organ_descriptor]"] = "[t_He] is missing [t_his] [organ_descriptor].\n" + wound_flavor_text["[organ_descriptor]"] = "[t_He] [t_is] missing [t_his] [organ_descriptor].\n" else if(E.is_stump()) - wound_flavor_text["[organ_descriptor]"] = "[t_He] has a stump where [t_his] [organ_descriptor] should be.\n" + wound_flavor_text["[organ_descriptor]"] = "[t_He] [t_has] a stump where [t_his] [organ_descriptor] should be.\n" else continue @@ -285,13 +285,13 @@ wound_flavor_text["[temp.name]"] = "[t_He] [t_has] a robot [temp.name]!\n" continue else - wound_flavor_text["[temp.name]"] = "[t_He] has a robot [temp.name]. It has[temp.get_wounds_desc()]!\n" + wound_flavor_text["[temp.name]"] = "[t_He] [t_has] a robot [temp.name]. It has[temp.get_wounds_desc()]!\n" else if(temp.wounds.len > 0 || temp.open) if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ]) var/obj/item/organ/external/parent = organs_by_name[temp.parent_organ] - wound_flavor_text["[temp.name]"] = "[t_He] has [temp.get_wounds_desc()] on [t_his] [parent.name].
            " + wound_flavor_text["[temp.name]"] = "[t_He] [t_has] [temp.get_wounds_desc()] on [t_his] [parent.name].
            " else - wound_flavor_text["[temp.name]"] = "[t_He] has [temp.get_wounds_desc()] on [t_his] [temp.name].
            " + wound_flavor_text["[temp.name]"] = "[t_He] [t_has] [temp.get_wounds_desc()] on [t_his] [temp.name].
            " if(temp.status & ORGAN_BLEEDING) is_bleeding["[temp.name]"] = "[capitalize(t_his)] [temp.name] is bleeding!
            " else From faec92b553e5b5185bb34b515eba1f7c8059bb93 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Fri, 25 Dec 2015 11:19:59 +0100 Subject: [PATCH 198/207] Can now join compatible cable coils of any type. Partial backport of #11656. Fixes #10935. --- code/modules/power/cable.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 09ed44c58cf..5d6aa522816 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -480,6 +480,7 @@ obj/structure/cable/proc/cableColor(var/colorC) slot_flags = SLOT_BELT item_state = "coil" attack_verb = list("whipped", "lashed", "disciplined", "flogged") + stacktype = /obj/item/stack/cable_coil /obj/item/stack/cable_coil/cyborg name = "cable coil synthesizer" From b000ca4eb76de7f456c8b0bf52ed0257db43ed69 Mon Sep 17 00:00:00 2001 From: Sebastian Broberg Date: Fri, 25 Dec 2015 11:30:33 +0100 Subject: [PATCH 199/207] Boop, logic escaped me also refractor this shit someone. --- code/modules/mob/living/simple_animal/constructs/soulstone.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index d5c7ad1149f..1007d89d99c 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -113,7 +113,7 @@ if(C.imprinted != "empty") U << "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!" else - if ((T.health + T.halloss) > config.health_threshold_crit || T.stat == DEAD) + if ((T.health + T.halloss) > config.health_threshold_crit && T.stat != DEAD) U << "\red Capture failed!: \black Kill or maim the victim first!" else if(T.client == null) From 370529bc428a26be325ef7230126d614ef6de7bb Mon Sep 17 00:00:00 2001 From: Sebastian Broberg Date: Fri, 25 Dec 2015 13:04:13 +0100 Subject: [PATCH 200/207] Refractored soulstone.dm Split the various functions of the proc into multiple procs Moved the transfer_soul proc under the soulstone object. --- .../simple_animal/constructs/soulstone.dm | 323 +++++++++--------- .../modules/mob/living/simple_animal/shade.dm | 3 +- 2 files changed, 165 insertions(+), 161 deletions(-) diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index 1007d89d99c..734c97e4d96 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -14,74 +14,68 @@ //////////////////////////////Capturing//////////////////////////////////////////////////////// - attack(mob/living/carbon/human/M as mob, mob/user as mob) - if(!istype(M, /mob/living/carbon/human))//If target is not a human. - return ..() - if(istype(M, /mob/living/carbon/human/dummy)) - return..() +/obj/item/device/soulstone/attack(mob/living/carbon/human/M as mob, mob/user as mob) + if(!istype(M, /mob/living/carbon/human))//If target is not a human. + return ..() + if(istype(M, /mob/living/carbon/human/dummy)) + return..() - if(M.has_brain_worms()) //Borer stuff - RR - user << "This being is corrupted by an alien intelligence and cannot be soul trapped." - return..() + if(M.has_brain_worms()) //Borer stuff - RR + user << "This being is corrupted by an alien intelligence and cannot be soul trapped." + return..() - M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)") + M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)") - transfer_soul("VICTIM", M, user) - return + transfer_soul("VICTIM", M, user) + return - /*attack(mob/living/simple_animal/shade/M as mob, mob/user as mob)//APPARENTLY THEY NEED THEIR OWN SPECIAL SNOWFLAKE CODE IN THE LIVING ANIMAL DEFINES - if(!istype(M, /mob/living/simple_animal/shade))//If target is not a shade - return ..() - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - transfer_soul("SHADE", M, user) - return*/ ///////////////////Options for using captured souls/////////////////////////////////////// - attack_self(mob/user) - if (!in_range(src, user)) - return - user.set_machine(src) - var/dat = "Soul Stone
            " - for(var/mob/living/simple_animal/shade/A in src) - dat += "Captured Soul: [A.name]
            " - dat += {"Summon Shade"} - dat += "
            " - dat += {" Close"} - user << browse(dat, "window=aicard") - onclose(user, "aicard") +/obj/item/device/soulstone/attack_self(mob/user) + if (!in_range(src, user)) + return + user.set_machine(src) + var/dat = "Soul Stone
            " + for(var/mob/living/simple_animal/shade/A in src) + dat += "Captured Soul: [A.name]
            " + dat += {"Summon Shade"} + dat += "
            " + dat += {" Close"} + user << browse(dat, "window=aicard") + onclose(user, "aicard") + return + + + + +/obj/item/device/soulstone/Topic(href, href_list) + var/mob/U = usr + if (!in_range(src, U)||U.machine!=src) + U << browse(null, "window=aicard") + U.unset_machine() return + add_fingerprint(U) + U.set_machine(src) - - - Topic(href, href_list) - var/mob/U = usr - if (!in_range(src, U)||U.machine!=src) + switch(href_list["choice"])//Now we switch based on choice. + if ("Close") U << browse(null, "window=aicard") U.unset_machine() return - add_fingerprint(U) - U.set_machine(src) - - switch(href_list["choice"])//Now we switch based on choice. - if ("Close") - U << browse(null, "window=aicard") - U.unset_machine() - return - - if ("Summon") - for(var/mob/living/simple_animal/shade/A in src) - A.status_flags &= ~GODMODE - A.canmove = 1 - A << "You have been released from your prison, but you are still bound to [U.name]'s will. Help them suceed in their goals at all costs." - A.loc = U.loc - A.cancel_camera() - src.icon_state = "soulstone" - attack_self(U) + if ("Summon") + for(var/mob/living/simple_animal/shade/A in src) + A.status_flags &= ~GODMODE + A.canmove = 1 + A << "You have been released from your prison, but you are still bound to [U.name]'s will. Help them suceed in their goals at all costs." + A.loc = U.loc + A.cancel_camera() + src.icon_state = "soulstone" + attack_self(U) ///////////////////////////Transferring to constructs///////////////////////////////////////////////////// /obj/structure/constructshell @@ -99,118 +93,127 @@ /obj/structure/constructshell/attackby(obj/item/O as obj, mob/user as mob) if(istype(O, /obj/item/device/soulstone)) - O.transfer_soul("CONSTRUCT",src,user) + var/obj/item/device/soulstone/S = O; + S.transfer_soul("CONSTRUCT",src,user) ////////////////////////////Proc for moving soul in and out off stone////////////////////////////////////// +/obj/item/device/soulstone/proc/transfer_human(var/mob/living/carbon/human/T,var/mob/U) + if(!istype(T)) + return; + if(src.imprinted != "empty") + U << "\red Capture failed!: \black The soul stone has already been imprinted with [src.imprinted]'s mind!" + return + if ((T.health + T.halloss) > config.health_threshold_crit && T.stat != DEAD) + U << "\red Capture failed!: \black Kill or maim the victim first!" + return + if(T.client == null) + U << "\red Capture failed!: \black The soul has already fled it's mortal frame." + return + if(src.contents.len) + U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." + return + + for(var/obj/item/W in T) + T.drop_from_inventory(W) + + new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton + T.invisibility = 101 + + var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = T + flick("dust-h", animation) + qdel(animation) + + var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade( T.loc ) + S.loc = src //put shade in stone + S.status_flags |= GODMODE //So they won't die inside the stone somehow + S.canmove = 0//Can't move out of the soul stone + S.name = "Shade of [T.real_name]" + S.real_name = "Shade of [T.real_name]" + S.icon = T.icon + S.icon_state = T.icon_state + S.overlays = T.overlays + S.color = rgb(254,0,0) + S.alpha = 127 + if (T.client) + T.client.mob = S + S.cancel_camera() -/obj/item/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob). + src.icon_state = "soulstone2" + src.name = "Soul Stone: [S.real_name]" + S << "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs." + U << "\blue Capture successful!: \black [T.real_name]'s soul has been ripped from their body and stored within the soul stone." + U << "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls." + src.imprinted = "[S.name]" + qdel(T) + +/obj/item/device/soulstone/proc/transfer_shade(var/mob/living/simple_animal/shade/T,var/mob/U) + if(!istype(T)) + return; + if (T.stat == DEAD) + U << "\red Capture failed!: \black The shade has already been banished!" + return + if(src.contents.len) + U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." + return + if(T.name != src.imprinted) + U << "\red Capture failed!: \black The soul stone has already been imprinted with [src.imprinted]'s mind!" + return + + T.loc = src //put shade in stone + T.status_flags |= GODMODE + T.canmove = 0 + T.health = T.maxHealth + src.icon_state = "soulstone2" + + T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form" + U << "\blue Capture successful!: \black [T.name]'s has been recaptured and stored within the soul stone." +/obj/item/device/soulstone/proc/transfer_construct(var/obj/structure/constructshell/T,var/mob/U) + var/mob/living/simple_animal/shade/A = locate() in src + if(!A) + U << "\red Creation failed!: \black The soul stone is empty! Go kill someone!" + return; + var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") + switch(construct_class) + if("Juggernaut") + var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + cult.add_antagonist(Z.mind) + qdel(T) + Z << "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike." + Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + Z.cancel_camera() + qdel(src) + if("Wraith") + var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + cult.add_antagonist(Z.mind) + qdel(T) + Z << "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." + Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + Z.cancel_camera() + qdel(src) + if("Artificer") + var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + cult.add_antagonist(Z.mind) + qdel(T) + Z << "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs" + Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + Z.cancel_camera() + qdel(src) +/obj/item/device/soulstone/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob). switch(choice) if("VICTIM") - var/mob/living/carbon/human/T = target - var/obj/item/device/soulstone/C = src - if(C.imprinted != "empty") - U << "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!" - else - if ((T.health + T.halloss) > config.health_threshold_crit && T.stat != DEAD) - U << "\red Capture failed!: \black Kill or maim the victim first!" - else - if(T.client == null) - U << "\red Capture failed!: \black The soul has already fled it's mortal frame." - else - if(C.contents.len) - U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." - else - for(var/obj/item/W in T) - T.drop_from_inventory(W) - new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton - T.invisibility = 101 - var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = T - flick("dust-h", animation) - qdel(animation) - var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade( T.loc ) - S.loc = C //put shade in stone - S.status_flags |= GODMODE //So they won't die inside the stone somehow - S.canmove = 0//Can't move out of the soul stone - S.name = "Shade of [T.real_name]" - S.real_name = "Shade of [T.real_name]" - S.icon = T.icon - S.icon_state = T.icon_state - S.overlays = T.overlays - S.color = rgb(254,0,0) - S.alpha = 127 - if (T.client) - T.client.mob = S - S.cancel_camera() - C.icon_state = "soulstone2" - C.name = "Soul Stone: [S.real_name]" - S << "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs." - U << "\blue Capture successful!: \black [T.real_name]'s soul has been ripped from their body and stored within the soul stone." - U << "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls." - C.imprinted = "[S.name]" - qdel(T) + transfer_human(target,U) if("SHADE") - var/mob/living/simple_animal/shade/T = target - var/obj/item/device/soulstone/C = src - if (T.stat == DEAD) - U << "\red Capture failed!: \black The shade has already been banished!" - else - if(C.contents.len) - U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." - else - if(T.name != C.imprinted) - U << "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!" - else - T.loc = C //put shade in stone - T.status_flags |= GODMODE - T.canmove = 0 - T.health = T.maxHealth - C.icon_state = "soulstone2" - T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form" - U << "\blue Capture successful!: \black [T.name]'s has been recaptured and stored within the soul stone." + transfer_shade(target,U) if("CONSTRUCT") - var/obj/structure/constructshell/T = target - var/obj/item/device/soulstone/C = src - var/mob/living/simple_animal/shade/A = locate() in C - if(A) - var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") - switch(construct_class) - if("Juggernaut") - var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - cult.add_antagonist(Z.mind) - qdel(T) - Z << "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike." - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) - - if("Wraith") - var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - cult.add_antagonist(Z.mind) - qdel(T) - Z << "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) - - if("Artificer") - var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - cult.add_antagonist(Z.mind) - qdel(T) - Z << "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs" - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) - else - U << "\red Creation failed!: \black The soul stone is empty! Go kill someone!" - return + transfer_construct(target,U) diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 359db24c636..f8ed654b958 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -37,7 +37,8 @@ /mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri if(istype(O, /obj/item/device/soulstone)) - O.transfer_soul("SHADE", src, user) + var/obj/item/device/soulstone/S = O; + S.transfer_soul("SHADE", src, user) return /mob/living/simple_animal/shade/proc/OnDeathInLife() From 14393ea706831a1fd2222e6bfaa50ebcfea2de49 Mon Sep 17 00:00:00 2001 From: Sebastian Broberg Date: Sun, 27 Dec 2015 17:05:08 +0100 Subject: [PATCH 201/207] Few refraction --- .../simple_animal/constructs/soulstone.dm | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index 734c97e4d96..7e182c6f09d 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -72,7 +72,7 @@ A.status_flags &= ~GODMODE A.canmove = 1 A << "You have been released from your prison, but you are still bound to [U.name]'s will. Help them suceed in their goals at all costs." - A.loc = U.loc + A.forceMove(U.loc) A.cancel_camera() src.icon_state = "soulstone" attack_self(U) @@ -102,16 +102,16 @@ if(!istype(T)) return; if(src.imprinted != "empty") - U << "\red Capture failed!: \black The soul stone has already been imprinted with [src.imprinted]'s mind!" + U << "Capture failed!: The soul stone has already been imprinted with [src.imprinted]'s mind!" return if ((T.health + T.halloss) > config.health_threshold_crit && T.stat != DEAD) - U << "\red Capture failed!: \black Kill or maim the victim first!" + U << "Capture failed!: Kill or maim the victim first!" return if(T.client == null) - U << "\red Capture failed!: \black The soul has already fled it's mortal frame." + U << "Capture failed!: The soul has already fled it's mortal frame." return if(src.contents.len) - U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." + U << "Capture failed!: The soul stone is full! Use or free an existing soul to make room." return for(var/obj/item/W in T) @@ -146,7 +146,7 @@ src.icon_state = "soulstone2" src.name = "Soul Stone: [S.real_name]" S << "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs." - U << "\blue Capture successful!: \black [T.real_name]'s soul has been ripped from their body and stored within the soul stone." + U << "Capture successful! : [T.real_name]'s soul has been ripped from their body and stored within the soul stone." U << "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls." src.imprinted = "[S.name]" qdel(T) @@ -155,13 +155,13 @@ if(!istype(T)) return; if (T.stat == DEAD) - U << "\red Capture failed!: \black The shade has already been banished!" + U << "Capture failed!: The shade has already been banished!" return if(src.contents.len) - U << "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room." + U << "Capture failed!: The soul stone is full! Use or free an existing soul to make room." return if(T.name != src.imprinted) - U << "\red Capture failed!: \black The soul stone has already been imprinted with [src.imprinted]'s mind!" + U << "Capture failed!: The soul stone has already been imprinted with [src.imprinted]'s mind!" return T.loc = src //put shade in stone @@ -171,11 +171,11 @@ src.icon_state = "soulstone2" T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form" - U << "\blue Capture successful!: \black [T.name]'s has been recaptured and stored within the soul stone." + U << "Capture successful! : [T.name]'s has been recaptured and stored within the soul stone." /obj/item/device/soulstone/proc/transfer_construct(var/obj/structure/constructshell/T,var/mob/U) var/mob/living/simple_animal/shade/A = locate() in src if(!A) - U << "\red Creation failed!: \black The soul stone is empty! Go kill someone!" + U << "Capture failed!: The soul stone is empty! Go kill someone!" return; var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") switch(construct_class) From 86144844081b373508b8a00ddc81661c3725920c Mon Sep 17 00:00:00 2001 From: ccomp5950 Date: Sun, 27 Dec 2015 19:17:21 -0500 Subject: [PATCH 202/207] Hidden doors when open can be seen through. Fixes #11765 --- code/game/turfs/simulated/wall_attacks.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 32668e47437..a4083b81901 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -10,12 +10,14 @@ //flick("[material.icon_base]fwall_opening", src) sleep(15) density = 0 + opacity = 0 set_light(0) else can_open = WALL_OPENING //flick("[material.icon_base]fwall_closing", src) set_wall_state("[material.icon_base]0") density = 1 + opacity = 1 sleep(15) set_light(1) From 3dfb821eedc0af1bc055d52374956a575b7f0730 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Mon, 28 Dec 2015 17:25:37 +0000 Subject: [PATCH 203/207] add revision topic call --- code/world.dm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/world.dm b/code/world.dm index 02d7d804a77..08ad4b61f82 100644 --- a/code/world.dm +++ b/code/world.dm @@ -184,6 +184,12 @@ var/world_topic_spam_protect_time = world.timeofday return list2params(positions) + else if(T == "revision") + if(revdata.revision) + return list2params(list(branch = revdata.branch, date = revdata.date, revision = revdata.revision)) + else + return "unknown" + else if(copytext(T,1,5) == "info") var/input[] = params2list(T) if(input["key"] != config.comms_password) From f040b221b0b716829b03d64e45f55f6b32dfbeda Mon Sep 17 00:00:00 2001 From: Nicolai Czempin Date: Wed, 6 Jan 2016 05:30:41 +0100 Subject: [PATCH 204/207] Cleanbot cleans closest dirt first --- code/modules/mob/living/bot/cleanbot.dm | 134 ++++++++++++++---------- 1 file changed, 78 insertions(+), 56 deletions(-) diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm index 73310108523..57f907ec25d 100644 --- a/code/modules/mob/living/bot/cleanbot.dm +++ b/code/modules/mob/living/bot/cleanbot.dm @@ -26,6 +26,8 @@ var/blood = 1 var/list/target_types = list() + var/maximum_search_range = 7 + /mob/living/bot/cleanbot/New() ..() get_targets() @@ -36,6 +38,25 @@ if(radio_controller) radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS) +/mob/living/bot/cleanbot/proc/handle_target() + if(loc == target.loc) + if(!cleaning) + UnarmedAttack(target) + return 1 + if(!path.len) +// spawn(0) + path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard) + if(!path) + custom_emote(2, "[src] can't reach the target and is giving up.") + target = null + path = list() + return + if(path.len) + step_to(src, path[1]) + path -= path[1] + return 1 + return + /mob/living/bot/cleanbot/Life() ..() @@ -46,7 +67,7 @@ return if(cleaning) return - + if(!screwloose && !oddbutton && prob(5)) custom_emote(2, "makes an excited beeping booping sound!") @@ -74,65 +95,64 @@ spawn(600) ignorelist -= gib - if(!target) // Find a target - for(var/obj/effect/decal/cleanable/D in view(7, src)) - if(D in ignorelist) - continue - for(var/T in target_types) - if(istype(D, T)) - target = D - patrol_path = list() + // Find a target + + if(pulledby) // Don't wiggle if someone pulls you + patrol_path = list() + return - if(!target) // No targets in range - if(!should_patrol) - return + var/found_spot + search_loop: + for(var/i=0, i <= maximum_search_range, i++) + for(var/obj/effect/decal/cleanable/D in view(i, src)) + if(D in ignorelist) + continue + for(var/T in target_types) + if(istype(D, T)) + patrol_path = list() + target = D + found_spot = handle_target() + if (found_spot) + break search_loop + else + target = null + continue // no need to check the other types - if(!patrol_path || !patrol_path.len) - if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet - var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq) - if(!frequency) - return - closest_dist = 9999 - next_dest = null - next_dest_loc = null - - var/datum/signal/signal = new() - signal.source = src - signal.transmission_method = 1 - signal.data = list("findbeakon" = "patrol") - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - signal_sent = world.time - else - if(next_dest) - next_dest_loc = listener.memorized[next_dest] - if(next_dest_loc) - patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null) - signal_sent = 0 - else - if(pulledby) // Don't wiggle if someone pulls you - patrol_path = list() + if(!found_spot && !target) // No targets in range + if(!patrol_path || !patrol_path.len) + if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet + var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq) + if(!frequency) return - if(patrol_path[1] == loc) - patrol_path -= patrol_path[1] - var/moved = step_towards(src, patrol_path[1]) - if(moved) - patrol_path -= patrol_path[1] - if(target) - if(loc == target.loc) - if(!cleaning) - UnarmedAttack(target) + + closest_dist = 9999 + next_dest = null + next_dest_loc = null + + var/datum/signal/signal = new() + signal.source = src + signal.transmission_method = 1 + signal.data = list("findbeakon" = "patrol") + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + signal_sent = world.time + else + if(next_dest) + next_dest_loc = listener.memorized[next_dest] + if(next_dest_loc) + patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null) + signal_sent = 0 + else + if(pulledby) // Don't wiggle if someone pulls you + patrol_path = list() return - if(!path.len) - spawn(0) - path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard) - if(!path) - path = list() - return - if(path.len) - step_to(src, path[1]) - path -= path[1] - return + if(patrol_path[1] == loc) + patrol_path -= patrol_path[1] + var/moved = step_towards(src, patrol_path[1]) + if(moved) + patrol_path -= patrol_path[1] + + /mob/living/bot/cleanbot/UnarmedAttack(var/obj/effect/decal/cleanable/D, var/proximity) if(!..()) @@ -145,7 +165,7 @@ return cleaning = 1 - custom_emote(2, "begins to clean up the [D]") + custom_emote(2, "begins to clean up \the [D]") update_icons() var/cleantime = istype(D, /obj/effect/decal/cleanable/dirt) ? 10 : 50 if(do_after(src, cleantime)) @@ -155,6 +175,8 @@ if(!D) return qdel(D) + if(D == target) + target = null cleaning = 0 update_icons() From 6f68a26f79413241c492590d51bba1634eb16695 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Wed, 6 Jan 2016 17:37:01 +0100 Subject: [PATCH 205/207] Changes the version BYOND use. Do not merge until server is confirmed updated. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 405ccc07db6..09eac5ef527 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ language: c sudo: false env: - BYOND_MAJOR="508" - BYOND_MINOR="1293" + BYOND_MAJOR="509" + BYOND_MINOR="1318" cache: directories: From a00a6ae0e66b6a68e1f4e489ed380dce43669a8e Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Sun, 10 Jan 2016 22:12:12 +0000 Subject: [PATCH 206/207] Fix #11955 --- code/modules/power/cable.dm | 80 ++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 5d6aa522816..02e2147f287 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -347,64 +347,54 @@ obj/structure/cable/proc/cableColor(var/colorC) . = list() // this will be a list of all connected power objects var/turf/T -///// Z-Level Stuff - if (d1 == 11 || d1 == 12) + // Handle up/down cables + if(d1 == 11 || d1 == 12 || d2 == 11 || d2 == 12) var/turf/controllerlocation = locate(1, 1, z) for(var/obj/effect/landmark/zcontroller/controller in controllerlocation) - if(controller.up && d1 == 12) + if(controller.up && (d1 == 12 || d2 == 12)) T = locate(src.x, src.y, controller.up_target) if(T) . += power_list(T, src, 11, 1) - if(controller.down && d1 == 11) + if(controller.down && (d1 == 11 || d2 == 11)) T = locate(src.x, src.y, controller.down_target) if(T) . += power_list(T, src, 12, 1) -///// Z-Level Stuff - //get matching cables from the first direction - else if(d1) //if not a node cable - T = get_step(src, d1) - if(T) - . += power_list(T, src, turn(d1, 180), powernetless_only) //get adjacents matching cables - if(d1&(d1-1)) //diagonal direction, must check the 4 possibles adjacents tiles - T = get_step(src,d1&3) // go north/south + // Handle standard cables in adjacent turfs + for(var/cable_dir in list(d1, d2)) + if(cable_dir == 11 || cable_dir == 12 || cable_dir == 0) + continue + var/reverse = reverse_dir[cable_dir] + T = get_step(src, cable_dir) if(T) - . += power_list(T, src, d1 ^ 3, powernetless_only) //get diagonally matching cables - T = get_step(src,d1&12) // go east/west - if(T) - . += power_list(T, src, d1 ^ 12, powernetless_only) //get diagonally matching cables - - . += power_list(loc, src, d1, powernetless_only) //get on turf matching cables - -///// Z-Level Stuff - if(d2 == 11 || d2 == 12) - var/turf/controllerlocation = locate(1, 1, z) - for(var/obj/effect/landmark/zcontroller/controller in controllerlocation) - if(controller.up && d2 == 12) - T = locate(src.x, src.y, controller.up_target) + for(var/obj/structure/cable/C in T) + if((C.d1 && C.d1 == reverse) || (C.d2 && C.d2 == reverse)) + . += C + if(cable_dir & (cable_dir - 1)) // Diagonal, check for /\/\/\ style cables along cardinal directions + for(var/pair in list(NORTH|SOUTH, EAST|WEST)) + T = get_step(src, cable_dir & pair) if(T) - . += power_list(T, src, 11, 1) - if(controller.down && d2 == 11) - T = locate(src.x, src.y, controller.down_target) - if(T) - . += power_list(T, src, 12, 1) -///// Z-Level Stuff - else - //do the same on the second direction (which can't be 0) - T = get_step(src, d2) - if(T) - . += power_list(T, src, turn(d2, 180), powernetless_only) //get adjacents matching cables + var/req_dir = cable_dir ^ pair + for(var/obj/structure/cable/C in T) + if((C.d1 && C.d1 == req_dir) || (C.d2 && C.d2 == req_dir)) + . += C - if(d2&(d2-1)) //diagonal direction, must check the 4 possibles adjacents tiles - T = get_step(src,d2&3) // go north/south - if(T) - . += power_list(T, src, d2 ^ 3, powernetless_only) //get diagonally matching cables - T = get_step(src,d2&12) // go east/west - if(T) - . += power_list(T, src, d2 ^ 12, powernetless_only) //get diagonally matching cables - . += power_list(loc, src, d2, powernetless_only) //get on turf matching cables + // Handle cables on the same turf as us + for(var/obj/structure/cable/C in loc) + if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) // if either of C's d1 and d2 match either of ours + . += C - return . + if(d1 == 0) + for(var/obj/machinery/power/P in loc) + if(P.powernet == 0) continue // exclude APCs with powernet=0 + if(!powernetless_only || !P.powernet) + . += P + + // if the caller asked for powernetless cables only, dump the ones with powernets + if(powernetless_only) + for(var/obj/structure/cable/C in .) + if(C.powernet) + . -= C //should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. //needed as this can, unlike other placements, disconnect cables From 5f655dbbdb8c59f740032fb8dfb7ba2530d351fb Mon Sep 17 00:00:00 2001 From: Ryan784 Date: Wed, 20 Jan 2016 22:14:21 -0500 Subject: [PATCH 207/207] Vampire Gamemode Developement Test The Vampire gamemode, as ported right now. The gamemode is in, as well as creating a vampire through the traitor panel. All abilities seem to function, unable to test enthrall however (though I have a feeling it will have to be redone). Enthralling someone without a CKey will give you the correct response, however. Any abilities having to do with lums will need to be redone. Vamphud as well. If looking over this and pointing out errors/fixing is faster than simply porting it yourself, then feel free to do so! --- baystation12.dme | 3 + code/datums/mind.dm | 10 +- code/game/antagonist/station/vampire.dm | 24 + code/game/gamemodes/events.dm | 4 +- code/game/gamemodes/vampire/vampire.dm | 10 + code/game/gamemodes/vampire/vampire_powers.dm | 838 ++++++++++++++++++ code/game/objects/items/weapons/weaponry.dm | 5 + code/modules/admin/DB ban/functions.dm | 2 +- code/modules/client/preferences.dm | 3 +- code/modules/mob/living/carbon/human/human.dm | 2 + .../living/carbon/human/human_attackhand.dm | 25 + code/modules/mob/living/carbon/human/life.dm | 20 +- .../Chemistry-Reagents-Other.dm | 9 + .../reagents/reagent_containers/blood_pack.dm | 31 +- code/modules/spells/targeted/mind_transfer.dm | 2 +- code/modules/virus2/effect.dm | 2 + code/setup.dm | 20 +- icons/mob/mob.dmi | Bin 198582 -> 198688 bytes sound/effects/creepyshriek.ogg | Bin 0 -> 45042 bytes 19 files changed, 999 insertions(+), 11 deletions(-) create mode 100644 code/game/antagonist/station/vampire.dm create mode 100644 code/game/gamemodes/vampire/vampire.dm create mode 100644 code/game/gamemodes/vampire/vampire_powers.dm create mode 100644 sound/effects/creepyshriek.ogg diff --git a/baystation12.dme b/baystation12.dme index af6e369282f..44ca50e4e65 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -240,6 +240,7 @@ #include "code\game\antagonist\station\revolutionary.dm" #include "code\game\antagonist\station\rogue_ai.dm" #include "code\game\antagonist\station\traitor.dm" +#include "code\game\antagonist\station\vampire.dm" #include "code\game\area\ai_monitored.dm" #include "code\game\area\areas.dm" #include "code\game\area\asteroid_areas.dm" @@ -309,6 +310,8 @@ #include "code\game\gamemodes\nuclear\pinpointer.dm" #include "code\game\gamemodes\revolution\revolution.dm" #include "code\game\gamemodes\traitor\traitor.dm" +#include "code\game\gamemodes\vampire\vampire.dm" +#include "code\game\gamemodes\vampire\vampire_powers.dm" #include "code\game\gamemodes\wizard\wizard.dm" #include "code\game\jobs\access.dm" #include "code\game\jobs\job_controller.dm" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 99c467825c4..c1badaaca85 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -53,6 +53,8 @@ var/datum/faction/faction //associated faction var/datum/changeling/changeling //changeling holder + var/datum/vampire/vampire //vampire holder + var/rev_cooldown = 0 // the world.time since the mob has been brigged, or -1 if not at all @@ -72,6 +74,8 @@ if(changeling) current.remove_changeling_powers() current.verbs -= /datum/changeling/proc/EvolutionMenu + if(vampire) + current.remove_vampire_powers() current.mind = null nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user @@ -83,7 +87,8 @@ if(changeling) new_character.make_changeling() - + if(vampire) + new_character.make_vampire() if(active) new_character.key = key //now transfer the key to link the client to our new body @@ -143,7 +148,7 @@ if(href_list["add_antagonist"]) var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]] - if(antag) + if(antag) if(antag.add_antagonist(src, 1, 1, 0, 1, 1)) // Ignore equipment and role type for this. log_admin("[key_name_admin(usr)] made [key_name(src)] into a [antag.role_text].") else @@ -439,6 +444,7 @@ assigned_job = null //faction = null //Uncommenting this causes a compile error due to 'undefined type', fucked if I know. changeling = null + vampire = null initial_account = null objectives = list() special_verbs = list() diff --git a/code/game/antagonist/station/vampire.dm b/code/game/antagonist/station/vampire.dm new file mode 100644 index 00000000000..69c130e5b9c --- /dev/null +++ b/code/game/antagonist/station/vampire.dm @@ -0,0 +1,24 @@ +var/datum/antagonist/vampire/vamp + +/proc/isvampire(var/mob/player) + if(!vamp || !player.mind) + return 0 + if(player.mind in vamp.current_antagonists) + return 1 + +/datum/antagonist/vampire + id = MODE_VAMPIRE + role_type = BE_VAMPIRE + role_text = "Vampire" + role_text_plural = "Vampires" + bantype = "vampires" + feedback_tag = "vampire_objective" + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") + welcome_text = "You are a Vampire! Use harm intent and aim for the head to drink blood! Stay away from the Chaplain, and use the darkness to your advantage." + flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + antaghud_indicator = "hudchangeling" //NEEDS TO BE CHANGED + +/datum/antagonist/vampire/update_antag_mob(var/datum/mind/player) + ..() + player.current.make_vampire() diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index d49247263f9..a5ad03b6228 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -336,7 +336,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is //var/dowhat = pick("STOP THIS", "SUPPORT THIS", "CONSTANTLY INFORM THE CREW OF THIS", "IGNORE THIS", "FEAR THIS") var/aimust = pick("LIE", "RHYME", "RESPOND TO EVERY QUESTION WITH A QUESTION", "BE POLITE", "CLOWN", "BE HAPPY", "SPEAK IN SEXUAL INNUENDOS", "TALK LIKE A PIRATE", "QUESTION AUTHORITY", "SHOUT", "BE DISTRACTED", "HEY LISTEN", "MUMBLE", "SPEAK IN HAIKU") var/define = pick("ABSENCE OF CYBORG HUGS", "LACK OF BEATINGS", "UNBOLTED AIRLOCKS", "BOLTED AIRLOCKS", "IMPROPERLY WORDED SENTENCES", "POOR SENTENCE STRUCTURE", "BRIG TIME", "NOT REPLACING EVERY SECOND WORD WITH HONK", "HONKING", "PRESENCE OF LIGHTS", "LACK OF BEER", "WEARING CLOTHING", "NOT SAYING HELLO WHEN YOU SPEAK", "ANSWERING REQUESTS NOT EXPRESSED IN IAMBIC PENTAMETER", "A SMALL ISLAND OFF THE COAST OF PORTUGAL", "ANSWERING REQUESTS THAT WERE MADE WHILE CLOTHED") - var/target = pick("a traitor", "a syndicate agent", "a changeling", "a wizard", "the head of a revolution", "Soviet spy", "a good person", "a dwarf", "an elf", "a fairy princess", "the captain", "Beepsky", "God", "a pirate", "a gryphon", "a chryssalid") + var/target = pick("a traitor", "a syndicate agent", "a changeling", "a vampire", "a wizard", "the head of a revolution", "Soviet spy", "a good person", "a dwarf", "an elf", "a fairy princess", "the captain", "Beepsky", "God", "a pirate", "a gryphon", "a chryssalid") var/require = pick("ADDITIONAL PYLONS", "MORE VESPENE GAS", "MORE MINERALS", "THE ULTIMATE CUP OF COFFEE", "HIGH YIELD EXPLOSIVES", "THE CLOWN", "THE VACUUM OF SPACE", "IMMORTALITY", "SAINTHOOD", "ART", "VEGETABLES", "FAT PEOPLE", "MORE LAWS", "MORE DAKKA", "HERESY", "CORPSES", "TRAITORS", "MONKEYS", "AN ARCADE", "PLENTY OF GOLD", "FIVE TEENAGERS WITH ATTITUDE") var/allergy = pick("cotton", "uniforms", "acid", "oxygen", "human contact", "cyborg contact", "medicine", "floors") var/allergysev = pick("deathly", "mildly", "severely", "contagiously") @@ -468,4 +468,4 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is world << "Ion Storm Main Done" - */ \ No newline at end of file + */ diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm new file mode 100644 index 00000000000..515799d8837 --- /dev/null +++ b/code/game/gamemodes/vampire/vampire.dm @@ -0,0 +1,10 @@ +/datum/game_mode/vampire + name = "Vampire" + round_description = "There are Vampires from Space Transylvania on the station, keep your blood close and neck safe!" + extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck." + config_tag = "vampire" + required_players = 1 + required_enemies = 1 + end_on_antag_death = 1 + antag_scaling_coeff = 8 + antag_tags = list(MODE_VAMPIRE) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm new file mode 100644 index 00000000000..0d7f4c8c5e9 --- /dev/null +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -0,0 +1,838 @@ + + +/datum/vampire + var/list/datum/mind/vampires = list() + var/list/datum/mind/enthralled = list() //those controlled by a vampire + var/list/thralls = list() //vammpires controlling somebody + var/bloodtotal = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS + var/bloodusable = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS + var/mob/living/owner = null + var/gender = FEMALE + var/iscloaking = 0 // handles the vampire cloak toggle + var/list/powers = list() // list of available powers and passives, see defines in setup.dm + var/mob/living/carbon/human/draining // who the vampire is draining of blood + var/nullified = 0 //Nullrod makes them useless for a short while. + +/datum/vampire/New(gend = FEMALE) + ..() + gender = gend + + + + +/mob/proc/make_vampire() + if(!mind) return + if(!mind.vampire) + mind.vampire = new /datum/vampire(gender) + mind.vampire.owner = src + verbs += /client/vampire/proc/vampire_rejuvinate + verbs += /client/vampire/proc/vampire_hypnotise + verbs += /client/vampire/proc/vampire_glare + //testing purposes REMOVE BEFORE PUSH TO MASTER + /*for(var/handler in typesof(/client/proc)) + if(findtext("[handler]","vampire_")) + verbs += handler*/ + for(var/i = 1; i <= 3; i++) // CHANGE TO 3 RATHER THAN 12 AFTER TESTING IS DONE + if(!(i in mind.vampire.powers)) + mind.vampire.powers.Add(i) + + + for(var/n in mind.vampire.powers) + switch(n) + if(VAMP_SHAPE) + verbs += /client/vampire/proc/vampire_shapeshift + if(VAMP_VISION) + continue + if(VAMP_DISEASE) + verbs += /client/vampire/proc/vampire_disease + if(VAMP_CLOAK) + verbs += /client/vampire/proc/vampire_cloak + if(VAMP_BATS) + verbs += /client/vampire/proc/vampire_bats + if(VAMP_SCREAM) + verbs += /client/vampire/proc/vampire_screech + if(VAMP_JAUNT) + verbs += /client/vampire/proc/vampire_jaunt + if(VAMP_BLINK) + verbs += /client/vampire/proc/vampire_shadowstep + if(VAMP_SLAVE) + verbs += /client/vampire/proc/vampire_enthrall + if(VAMP_FULL) + continue + +/mob/proc/remove_vampire_powers() + for(var/handler in typesof(/client/vampire/proc)) + if(findtext("[handler]","vampire_")) + verbs -= handler + +/mob/proc/handle_bloodsucking(mob/living/carbon/human/H) + src.mind.vampire.draining = H + var/blood = 0 + var/bloodtotal = 0 //used to see if we increased our blood total + var/bloodusable = 0 //used to see if we increased our blood usable + + src.visible_message("\red [src.name] bites [H.name]'s neck!", "\red You bite [H.name]'s neck and begin to drain their blood.", "\blue You hear a soft puncture and a wet sucking noise") + if(!iscarbon(src)) + H.LAssailant = null + else + H.LAssailant = src + while(do_mob(src, H, 50)) + if(!mind.vampire) + src << "\red Your fangs have disappeared!" + return 0 + bloodtotal = src.mind.vampire.bloodtotal + bloodusable = src.mind.vampire.bloodusable + if(!H.vessel.get_reagent_amount("blood")) + src << "\red They've got no blood left to give." + break + if(H.stat < 2) //alive + blood = min(10, H.vessel.get_reagent_amount("blood"))// if they have less than 10 blood, give them the remnant else they get 10 blood + src.mind.vampire.bloodtotal += blood + src.mind.vampire.bloodusable += blood +// H.adjustCloneLoss(10) // beep boop 10 damage //probably not necessary actually honestly okay + else + blood = min(5, H.vessel.get_reagent_amount("blood"))// The dead only give 5 bloods + src.mind.vampire.bloodtotal += blood + if(bloodtotal != src.mind.vampire.bloodtotal) + src << "\blue You have accumulated [src.mind.vampire.bloodtotal] [src.mind.vampire.bloodtotal > 1 ? "units" : "unit"] of blood[src.mind.vampire.bloodusable != bloodusable ?", and have [src.mind.vampire.bloodusable] left to use" : "."]" + check_vampire_upgrade(mind) + H.vessel.remove_reagent("blood",25) + + src.mind.vampire.draining = null + src << "\blue You stop draining [H.name] of blood." + return 1 + +/mob/proc/check_vampire_upgrade(datum/mind/v) + if(!v) return + if(!v.vampire) return + var/datum/vampire/vamp = v.vampire + var/list/old_powers = vamp.powers.Copy() + + // This used to be a switch statement. + // Don't use switch statements for shit like this, since blood can be any random-ass value. + // if(100) requires the blood to be at EXACTLY 100 units to trigger. + // if(blud >= 100) activates when blood is at or over 100 units. + // TODO: Make this modular. + + // TIER 1 + if(vamp.bloodtotal >= 100) + if(!(VAMP_VISION in vamp.powers)) + vamp.powers.Add(VAMP_VISION) + if(!(VAMP_SHAPE in vamp.powers)) + vamp.powers.Add(VAMP_SHAPE) + + // TIER 2 + if(vamp.bloodtotal >= 150) + if(!(VAMP_CLOAK in vamp.powers)) + vamp.powers.Add(VAMP_CLOAK) + + + // TIER 3 + if(vamp.bloodtotal >= 200) + if(!(VAMP_BATS in vamp.powers)) + vamp.powers.Add(VAMP_BATS) + if(!(VAMP_SCREAM in vamp.powers)) + vamp.powers.Add(VAMP_SCREAM) + src << "\blue Your rejuvination abilities have improved and will now heal you over time when used." + if(!(VAMP_DISEASE in vamp.powers)) + vamp.powers.Add(VAMP_DISEASE) + + // TIER 3.5 (/vg/) + if(vamp.bloodtotal >= 250) + if(!(VAMP_BLINK in vamp.powers)) + vamp.powers.Add(VAMP_BLINK) + + // TIER 4 + if(vamp.bloodtotal >= 300) + if(!(VAMP_JAUNT in vamp.powers)) + vamp.powers.Add(VAMP_JAUNT) + if(!(VAMP_SLAVE in vamp.powers)) + vamp.powers.Add(VAMP_SLAVE) + + // TIER 5 + if(vamp.bloodtotal >= 500) + if(!(VAMP_FULL in vamp.powers)) + vamp.powers.Add(VAMP_FULL) + + announce_new_power(old_powers, vamp.powers) + +/mob/proc/announce_new_power(list/old_powers, list/new_powers) + for(var/n in new_powers) + if(!(n in old_powers)) + switch(n) + if(VAMP_SHAPE) + src << "\blue You have gained the shapeshifting ability, at the cost of stored blood you can change your form permanently." + verbs += /client/vampire/proc/vampire_shapeshift + if(VAMP_VISION) + src << "\blue Your vampiric vision has improved." + //no verb + if(VAMP_DISEASE) + src << "\blue You have gained the Diseased Touch ability which causes those you touch to die shortly after unless treated medically." + verbs += /client/vampire/proc/vampire_disease + if(VAMP_CLOAK) + src << "\blue You have gained the Cloak of Darkness ability which when toggled makes you near invisible in the shroud of darkness." + verbs += /client/vampire/proc/vampire_cloak + if(VAMP_BATS) + src << "\blue You have gained the Summon Bats ability." + verbs += /client/vampire/proc/vampire_bats // work in progress + if(VAMP_SCREAM) + src << "\blue You have gained the Chiropteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process." + verbs += /client/vampire/proc/vampire_screech + if(VAMP_JAUNT) + src << "\blue You have gained the Mist Form ability which allows you to take on the form of mist for a short period and pass over any obstacle in your path." + verbs += /client/vampire/proc/vampire_jaunt + if(VAMP_SLAVE) + src << "\blue You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time." + verbs += /client/vampire/proc/vampire_enthrall + if(VAMP_BLINK) + src << "\blue You have gained the ability to shadowstep, which makes you disappear into nearby shadows at the cost of blood." + verbs += /client/vampire/proc/vampire_shadowstep + if(VAMP_FULL) + src << "\blue You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly." + //no verb + + //This should hold all the vampire related powers + + +/mob/proc/vampire_power(required_blood=0, max_stat=0) + + if(!src.mind) return 0 + if(!ishuman(src)) + src << "You are in too weak of a form to do this!" + return 0 + + var/datum/vampire/vampire = src.mind.vampire + + if(!vampire) + //msg_scopes("[src] has vampire verbs but isn't a vampire.") + world.log << "[src] has vampire verbs but isn't a vampire." + return 0 + + var/fullpower = (VAMP_FULL in vampire.powers) + + if(src.stat > max_stat) + src << "You are incapacitated." + return 0 + + if(vampire.nullified) + if(!fullpower) + src << "Something is blocking your powers!" + return 0 + if(vampire.bloodusable < required_blood) + src << "You require at least [required_blood] units of usable blood to do that!" + return 0 + //chapel check + if(istype(loc.loc, /area/chapel)) + if(!fullpower) + src << "Your powers are useless on this holy ground." + return 0 + return 1 + +/mob/proc/vampire_affected(datum/mind/M) + //Other vampires aren't affected + if(mind && mind.vampire) return 0 + //Chaplains are resistant to vampire powers + if(mind && mind.assigned_role == "Chaplain") + return 0 + if(get_species() == "Machine") + return 0 + //Vampires who have reached their full potential can affect nearly everything + if(M && M.vampire && (VAMP_FULL in M.vampire.powers)) + return 1 // This doesn't really need to be here because of well the line below it. + return 1 + +/mob/proc/vampire_can_reach(mob/M as mob, active_range = 1) + if(M.loc == src.loc) return 1 //target and source are in the same thing + if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something. + if(Adjacent(M))//if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, active_range)) //If a path exists, good! + return 1 + return 0 + +/mob/proc/vampire_active(required_blood=0, max_stat=0, active_range=1) + var/pass = vampire_power(required_blood, max_stat) + if(!pass) return + var/datum/vampire/vampire = mind.vampire + if(!vampire) return + var/list/victims = list() + for(var/mob/living/carbon/C in view(active_range)) + if(C==src) continue + victims += C + var/mob/living/carbon/T = input(src, "Victim?") as null|anything in victims + + if(!T) return + if(!(T in view(active_range))) return + if(!vampire_can_reach(T, active_range)) return + if(!vampire_power(required_blood, max_stat)) return + return T + +/client/vampire/proc/vampire_rejuvinate() + set category = "Abilities" + set name = "Rejuvinate " + set desc= "Flush your system with spare blood to remove any incapacitating effects" + var/datum/mind/M = usr.mind + if(!M) return + if(M.current.vampire_power(0, 1)) + M.current.weakened = 0 + M.current.stunned = 0 + M.current.paralysis = 0 + //M.vampire.bloodusable -= 10 + M.current << "\blue You flush your system with clean blood and remove any incapacitating effects." + spawn(1) + if(M.vampire.bloodtotal >= 200) + for(var/i = 0; i < 5; i++) + M.current.adjustBruteLoss(-2) + M.current.adjustOxyLoss(-5) + M.current.adjustToxLoss(-2) + M.current.adjustFireLoss(-2) + sleep(35) + M.current.verbs -= /client/vampire/proc/vampire_rejuvinate + spawn(200) + M.current.verbs += /client/vampire/proc/vampire_rejuvinate + +/client/vampire/proc/vampire_hypnotise() + set category = "Abilities" + set name = "Hypnotise" // (20) + set desc= "A piercing stare that incapacitates your victim for a good length of time." + var/datum/mind/M = usr.mind + if(!M) return + + var/mob/living/carbon/C = M.current.vampire_active(0, 0, 1) //(20, 0, 1) + + if(!C) return + if(C==usr) + M.current << "\red You can't do that to yourself" + return + + if(!M.current.has_eyes()) + M.current << "\red You don't have eyes" + return + + var/vampgender + if(M.current.gender == "male") + vampgender = "he" + else + vampgender = "she" + + M.current.visible_message("[M]'s eyes flash briefly as [vampgender] stares into [C.name]'s eyes") +// M.current.remove_vampire_blood(20) Moved to remove if it works only. + if(M.current.vampire_power(0, 0)) //if(M.current.vampire_power(20, 0)) + M.current.verbs -= /client/vampire/proc/vampire_hypnotise + spawn(1200) + M.current.verbs += /client/vampire/proc/vampire_hypnotise + if(do_mob(M.current, C, 50)) + if(C.mind && C.mind.vampire) + M.current << "\red Your piercing gaze fails to knock out [C.name]." + C << "\blue [M.current]'s feeble gaze is ineffective." + return + else + M.current << "\red Your piercing gaze knocks out [C.name]." + C << "\red You find yourself unable to move and barely able to speak" + C.Weaken(20) + C.Stun(20) + C.stuttering = 20 +// M.current.remove_vampire_blood(20) + else + M.current << "\red You broke your gaze." + return + +/client/vampire/proc/vampire_disease() + set category = "Abilities" + set name = "Diseased Touch (200)" + set desc = "Touches your victim with infected blood giving them the Shutdown Syndrome which quickly shutsdown their major organs resulting in a quick painful death." + var/datum/mind/M = usr.mind + if(!M) return + + var/mob/living/carbon/C = M.current.vampire_active(200, 0, 1) + if(!C) return + if(C==usr) + M.current << "\red You can't do that to yourself" + return + if(C.get_species() == "Machine") + M.current << "\red You can't to that to a machine" + return + if(!M.current.vampire_can_reach(C, 1)) + M.current << "\red You cannot touch [C.name] from where you are standing!" + return + M.current << "\red You stealthily infect [C.name] with your diseased touch." + /*var/t_him = "it" + if (src.gender == MALE) + t_him = "him" + else if (src.gender == FEMALE) + t_him = "her" + M.current.visible_message("\blue [M] shakes [src] trying to wake [t_him] up!" ) + playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)*/ + C.help_shake_act(M.current) // i use da colon + if(!C.vampire_affected(M)) + M.current << "\red They seem to be unaffected." + return + var/datum/disease2/disease/shutdown = new /datum/disease2/disease + var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder + var/datum/disease2/effect/organs/vampire/O = new /datum/disease2/effect/organs/vampire + holder.effect += O + holder.chance = 10 + shutdown.infectionchance = 100 + shutdown.antigen |= text2num(pick(ALL_ANTIGENS)) + shutdown.antigen |= text2num(pick(ALL_ANTIGENS)) + shutdown.spreadtype = "None" + shutdown.uniqueID = rand(0,10000) + shutdown.effects += holder + shutdown.speed = 1 + shutdown.stage = 2 + shutdown.clicks = 185 + msg_admin_attack("[key_name_admin(usr)] gave [key_name_admin(C)] the shutdown disease - JMP") + usr.attack_log += text("\[[time_stamp()]\] Gave [C.name] ([C.ckey]) the shutdown disease") + C.attack_log += text("\[[time_stamp()]\] Has been given the shutdown disease by [usr.name] ([usr.ckey])") + infect_virus2(C,shutdown,0) + M.current.remove_vampire_blood(200) + M.current.verbs -= /client/vampire/proc/vampire_disease + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_disease + +/client/vampire/proc/vampire_glare() + set category = "Abilities" + set name = "Glare" + set desc= "A scary glare that incapacitates people for a short while around you." + var/datum/mind/M = usr.mind + if(!M) return + + if(!M.current.has_eyes()) + M.current << "\red You don't have eyes" + return + + if(M.current.vampire_power(0, 1)) + M.current.visible_message("\red [M.current]'s eyes emit a blinding flash!") + //M.vampire.bloodusable -= 10 + M.current.verbs -= /client/vampire/proc/vampire_glare + spawn(800) + M.current.verbs += /client/vampire/proc/vampire_glare + if(istype(M.current:glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) + M.current << "You're blindfolded!" + return + for(var/mob/living/carbon/C in view(1)) + if(C == M.current) continue //Don't stunn yourself + if(!C.vampire_affected(M) && !C.get_species() == "Machine") //Or machines + continue + if(!M.current.vampire_can_reach(C, 1)) continue +// C.Stun(8) + C.Weaken(8) + C.stuttering = 20 + C << "\red You are blinded by [M.current]'s glare" + +/client/vampire/proc/vampire_shapeshift() //Hi. I'm stupid and there are missing procs all around. Namely the randomname proc. I can't find it and can't code a new one because I am bad. Sorry! + set category = "Abilities" + set name = "Shapeshift (50)" + set desc = "This does nothing. It's broken. Sorry!"//orig text: Changes your name and appearance at the cost of 50 blood and has a cooldown of 3 minutes. +/* var/datum/mind/M = usr.mind + if(!M) return + if(M.current.vampire_power(50, 0)) + M.current.visible_message("[M.current.name] transforms!") + M.current.client.prefs.real_name = M.current.generate_name() //random_name(M.current.gender) + M.current.client.prefs.randomize_appearance_for(M.current) + M.current.regenerate_icons() + M.current.remove_vampire_blood(50) + M.current.verbs -= /client/vampire/proc/vampire_shapeshift + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_shapeshift +*/ +/client/vampire/proc/vampire_screech() + set category = "Abilities" + set name = "Chiropteran Screech (90)" + set desc = "An extremely loud shriek that stuns nearby humans in a four-tile radius, as well as shattering the windows." + var/datum/mind/M = usr.mind + if(!M) return + if(M.current.vampire_power(90, 0)) + M.current.visible_message("\red [M.current.name] lets out an ear piercing shriek!", "\red You let out a loud shriek.", "\red You hear a loud painful shriek!") + for(var/mob/living/carbon/C in hearers(4, M.current)) + if(C == M.current) continue + if(ishuman(C) && (C:l_ear || C:r_ear) && istype((C:l_ear || C:r_ear), /obj/item/clothing/ears/earmuffs)) continue + if(!C.vampire_affected(M)) + if(!C.get_species() == "Machine") + continue + C << "You hear a ear piercing shriek and your senses dull!" + C.Weaken(5) + C.ear_deaf = 20 + C.stuttering = 20 + C.Stun(5) +// C.Jitter(150) + for(var/obj/structure/window/W in view(7)) + W.shatter() + playsound(M.current.loc, 'sound/effects/creepyshriek.ogg', 100, 1) + M.current.remove_vampire_blood(90) + M.current.verbs -= /client/vampire/proc/vampire_screech + spawn(3600) M.current.verbs += /client/vampire/proc/vampire_screech + +/client/vampire/proc/vampire_enthrall() + set category = "Abilities" + set name = "Enthrall (150)" + set desc = "You use a large portion of your power to sway those loyal to none to be loyal to you only." + var/datum/mind/M = usr.mind + if(!M) return + var/mob/living/carbon/C = M.current.vampire_active(150, 0, 1) + if(!C) return + if(C==usr) + M.current << "\red You can't do that to yourself" + return + if(C.get_species() == "Machine") + M.current << "\red You can only enthrall humans" + return + M.current.visible_message("\red [M.current.name] bites [C.name]'s neck!", "\red You bite [C.name]'s neck and begin the flow of power.") + C << "You feel the tendrils of evil invade your mind." + if(!ishuman(C)) + M.current << "\red You can only enthrall humans" + return + + if(do_mob(M.current, C, 50)) + if(M.current.can_enthrall(C)) // recheck + if(M.current.vampire_power(150, 0)) + M.current.handle_enthrall(C) + M.current.remove_vampire_blood(150) + M.current.verbs -= /client/vampire/proc/vampire_enthrall + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_enthrall + return + else + M.current << "\red You or your target either moved or you dont have enough usable blood." + return + +/client/vampire/proc/vampire_cloak() + set category = "Abilities" + set name = "Cloak of Darkness (toggle)" + set desc = "Toggles whether you are currently cloaking yourself in darkness." + var/datum/mind/M = usr.mind + if(!M) return + if(M.current.vampire_power(0, 0)) + M.vampire.iscloaking = !M.vampire.iscloaking + M.current << "\blue You will now be [M.vampire.iscloaking ? "hidden" : "seen"] in darkness." + +/mob/proc/handle_vampire_cloak() + if(!mind || !mind.vampire || !ishuman(src)) + alpha = 255 + return + var/turf/simulated/T = get_turf(src) + + if(!istype(T)) + return 0 + + if(!mind.vampire.iscloaking) + alpha = 255 + return 0 +// if(T.lighting_lumcount <= 2) +// alpha = round((255 * 0.15)) +// return 1 + else + alpha = round((255 * 0.80)) + +/mob/proc/can_enthrall(mob/living/carbon/C) + var/enthrall_safe = 0 + var/datum/vampire/vampire = src.mind.vampire + for(var/obj/item/weapon/implant/loyalty/L in C) + if(L && L.implanted) + enthrall_safe = 1 + break +// for(var/obj/item/weapon/implant/traitor/T in C) +// if(T && T.implanted) +// enthrall_safe = 1 +// break + if(!C) + world.log << "something bad happened on enthralling a mob src is [src] [src.key] \ref[src]" + return 0 + if(!C.mind) + src << "\red [C.name]'s mind is not there for you to enthrall." + return 0 + if(enthrall_safe || ( C.mind in vampire.vampires )||( C.mind.vampire )||( C.mind in vampire.enthralled )) + C.visible_message("\red [C] seems to resist the takeover!", "\blue You feel a familiar sensation in your skull that quickly dissipates.") + return 0 + if(!C.vampire_affected(mind)) + C.visible_message("\red [C] seems to resist the takeover!", "\blue Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil") + return 0 + if(!ishuman(C)) + src << "\red You can only enthrall humans!" + return 0 + return 1 + +/mob/proc/handle_enthrall(mob/living/carbon/human/H as mob) + if(!istype(H)) + //msg_scopes("handle_enthrall fucked up with no H < [src]") + src << "\red SOMETHING WENT WRONG, YELL AT POMF OR NEXIS" + return 0 + var/ref = "\ref[src.mind]" + if(!(src.mind.vampire.thralls)) + src.mind.vampire.thralls[ref] = list(H.mind) + else + src.mind.vampire.thralls[ref] += H.mind + //msg_scopes("[H.name] Changed in handle_enthrall") //purely here to see live changes incase of unexpected things + src.mind.vampire.enthralled.Add(H.mind) + src.mind.vampire.enthralled[H.mind] = src.mind + H.mind.special_role = "VampThrall" + H << "\red You have been Enthralled by [name]. Follow their every command." + src << "\red You have successfully Enthralled [H.name]. If they refuse to do as you say just adminhelp." + var/client/vampire/c = src + c.update_vampire_icons_added(H.mind) + c.update_vampire_icons_added(src.mind) + msg_admin_attack("[key_name_admin(src)] has mind-slaved [key_name_admin(H)] - JMP.") + +/client/vampire/proc/vampire_bats() + set category = "Abilities" + set name = "Summon Bats (60)" + set desc = "You summon a pair of space bats who attack nearby targets until they or their target is dead." + var/datum/mind/M = usr.mind + if(!M) return + if(M.current.vampire_power(60, 0)) + var/list/turf/locs = new + var/number = 0 + for(var/direction in alldirs) //looking for bat spawns + if(locs.len == 2) //we found 2 locations and thats all we need + break + var/turf/T = get_step(M.current,direction) //getting a loc in that direction + if(AStar(M.current.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1)) // if a path exists, so no dense objects in the way its valid salid + locs += T + if(locs.len) + for(var/turf/tospawn in locs) + number++ + new /mob/living/simple_animal/hostile/scarybat(tospawn, M.current) + if(number != 2) //if we only found one location, spawn one on top of our tile so we dont get stacked bats + new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current) + else // we had no good locations so make two on top of us + new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current) + new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current) + M.current.remove_vampire_blood(60) + M.current.verbs -= /client/vampire/proc/vampire_bats + spawn(1200) M.current.verbs += /client/vampire/proc/vampire_bats + +/client/vampire/proc/vampire_jaunt() + //AHOY COPY PASTE INCOMING + set category = "Abilities" + set name = "Mist Form (30)" + set desc = "You take on the form of mist for a short period of time." + var/jaunt_duration = 50 //in deciseconds + var/datum/mind/M = usr.mind + if(!M) return + + if(M.current.vampire_power(30, 0)) + if(M.current.buckled) M.current.buckled.unbuckle_mob() + spawn(0) + var/originalloc = get_turf(M.current.loc) + var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( originalloc ) + var/atom/movable/overlay/animation = new /atom/movable/overlay( originalloc ) + animation.name = "water" + animation.density = 0 + animation.anchored = 1 + animation.icon = 'icons/mob/mob.dmi' + animation.icon_state = "liquify" + animation.layer = 5 + animation.master = holder + M.current.ExtinguishMob() + M.current.weakened = 0 + M.current.stunned = 0 + if(M.current.buckled) + M.current.buckled.unbuckle_mob() + flick("liquify",animation) + M.current.loc = holder + M.current.client.eye = holder + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, originalloc) + steam.start() + sleep(jaunt_duration) + var/mobloc = get_turf(M.current.loc) +/* if(get_area(mobloc) == /area/security/armoury/gamma) + M << "A strange energy repels you!" + mobloc = originalloc*/ + animation.loc = mobloc + steam.location = mobloc + steam.start() + M.current.canmove = 0 + sleep(20) + flick("reappear",animation) + sleep(5) + if(!M.current.Move(mobloc)) + for(var/direction in list(1,2,4,8,5,6,9,10)) + var/turf/T = get_step(mobloc, direction) + if(T) + if(M.current.Move(T)) + break + M.current.canmove = 1 + M.current.client.eye = M.current + qdel(animation) + qdel(holder) + M.current.remove_vampire_blood(30) + M.current.verbs -= /client/vampire/proc/vampire_jaunt + spawn(600) M.current.verbs += /client/vampire/proc/vampire_jaunt + +// Blink for vamps +// Less smoke spam. +/client/vampire/proc/vampire_shadowstep() + set category = "Abilities" + set name = "Shadowstep (30)" + set desc = "Vanish into the shadows." + var/datum/mind/M = usr.mind + if(!M) return + + // Teleport radii + var/inner_tele_radius = 0 + var/outer_tele_radius = 6 + + // Maximum lighting_lumcount. +// var/max_lum = 1 + + if(M.current.vampire_power(30, 0)) + if(M.current.buckled) M.current.buckled.unbuckle_mob() + spawn(0) + var/list/turfs = new/list() + for(var/turf/T in range(usr,outer_tele_radius)) + if(T in range(usr,inner_tele_radius)) continue + if(istype(T,/turf/space)) continue + if(T.density) continue + if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.y max_lum) continue + // turfs += T + //M.current.remove_vampire_blood(30) This isn't the right place for this either. + + if(!turfs.len) + usr << "\red You cannot find darkness to step to." + return + + var/turf/picked = pick(turfs) + + if(!picked || !isturf(picked)) + return + M.current.ExtinguishMob() + if(M.current.buckled) + M.current.buckled.unbuckle_mob() + var/atom/movable/overlay/animation = new /atom/movable/overlay( get_turf(usr) ) + animation.name = usr.name + animation.density = 0 + animation.anchored = 1 + animation.icon = usr.icon + animation.alpha = 127 + animation.layer = 5 + //animation.master = src + usr.loc = picked + M.current.remove_vampire_blood(30) + spawn(10) + del(animation) +// M.current.remove_vampire_blood(30) + M.current.verbs -= /client/vampire/proc/vampire_shadowstep + spawn(20) + M.current.verbs += /client/vampire/proc/vampire_shadowstep + +/mob/proc/remove_vampire_blood(amount = 0) + var/bloodold + if(!mind || !mind.vampire) + return + bloodold = mind.vampire.bloodusable + mind.vampire.bloodusable = max(0, (mind.vampire.bloodusable - amount)) + if(bloodold != mind.vampire.bloodusable) + src << "\blue You have [mind.vampire.bloodusable] left to use." + +//prepare for copypaste +/client/vampire/proc/update_vampire_icons_added(datum/mind/vampire_mind) + var/ref = "\ref[vampire_mind]" + if(ref in vampire_mind.vampire.thralls) + if(vampire_mind.current) + if(vampire_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = vampire_mind.current, icon_state = "vampire") + vampire_mind.current.client.images += I + for(var/headref in vampire_mind.vampire.thralls) + for(var/datum/mind/t_mind in vampire_mind.vampire.thralls[headref]) + var/datum/mind/head = locate(headref) + if(head) + if(head.current) + if(head.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall") + head.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "vampire") + t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall") + t_mind.current.client.images += I + +/client/vampire/proc/update_vampire_icons_removed(datum/mind/vampire_mind) + for(var/headref in vampire_mind.vampire.thralls) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in vampire_mind.vampire.thralls[headref]) + if(t_mind.current) + if(t_mind.current.client) + for(var/image/I in t_mind.current.client.images) + if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current) + //world.log << "deleting [vampire_mind] overlay" + del(I) + if(head) + //world.log << "found [head.name]" + if(head.current) + if(head.current.client) + for(var/image/I in head.current.client.images) + if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current) + //world.log << "deleting [vampire_mind] overlay" + del(I) + if(vampire_mind.current) + if(vampire_mind.current.client) + for(var/image/I in vampire_mind.current.client.images) + if(I.icon_state == "vampthrall" || I.icon_state == "vampire") + del(I) + +/client/vampire/proc/remove_vampire_mind(datum/mind/vampire_mind, datum/mind/head) + //var/list/removal + if(!istype(head)) + head = vampire_mind //workaround for removing a thrall's control over the enthralled + var/ref = "\ref[head]" + if(vampire_mind.vampire.thralls) + vampire_mind.vampire.thralls[ref] -= vampire_mind + vampire_mind.vampire.enthralled -= vampire_mind + //vampire.special_role = null + update_vampire_icons_removed(vampire_mind) + //world << "Removed [vampire_mind.current.name] from vampire shit" + vampire_mind.current << "\red The fog clouding your mind clears. You remember nothing from the moment you were enthralled until now." + +/mob/living/carbon/human/proc/check_sun() + + var/ax = x + var/ay = y + + for(var/i = 1 to 20) + ax += sun.dx + ay += sun.dy + + var/turf/T = locate( round(ax,0.5),round(ay,0.5),z) + + if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) + break + + if(T.density) + return + if(prob(35)) + switch(health) + if(80 to 100) + src << "\red Your skin flakes away..." + if(60 to 80) + src << "Your skin sizzles!" + // if((-INFINITY) to 60) + // if(!on_fire) + // src << "\red Your skin catches fire!" + // else + // src << "\red You continue to burn!" + // fire_stacks += 5 + // IgniteMob() + // emote("scream") + //else + // switch(health) + // if((-INFINITY) to 60) + // fire_stacks++ + // IgniteMob() + adjustFireLoss(30) //Original value was 3. Barely did anything. Vamps should vaporize in starlight. + +/mob/living/carbon/human/proc/handle_vampire() +/* if(hud_used) + if(!hud_used.vampire_blood_display) + hud_used.vampire_hud() + hud_used.human_hud('icons/mob/screen1_Vampire.dmi') + hud_used.vampire_blood_display.maptext_width = 64 + hud_used.vampire_blood_display.maptext_height = 26 + hud_used.vampire_blood_display.maptext = "
            U:[mind.vampire.bloodusable]
            T:[mind.vampire.bloodtotal]
            " + */ + handle_vampire_cloak() + if(istype(loc, /turf/space)) + check_sun() + mind.vampire.nullified = max(0, mind.vampire.nullified - 1) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 867c5155e08..730adfca1f8 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -53,6 +53,11 @@ user << "You wave [src] over [M]'s head and see their eyes become clear, their mind returning to normal." cult.remove_antagonist(M.mind) M.visible_message("\The [user] waves \the [src] over \the [M]'s head.") + else if(M.mind && M.mind.vampire) + if(!(VAMP_FULL in M.mind.vampire.powers)) + user << "\red The rod burns cold in your hand, filling you with grim determination. You feel the creature's power weaken." + M << "The nullrod's power interferes with your own! They are on to you!" + M.mind.vampire.nullified = max(8, M.mind.vampire.nullified + 8) else if(prob(10)) user << "The rod slips in your hand." ..() diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 8e1ad3aa798..56bbbb8a008 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -302,7 +302,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" for(var/j in nonhuman_positions) output += "" - var/list/bantypes = list("traitor","changeling","operative","revolutionary","cultist","wizard") //For legacy bans. + var/list/bantypes = list("traitor","changeling","vampire","operative","revolutionary","cultist","wizard") //For legacy bans. for(var/antag_type in all_antag_types) // Grab other bans. var/datum/antagonist/antag = all_antag_types[antag_type] bantypes |= antag.bantype diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 7e69a279bea..ca5f210f479 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -19,7 +19,8 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set "raider" = IS_MODE_COMPILED("heist"), // 11 "diona" = 1, // 12 "loyalist" = IS_MODE_COMPILED("revolution"), // 13 - "pAI candidate" = 1, // -- TLE // 14 + "vampire" = IS_MODE_COMPILED("vampire"), // 14 + "pAI candidate" = 1, // -- TLE // 15 ) //used for alternate_option diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index cabbc1474f3..20fd7b07f8f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -79,6 +79,8 @@ stat(null, "Suit charge: [cell_status]") if(mind) + if(mind.vampire) + stat("Blood", mind.vampire.bloodusable) if(mind.changeling) stat("Chemical Storage", mind.changeling.chem_charges) stat("Genetic Damage Time", mind.changeling.geneticdamage) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 9c17339e4cb..d1161585254 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -108,6 +108,31 @@ return 1 if(I_HURT) + //Vampire code + if(H.zone_sel && M.zone_sel.selecting == "head") + if(H.mind && H.mind.vampire && !H.mind.vampire.draining) + if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH))) + H << "\red Remove their mask!" + return 0 + if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) + H << "\red Remove your mask!" + return 0 + if(mind && mind.vampire) + H << "\red Your fangs fail to pierce [src.name]'s cold flesh" + return 0 + if(get_species() == "Machine") + H << "\red They have no blood" + return 0 + //we're good to suck the blood, blaah + //and leave an attack log + H.attack_log += text("\[[time_stamp()]\] Bit [src.name] ([src.ckey]) in the neck and draining their blood") + src.attack_log += text("\[[time_stamp()]\] Has been bit in the neck by [H.name] ([H.ckey])") + msg_admin_attack("[key_name_admin(H)] bit [key_name_admin(src)] in the neck - JMP") + H.handle_bloodsucking(src) + // var/datum/organ/external/affecting = get_organ(src.zone_sel.selecting) + // affecting.take_damage(10,0,1,0,"dual puncture marks") //this does not work and causes runtimes. + return + //end vampire codes if(!istype(H)) attack_generic(H,rand(1,3),"punched") diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index ddd0c9ef8c3..e7fa1ef4ab3 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -130,6 +130,8 @@ for(var/obj/item/weapon/grab/G in src) G.process() + if(mind && mind.vampire) + handle_vampire() // Calculate how vulnerable the human is to under- and overpressure. // Returns 0 (equals 0 %) if sealed in an undamaged suit, 1 if unprotected (equals 100%). // Suitdamage can modifiy this in 10% steps. @@ -366,14 +368,14 @@ get_breath_from_environment(var/volume_needed=BREATH_VOLUME) var/datum/gas_mixture/breath = ..() - + if(breath) //exposure to extreme pressures can rupture lungs var/check_pressure = breath.return_pressure() if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5) if(!is_lung_ruptured() && prob(5)) rupture_lung() - + return breath handle_breath(datum/gas_mixture/breath) @@ -1022,6 +1024,12 @@ if( prob(2) && health && !hal_crit ) spawn(0) emote("snore") + if(mind) + if(mind.vampire) + if(istype(loc, /obj/structure/closet/coffin)) + adjustBruteLoss(-1) + adjustFireLoss(-1) + adjustToxLoss(-1) //CONSCIOUS else stat = CONSCIOUS @@ -1240,6 +1248,14 @@ see_in_dark = species.darksight see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING + if(mind && mind.vampire) + if((VAMP_VISION in mind.vampire.powers) && !(VAMP_FULL in mind.vampire.powers)) + sight |= SEE_MOBS + if((VAMP_FULL in mind.vampire.powers)) + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING + if(XRAY in mutations) sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS see_in_dark = 8 diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm index 63cfb46235e..7fa6bfe5fb5 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm @@ -211,6 +211,15 @@ if(ishuman(M)) // Any location if(M.mind && cult.is_antagonist(M.mind) && prob(10)) cult.remove_antagonist(M.mind) + if(M.mind.vampire && (!(VAMP_FULL in M.mind.vampire.powers))) + if(!M) M = holder.my_atom + M.adjustFireLoss(6) + M.adjust_fire_stacks(1) + M.IgniteMob() + //M.take_organ_damage(0, 1*REM) + if(prob(20)) + for (var/mob/V in viewers(src)) + V.show_message(text("\red []'s skin sizzles and burns.", M), 1) /datum/reagent/water/holywater/touch_turf(var/turf/T) if(volume >= 5) diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 4f4981b4d8a..3afb1abc0df 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -38,6 +38,35 @@ if(10 to 50) icon_state = "half" if(51 to INFINITY) icon_state = "full" +/obj/item/weapon/reagent_containers/blood/attack(mob/living/carbon/human/M as mob, mob/living/carbon/human/user as mob) + if (user == M && (user.mind.vampire)) + if (reagents.get_reagent_amount("blood")) + user.visible_message("\red [user] raises \the [src] up to \his mouth and bites into it.", "\blue You raise \the [src] up to your mouth and bite into it, starting to drain its contents.") + + while (do_after(user, 25, 5, 1)) + var/blood_taken = 0 + var/need_to_break = 0 + if (reagents.get_reagent_amount("blood") > 10) + blood_taken = 10 + else + blood_taken = reagents.get_reagent_amount("blood") + need_to_break = 1 + + reagents.remove_reagent("blood", blood_taken) + user.mind.vampire.bloodtotal += blood_taken + user.check_vampire_upgrade(user.mind) + + if (blood_taken) + user << "\blue You have accumulated [user.mind.vampire.bloodtotal] [user.mind.vampire.bloodtotal > 1 ? "units" : "unit"] of blood and have [user.mind.vampire.bloodusable] left to use." + + if (need_to_break) + break + + user.visible_message("\red [user] licks \his fangs dry, lowering \the [src].", "\blue You lick your fangs clean of the tasteless blood.") + + else + ..() + /obj/item/weapon/reagent_containers/blood/APlus blood_type = "A+" @@ -59,4 +88,4 @@ /obj/item/weapon/reagent_containers/blood/empty name = "Empty BloodPack" desc = "Seems pretty useless... Maybe if there were a way to fill it?" - icon_state = "empty" \ No newline at end of file + icon_state = "empty" diff --git a/code/modules/spells/targeted/mind_transfer.dm b/code/modules/spells/targeted/mind_transfer.dm index 1f20e6afbf8..3714316ef9a 100644 --- a/code/modules/spells/targeted/mind_transfer.dm +++ b/code/modules/spells/targeted/mind_transfer.dm @@ -13,7 +13,7 @@ compatible_mobs = list(/mob/living/carbon/human) //which types of mobs are affected by the spell. NOTE: change at your own risk // TODO: Update to new antagonist system. - var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell + var/list/protected_roles = list("Wizard","Changeling","Cultist", "Vampire") //which roles are immune to the spell var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell amt_paralysis = 20 //how much the victim is paralysed for after the spell diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index e023beef802..f55a2bc2171 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -161,6 +161,8 @@ C.status |= ORGAN_DEAD H.update_body(1) mob.adjustToxLoss(15*multiplier) + vampire + stage = 3 deactivate(var/mob/living/carbon/mob,var/multiplier) if(istype(mob, /mob/living/carbon/human)) diff --git a/code/setup.dm b/code/setup.dm index f501e736690..1192847013b 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -574,6 +574,7 @@ #define BE_PLANT 4096 #define BE_LOYALIST 8192 #define BE_PAI 16384 +#define BE_VAMPIRE 32768 var/list/be_special_flags = list( "Traitor" = BE_TRAITOR, @@ -590,7 +591,8 @@ var/list/be_special_flags = list( "Raider" = BE_RAIDER, "Diona" = BE_PLANT, "Loyalist" = BE_LOYALIST, - "pAI" = BE_PAI + "pAI" = BE_PAI, + "vampire" = BE_VAMPIRE ) // Age limits on a character. @@ -677,6 +679,21 @@ var/list/be_special_flags = list( #define COLOR_WHITE "#FFFFFF" #define COLOR_BLACK "#000000" +// Vampire power defines +#define VAMP_REJUV 1 +#define VAMP_GLARE 2 +#define VAMP_HYPNO 3 +#define VAMP_SHAPE 4 +#define VAMP_VISION 5 +#define VAMP_DISEASE 6 +#define VAMP_CLOAK 7 +#define VAMP_BATS 8 +#define VAMP_SCREAM 9 +#define VAMP_JAUNT 10 +#define VAMP_SLAVE 11 +#define VAMP_BLINK 12 +#define VAMP_FULL 13 + /* * Germs and infections. */ @@ -832,6 +849,7 @@ var/list/be_special_flags = list( #define MODE_RAIDER "raider" #define MODE_WIZARD "wizard" #define MODE_CHANGELING "changeling" +#define MODE_VAMPIRE "vampire" #define MODE_CULTIST "cultist" #define MODE_HIGHLANDER "highlander" #define MODE_MONKEY "monkey" diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index c20a2cbc0ff714b270b34e9ae11e6b7354b6dfa8..ef8ee9d29b2fcc47f268992f0bce87eafe8895e3 100644 GIT binary patch delta 8728 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 D)WDZ{ diff --git a/sound/effects/creepyshriek.ogg b/sound/effects/creepyshriek.ogg new file mode 100644 index 0000000000000000000000000000000000000000..86933130d5df41dcf1ce527fc3e844c0902e5d00 GIT binary patch literal 45042 zcmagF1z1*5(F3=}@{GK{_Rs?nYYjMM6*-1f-Ehx;{>sjxfy=T_Unwd2-Yj0I6D@}j^{&Pgy{p-Z`J$8pt!91K?Ol@56F2SCZ z{O1-=*xybAO!e-`|32=Xyo0dGzY)P@zx{t5J&6AhQ9^KC8)xfBsxDSE_BN*4f6>#( z({OQc@Nn>P3Ep9YA^*FXSxQ}9`N=L2s()8|ZjgOnJCZ zdHCrihdgia(`yKMJ{@9k8e&2c`k(X6Z|U^z{L4BG3}ihNO#H$8@d4S#Rl$#l!J#Dx z!2C`mH0W^;nB#Kf^DS-5Y*Op2Kh-((Rk8I|Vg0=Ynnk3$(SR(Ql>GnCX{ncJ@qa%h zth-r&1SHF@mlRzu>0~tMx?I>$|4O(UKyxag!Peoz^VF56%T)wApSnHiNl+R%Qo{MK zNw}MK03fGcI`%dESt?^=QF7|v8MGfH{Q=D-bMJ?a ztPjH}u7mPeDS7{Tukce*ON&OKYowcL*qx*%(0w+eDX2v=y3n(F!zmkujf7AyJRy~_ zw(;3NeE(64BEz)7uYxPk6XCO|c8%x;Q19G4?biVM-L?N+eI%fHGnppoOn*(|7lmR< zNSjX^PvsVk9iPS7&74aW86~Sw6r`p>%9!W&`Y-1+00iUy)#CqZ{;KjnEzXU5%hJnK z-Ots>cGr}&4+`y6wBt%+aY9d>Ml@_ETh5m1X|I2b-5_ZK>^u*FBR?#Vs zvJL#KH7W4q`h#{XtH)^7`v-xh?u z-3*Ij3Qx2NPbqHvXy045)AWBm|J!n&y3j!{cp$;P2Y?iShtMPk&YM|dU`^)AY)$qs5~=!A_+G$eLlX~kF=ao`JUVa z62-Uax%g(`rO-nF75ZUj569exNe}{Hilu?U9Fm|h$h;Aw(aX6`p`jpHkfu2(h(;OQ z%ZZX6gv*>qp*hIhMG@RDxtq}bSgEG$l8DlRT6u5&0ZD}DZPtN3GaZp9R?%Cvzti-%#+_DO%Y7li;D-*xhl7!4#`DvVDhJ`#(#u{5 z!RVRbkP}5C^jNhcIdrY_kX777AS%x)1sZ8_X=?GOohnDx_L3bbbuB-G_ZCb1271Jf zOZ-vKry@TV|7>FEYk>%H&UZRdeCD7qnB#*0=~bneerDaL=tFjMoi8tiew?`Hlw+ZH zMMJs)yVDJVUWsg4Rs^^J44}|%5^CbIbkMlrYW$?hea4AG>#CyAL6M-QU`v}Y&eBQq zEK0sREgoONnmJ)q12sEOO~EcZVN%1cGJo83k0zH$!G=9yRNuC!b6h_H&kUDqGuM1j z9zCz-4gjIr%*w@LK-zNi*Lm6uDTsK8lA_}r0mk^*`n z7yr3Db0?vu1AAx6!%i9qRnHyqzckj96ChL{g5neuO5ew6^ryw&p$dvpkY}!oQ&56N zrJzt5qM>ikIhm$m&kKzTLKUZA&)%v3T&dO_S0D55s7h#CTB#H`^wM2G~ zoEu~cHl=sOi#mv&M?u6j?RfJiZSMfj9YiNnTopL1yNT zNkKIFJR(IF_6}`3W@d;Bb|~)nYqluL;Tz%RF_tM7 zXDE%^GcFdqU?l~{qCiNZrS6a_ zd1O>jfk-aH$4G+C!ejoI2{;WT#t6<(LesaLn`zQ$%pJ*4jFV4t7kWU8>|Oj30Rf=D zoe)59lj5#PbB+36fyw{sq5uCdQ3SF+?dh)-&|08Dq zU(x&jsrTHj6jHhW*#L=F3{-H7O0NA>fSC-F?T$xWY$(ucPliT}LKz&&yp6kVx;mjS?fb5gRtOPP3eLHCAcI?cxlco{1ko+MJF=_ga zcTyh{EIT>_xLn1{(D%93-$s`I&NVF*Y)k!>_FZD20nJ6$owm?EQGm4SPDf~ip=tPc zEjZ@Cui*-9{!=YTp*H{Bm!Kx~SGCZxp=->PkdiU|?a@O$^nU@|Uu6u&heEjo2=l*d z3HT6=zu{ei#+^n&qPYY7Rn@;eblN*{{k@s?-?MkIAf%#*cV7767F|y71ACs8Z-{Ev z-3kDX1;EQ`+a2b~Zkmp?;6%mX7#CdAM|c`<1)o-0$dPuCOeApT5o&7KZKat;sH>)% zDR8!zBxoxz#l9YODXI17hjK_7G{AvN%N-~IBP8jD2n8cCgRF|SVa^vwNNf097+4rx z!LFk=hyXXZ8!I+U7Ym=DIPjyX5YT;L+>Hvyij1szhq=YohHNnJP7_RnL>txtBaDFu z5jc9S-cxP(iY_FRhy5?*g#ju6;_lHrc#t9(g&mC(gByz%haXRn0I4qk%P=?&fYTv| zg@sv0<+T4mq
            ocnzZiT*G6u0cclm#QHB?f*-O+f@I7?^5DBGTSxSG$agT^gJBX z9W9;p?QLJWn%WwBItS)Arq=21jkFVlZuXG#VInereZ1L<|NKSsOT#_iow@Q1@n72s zm3fPuD<+Ah2H$g+sFm!g`bQOFx0mPHU(pMU z=BFFJygdH1?RK%209b1#31TmwCmHXs9U8V4o%eog%%amH%l^znA7QWWRLXu6+duG2 z;PSy~)2;q@?&OiKnpzRJ`QDmhe<^PZ*LH7B<<+DogyA(tN{64;^aHdv#!a@og!3{e zV{dA7oaRNM+)YYvzob3jl(Rf5QL_AU&CDGU)^untXQb{{LshFH_Th`10k93>jKu$brgd@jcK zTcWq0o^v32ca8%qv#imy$t{SL15f}mETECGS!>wMk!AP@^Req-ov)kLzF~;VeDzO@ z4;OgxeE3)o6E29au?WKoRQB&HEG?K9WfQ&T=UexqxL~x!7%_LoBT$(XE951Z!Y_?g z+_x$bncK2_Eon!-kQux) zn%jsR?rkIy`zZOv)B?fqdd2MR&kPk9SFPo`uBz#@Tq=33KhdAy zngV}0O%+Q{jo?8R4et8#^hiJEAzE4zxz{oe%k@8y;0^e=WS6_e_;|}VdvgW}R#}cn zAAeLsXQu@~(`CPM?To{7)2moob*9-hBC3Q}QJtwtXYqtx&P}XcFpWT$+JOaOTQY55 zsN03;-jym0F0+C>?5ex+dc=vc!iAnj5Zug8ircicuM(1sEE533O^W{O02C6rYg25u zIBLwMpMBNf;}*&&7S8Lhw6X88Vn<{9f&J;>DTBb-gSo34Q%ey?!Y?Wmr*+nkPQrlI z_NuC%IDHsHF7m@9&F-<$h5(y5h8=2@$uaa|k=BR8Bf4VD18F0_zG`sdPN1b3D@3s86gXi z6pEMPu_UxlzED7_N?5m~RjL)g$Le{E`081?QW2Swc{YTm~+9khNQFU(cX-p*=n+H|zMDrVD`z^-s(#+O& z_U#D{;-5`z`Po+n94H5Z!zj!fq1wi`m4iBRK)@PN9v%;Q^W~!8D|<`OhLVa}F&2Z0 z38;|}lN~WZh84s`Ym%Bf?WRfi_cH3wiKZ<}vI=Tjz@Yr$MngQ(83h3VljW9F45?!u z8XFB^f4D3F9_jTPG4T~Q?MTvAIrH!5@%1nF*AS96y2Abpj*NdJZ#g*omPb>r%(=_xc!+0Pn#_gGywX z&e0q)fZvM6-Lr=m1#-7)G0DMVS}^bD*&_>>q5)&XjHd%Qw*d+*>ay7=^JO^c0Oz4h3$Y$1KUnv1)OUiXELEOl!Q9{^q{ zUXUL*JQqC4{=SfZ%Tz4Th>5ou_R4dlq^6#ne<~?mkSDf#M#v|FyaqoD(OmGIV(bTN zWyDi=agp#r&xfOJ)2re}MGCKPw0FK-KlY&l%kL;8?Lb?b%14g2q5xbVA%y~$NxGGF z04QJ!{1(5>F7*WIXn+8;cv6zw+$v-cFjmsR{#5J)eJwuZL)^$thaG(>`4T8$`U^$} z)IQ+dmi@X{d#t3%<2B$vj4IkEau9tib#Bb9ZlPo=#gXO@b11nps zVu6Zl!c2l5sp%Io;=9AKhqY9)40Gw+?UG2oxuYF|66fOxgSz$D!Ko27TQwWGhGqw@|kikz` z_x0AUTGk-`3yqZYH$iO{Y0#(M49gl&AP;{52Y~CcM#OpMm%rC(ZTdB8htu_|nyZV| zYkB(!G5acKb5z>O6p-|p?p{M-wVt=G5#Q>fvJ22K+2m$UKJ ze{%ceaUTFU-}(u$ee}~-TNM&({7*t&qQCvNFc06BgccNa7&~&GjaP^*B4f(FX5^%Y z9};~hvko7zw?@#y-S!HZaEKSKhEmty*nsOem5qw*C^g@EFg=I9l8m2<7CyFNmV?uz zFLp8`(?wvw!PeL|;j>K_!`0CPV@;-PZFzX$LclHO6KLGvJPilRyof!AbqIxkG4Q5U zt9av@VGTjDWMm-~db2QnaQid{;ix2h3w3x?+@c*eMk+y*ruEHRkB%J-T@002wu{_1 zeEO4^DrevD(tFT(zjvX+Fj|T~Ui5YM#+Q2aJ|3I%(8XDrN$p7YqA?^|!FHl8@YQ5j zK!ALAfNk6E;96af_E7Fe^Vpg*+9N>VIs0j=jugv&~%i^XpdT5mdP+rUL@s z0i01|t@6fuP0koc9hN0yxzU=4yxjA9{-{i&!jmklS^CJYOtwGV`Hu@LYS)(5)^*Vx*B1aq`4nP&Vu@ zpkHRHcjjkJ;=nqA_lDoA8b&pRE3jc}8Jzx+sVBaRi(MQZwRNC|?|pmhPF#~4I=E;y zU15St`3Pn4aajCY=_6}qoUg9_j`x9Dw}C_(*)SnH-f{rFDriI9`SO!j%F4nY=KjF* zPS#_A_qyNdZz<;M7r@DMnWnA5VmBq)ZMl)4;q;=R}EA4n$q#;lv|6 z(+YH+1UL-$(h0x%>n3HXqgbuV^ocQiYE&wK3|~{4)>yxgKq0>-;hQ$f(@;<>t*8|Mdv5o7Ej?w{>cl| z!?!;)Lj%Qv7qst7ofy`Wmn2J?&JSm?bRo8h46BFB3bi>61qApXxQJB;#5(%)xLDSH z5S2HJR&I&0W9Ed{i24puJS8@1K2l~rnK?AqM=gZ(SRZlLp7EHA8f|8l4#$FP{9~l7 zW{<>u{OREywBC1mhI`)3czjL$Ax*4;#SF%D$hVx;dGqOxf^;eEW%e!EWTi~=Q6Eh~ z792GcffCrm{d`0ddcb6xdr-LNEf$Q1z#}0cAl(WP%1#){$pD~AUT6rs6&}UdO0so~ zm_`lseZ`s7r|+Z-o8=jJYfOkH_cZJtGCr?gOgXk8nIXz6SI!;Ws27U^FREG`=t2p2 z2P(+NwFd_pDzW&p`@80%#F#_TJ3FMlOVfI1R?07niy2VMPHUO)KEcvv4dCj`K+oMq z=F$JjbZH^UYF8^zv$=`*I$k;HMnNDs7O{3$f2ZR<3tz(|0F{6VJc1inUR?|=dbDgg zbAyAPF=*HYp7ispH|{0D=9o}u^b?QK2Ln)bFEo6;bysYJ*D`2M@KlMRMNPljmx5_0 zPlKko8#4KPIAS48Lhc?in|z9SCRd}u4CROX9Jz)+t+`ezAFTP#eFeUmcJ(qUQP}>sM})dbbYowpe~iKea!<|!tQPQeo`(K zXv4eP4h+Ncy&;Bh!?WKDX569xF|UP&`P-Ig`L8*|wv|G?Z_tmv)+v9E=j1n4Bd_c8^NWXzAzf7z*xz z`Y%_r7#uSxU#n&aniGQ^9PEsZZu;cLY4C&1$KuSag@kXkT_`Xu-L^|(*yFqd(ny5z zT2ga*&5p&P6t9g^W-aUqKbrHCZ`|)0%UF@WM=0e#5Ja8{8S!BL77IzkW_qWI40$fo zi1gOr7@y+HE&)BTJ|rhUXl;X7EH{d3N1TBYU#h}|EtK2Cx*T;~GlFOF zAM)exQHX9kVKeOkfb9%u2qjd70807(P4aES?}?3^%X1B`a=(_5#HQ_!kERSsEV-UW z7=}MFidyuw5`~H@9KMc+j?mVpbJ_8)8AD3Zp}jf->V27{AZWi5lw=M;x18;r5`f7r zN&pX5C9_Ggsvi!u&NK6Uh=7?LqmpV=8A<${u9r_$WKj_>_k^d+EfQ-aqIU4|RSunL znnj2kGG6Rkt(z;cBN`8htwhX}$I~TJ93~{d*AK!C;KZ1qAnC?UdE z851M>JE-0KhifNp2-HPe7+GF%9TyN|Thxl9kB(oun|u~@7nv|mB3PD$mgESW!3+FC z&kSfA_YJloH-`u1v?X^5arBDT_aqp5F|&fydQTh@+h-*jtP)OMPm);jbmdi(Hd4zX z9*hIQQnXKV=M#UJ`RC^081`jbReT} z!TN^!)-q@;t~UPwXGb62z2y}&K|34O6sg1z4?`baLP?kf9N;znTNFO9&4f^=lZ1Hg z(wT4dUbsQwih|^HC7X5f@P{Xs$egivDQWZTPkc@QR5YEXEKG^aZpL&qUrK}JJ{1EV zn6Y0*4YH$OEEG1Q1wonv&xwgFjM55Zw2i{kxYX;fK!YDKiIx;Ox{je6IP%0Pd5Mem zb0EJRTx4B%RQDtf9k4oHISze9<%!9$M^|vvMQJbB|HG~-0)QMjXseOF>}p+tIHS3( zfGUgtG;h9?S)q^v|EW)WxVr|xU3~)bmB4PAhl_H0X?AICdTD)RVq|8M{V^~1{OA}b z2PY>RFE8)RV!^^%V8B(+<9lddA;osv3NruIlz`d9OHS3v&c`G=!uU0>B^ntUqh&b7hV8#_se;r^?o9rmOfwInQ{YpCnC zG>Eii0L!u+=cVy@5bB1Vm7JxF9BxBnFz=hmqz6Oeoty77TYts7@f%_F$GaEBbQUuH z;obPUmVN^m8?Ex;>9IpzQPRR-6Ag+l7OGAN>WB_sU(Q}#1ztk?;CB(y`ZN_b_=Ahy zHvf7`)nZAa7YMZ>X6P&^wcoztA_*Z0Vzi4R`Gtem^tk{btjl~C)9NL%+bv*O23<%% z5TncEP2{oW6T6HE{wmGLp2sCdSSLqXH}$04-8bBjX|A)`;b4R1&LPxCqC-0X96TVX zDNq@xUekp7g>5zruD@hw;kN9)cFkL>)TYu^iG}2=J%NO!Q4)=$R>rVIX1T0YtNCz98tbVaEoIorJwf-J}7ILH=>RbD=`H%5&!#iXj8M59eAC*^8D{VzM zEb+WUrIADt!nMDZh?3%S=2NDsIvW3eWu?FD@+0r4dH!Z7N7kcabO`b?g#(&?ZSFJ| zvJAkPzUvZmzg`Kd?jzS1Q73C_?hCI6-?Xf8F2)6D>|W6YzHRu}6_1YdeSxLnjr|11 zpNKm8guEXb!-1ln_{usdatsTE2Jc+k(aK;^XvSOCJsr;r?3=Iv9bMhl^#P0O=3e5R za>mpT1vDg`VF0~24Zr}^;)D-a&mdn9C{V)C!D7-vLSTUJ=BUkMW=ln7+%eeGL42+2 z1AAa*^!S}3*aykjke?Ojl@NLxC!Sh1FB1B${^tC8_E7kJ?JuI7h37-uhp;Mni^j%j zjXwV}_n`?0weh*2h$)m*W{>#&%wew|`o_2XR6Dr`S^>~h#jrB>^nMxm8svQfZBj>N zi?5c7BzV7%?pWgb^>^hOqaYkrYMLMj%9{^R)T!M!{p=Zx#mm{pu)|#YyXXYr$DWU` z1O_VhAT0)$2xtxW3W+>>Gx08G6X!YA7%ND-21q&WU%;VL1`wy-s(qI z$nG|okWz3Ig_<_8b)XS50n6vA1|(}#fQupEss~4bCj>-3FABeJ^Z13Fpm&a^|0H|r z04ZvQeM?(aa2D~;k5g@Z>Klm6&=TxhJ>T2x7*``-^6XH#$F+_Kfw6SrG=2Hw%s#jR^8v14&^s! z?>=ww6j@j6c-DrUY5Yv?Yi_hw|4^K8u1l!K{>f=UjMe3IF+j8TSFss%uDwj&-qW`ht8s|oo0 zVPSVjRvTr1)#c|6qB6Fuq3-4_)?f%@9B+TR1!2JYxvZ7-vl0dY<%mRFG21vnK^@M} zGIWu$)bgJU_dXFl0LQyk-7Dr10OZM);2V%O9*1kTaS2;SSr{?YH^CLlxeme83G?g*+?#@q@;}K`8YM zI_}1G7A+_bqz6=C3%R@Eo<1M?62uK~YzveH6Rlvh}d=gp^Dcc5MSl);4-*@gze4@-VY+yVmx; zc%Jv^Oyy^oJ9^LjFvAwY6(PsqZ-R?tJ+&^N{E7+FxBuajnV#JW*vk4NJ$B zZ=Weqv;7r`*Fil{8y_HLz%fkri+e`NHWt=TN^2~qVD~4S^`rGgxF>txLH%^T`g?-I=Fiw+8atFrTw&;5_%vsQxV@{tNpv6c3hHWxopxMnm8 zOzt438#ZBFB08F@aGPka5M=e}uF^}~o5Mv6v@{@}qpGEx%`wJHnfFGk|D0K5fM)|$ z`hhp$L9{3Z2HHexw527T(}cV90ggVmwG9rU`MryYh_v&ZEI%Q9VA!)Daemq-6Jw}= zzryz;%~YV{!Y(=4o`=%xh17$0%?!yX5=_hHc;LmrJiY523jM8Na&7DR*uqlc8x&N( zxemgY33vwMu?%;9bV6hY&fAjIw4@snKtRM@0D=aLc7Z zLIh_mE!TUZusX|9@w(KZL#X6%ad{z;A=Bwl9)eb@QjI zWxarPnBPTh=hxDtxc96*9UU}YC_ng>9KTgsOj1`d5NRp9J(?%!Nf9L!KG5y^4a`WyK$&tH-4<0N>fg1!B_+Ys*Vx^?^8= zYlMY3Hk_0X=(UiEkdk@K#9?$W!wX?Zz^3A&ZD9ATur6Jh`+8R0e(mv8mHl}}r2!?= zbw=*9g^c;x^u0IXvAz!0BT=N?B=5yOxYQtd?>}xn$Q#WtuycTRfGTKT-6~O&O!@t+ z4Vy|QFGaGrlS}uiz6Kt8RzXM zh2U4K1e@kpUk%DNbAJ*47Da2)G|XoeW-|zWH-AGOXW?o|uUw(`CR@Yi$`1!7(L{Ou zwmiM7oh1rgsodU<=1FQIr|TRzvw#66nOjek;s!-%{TBB@ehUudP4I>Z01^5kNuyp~ zA6wYt(kGvI(OcdKAD>ga+~l>?Kww4BuU*BADi>1sHV+woo`1T3O8Ot?#1x3XExH_aa@*COM z^~vY}S%#&7K7D3B<$SPKy|#EKGS)%&xbL^R%``p_?DEae`(IY`Yg*3fT392ub3jYH zEj$CE%&AcQ)u&uGE-7#nu(89RX$UZzRY*^Cx?6tW^RGYmLKAcWItgTem~SB zc0HsL{n@GiBXDAl)yN@99*VF4_=PpQcJZ4tA2Vy3a zfF7&nr1;n4DGPP{xAuUlVIkpwI^CWC=i&WJUWt{5j*qwk zYHiz$fL6n6LF6)_SKPC8`Y0uKjxV5YZ|26AEBVLp;PcX{4M~3o)$PWrUs$2!!4rMT zsYswjTvEUK5%y+e9_t-5Ptx^n_@k9KIQ%#F0f)l7h8Z_H-Zm~S(S2~B=%+{KZceH` z`@_TpbGM&!?wR*)Vwsp^bse;Qng~RNw^_)8Qhg0j8yp z&u3b{YIQhbT9JYFu20Yw1x})KBZ5pSU01elV8E-Z+8MEJx*n-}6(DV6Bbfs<Mo4k<^lu{>6m)`SIRSvPtci zRS!ie^(r*Q`>u1IC}gcCBX#31O-tGzrZNvd+cx%%duXM9RC~Q>P$F-&LH|?d*(e-J zfx(|Is66m|a*<3+EANm;D+s{IHT49tK?94(PUdIx$EjH23~CahZUL?eoH@Z&5)6 zPB^eUm_VV(96Q zYJ%02t1dj$@}L&5&2{A5UJFrt#zV1L{MgL6As6xS4Ms;pS$d`&nJW!h2(^qHNaZkTNa! ztrSo;?tS;XlJa@rRBj@iZm`GkhM11n0>n3x4BuKCv`0IoCTeIy*W&ebc=la7lgbzLT3o z`uuDs;^XrC=-e}md(+8TRRww?F@OyFq@n~tf+=ff69y6lUwQ1=^j6yu8`)o{3JW`5 z^&nn~I@)#)B=U+H*-C}(9O=c8mq^+Sz<|IUo%5lp{?V#fj~+X(h>^=0hfus2#j!C-Vi77pEoa zK>`wHKK~$<;zFQ;s)Vt4F)E^mfAXX2=z#Z*Q2B0q0qx=`e!k*V!5dGu?B1B5qqM3e zTQzgnSePL*1ZP^!$w%GO&15>C$$I5?py`DxOggu`da)s)aMTWQMS_< zv69>Hj8v=EB3;0acG&AOS3iHhD3%8gRlsRlxk@g460~J0RhBDlpTH81-Xm{^SHC*K zVVp5@fW8AUnnVQf5-K%+)Vp%slN;*GWW}yNhO0&tx(AtCC$R&Baq_$b+nAG>x-jhJ z`}b%Fv)Fmyflb`Pdlx&KHqqv&GXWSn5zbGO2uY8sq*CN-s$>2` zWP?^K*=~_|Iw0)k{AT2|?qi7zbz{AdRK91y+e?2xxU*tPN@2{y8kmFrJ3849pZ5to zEyIVAZfekVSr2ol1v@}5!|kK|*^$yT4lUj>h0+^QdZLv%>VcQ4cQL*3$yAQaBk~T~ zdgJaB{f*E=ghqgc!$IfysY3nagnrd|jb{z{P2LgdM& zn&}m~kgVdQcvgiVXM}6D3d7Y9hoQlBtHt`gsV$AP92!QkM+QaYu?;&dy)?#tG?IXHVK%~n|>Q^>36XAj-WLfCmq5MDc)YXhT zq*L4<_yw;@IM$Iu6D1db)qRoqre)q@aO!M(=A>Vopwd^aroXSqZlqs;$Gny+$u2;1 zaWU?b&Armd%RQcRlia%CsjFuttxhI4+a7*#cPk_bPTr?YF=flZ9Qi#;muo5w(L~uF z*tIKcm0$LABvNqcnKK9VQKxn5UHlUXfOe{tC)F3rchcM%x>FN7Np55U8*U8 z6cJVuV@(X=+3>%4DK5it^D_Y!4f^fRuj7hAs&g%~F7Dm}5z+hDL$+@zd}Eggw46F4 zVtFz)guCC@GPMl0oSFC~;HQ{a>wv6kF6<0jfB!!(=ki{Bt5cpt;FwKg9Zk*-j&Kk( zF8&acX_A=p1n0N5K5m*Nd&sxUq7{=KGD$Wc_mgx6a{YVKQiF_MvwB~oP}pHqv&BYp zk8taaSC67FD;zey;UHv+JrYZ7E-%8n(|b^%b$j#2Y9>Mj(HH^R3w*Xi?c;{^?G2^S z4w)oe>^uB<`iMDNZYAWv=@NFbG68A~lwff{@6aJ4>w5Xgx)z+L4x)XC>6%-(82RJ4 zT84)+^Ik~gRpswf>lSSN2URBPzSWalP<FQH2v>AFU@#xKPi{ikr!1NtqLMa1Sgb0R6H z5R$AQPCMOu^YV3?dbrxV7?=C+!`#gjdQiiG2iff&0?1QX#;Osff>_FX&n+ZfeC6JVyMw*!?Kn=a>Lfu|m{^U39W3e55%hAi$Qufy_(q;uV2$TkXE%_V4lEv$7jO zhqBH$#ZL7&uKq6CU1I_n{b{@7eEe5NU@+S&?RQ#>f z4xCHaDbu!0mwvJp(=o7&pV<)Mf@U^D(zf}xmu;9P0)~lhA+=V9HT5Z+4--^u;25L7 zar~R(|H_P>7ua^$B-4(RN6UPiI6wo}Lf8{&qkD%aL4=b9eS&yR2SdDn@=Ht)Wr*U; z*J5s+4?Dx>bYgCD=HgSLR`-c~A7dnX-SJ3L@~-r2j{M{0aD=_=O-gU$cz1zY??<0A zMRcLJZ|u(we#93fwcd`Eem3{`1i;ExMIGIcvg{`?{7ojUP5s)+7YQz+e7a0^kzVUq zE=(3{wEjsUs16~X9s2-n$56R}eJ-%qiaBOzeERa9++BeYd_ipU6p6Wpdge#1H&4;e zkQ~XO6^rgB;KtO=@7(zvUNNVZz^vY06Sl5|X@7>oQzndCQx7*M0}4(bF{t*4N;AB%XsjAL<_j0IY})2*Y%R3nCSX?yNkkOj zFX-%>+f8kqW^k>O?^wtfxf_k+XcP%i2DPto+QsZHONpyQQu6vc_Q`&2 z!cI%H$lICK8lI4eLuovIdF)Ip2}$-&$37TM2?HJEeL6Rf z?vx)~wWU`tbPVhn&Nid<&3u&1cd`Cnv9%T8T&B&*xH9jV|LMK9mqum;=4h0F*Xx3MSPTtKxTdTm?L$Z4=Ab?Bvrtr$wbo|^k1Ws|H1+F2b+mH*|q z+P2^j*Xf~i4-9|K?|MuZQCir^ZC&Hv{hVs^YD}WAw^O)XwmLy)Dk!2VXFY#vY+7Ho zsx~m);rC;l&N&{rZ|>J-*}<8*^g>qFQY%Nk9hfrXTo}(S@t%8)zm3X)UMWC(wism} zewuy%LI9|e;J4H-L>vSJeAi|-%xKi$=2RE`$Tr@|f=OUJ0q68d5R*za4@ICM6mY?+ zX#Jdcd$b>N8<6Q|Bdq1eb$mP|N$fGx8yWuSeE#u#?iTXK)OAEku$Qwj{)xtr2Lm)W zwWN*#<>D!+!Q}KN5v@H-y0O7@?1x#ZrXw?zFJk3F&rDNjT#%`w7{8#I>0}QC2i{NR zs#42GA@zCk&`B?w-|B@&Ql$|8CsgB`3a!+A_Zjb5_~!R#(rIo zZx?S#OpGbv28a@@a(DYbJiWIs7*xOXrzrE%#EwWamPOMAqcWHovHHb9Ca7eIh&!4F zRRnR9#OcW}m#|Mn2)56LqN#nn9>)4-y8qe6*KEJh4-3%L)S*oop;Sd~NC~;-cc_^9W<`T+XOI8x-IHY9vgi3ItxSr<2e(8b3JCNn8?bD=Yra8t zPFLT-1h$8k4TkKeWHfvI{y)bpVX@K|L~;JB%#xlF&bdM)Owgt=_}1Xc#AH6Rj&BwC zvjS+KT(yzTskR_p-xuJ3@1QMnv|)ml!Ud9ZadFq}1XbxswMcn7QMNM_85&*mVavVT z^34Hj$VaG%3&UZZ0XNNju1EQ7PYVK+_V;H3h72bgi^k6#TU!a;^#{LsaDG!y94_AZ zJWzy1^((!O8KO@k)+6Tk{E*Rzmp7P6-Px-9+z(9>| z5?nPLs=E=Pk;EXJQ6VNL`5hQYJK|&{FVG!{2Q+eu%rgfYOeK?bb6&a9w=f(3XfvlG zkllXRFU)keQNVP8j)PL;c#HjEH-Pu&Sd!i)s*|2ow7AZ8>jj;an~uC*Vtc$3rf|ft zS%TW{wf5b%YV>AdlL~}oD{}1JN6MDzJnWSl^MxF9y9VKAI)(B=ANok{ zfy0$Lud=H!n_UAt3Yn3ykPVWW107Vd$;WT-iO3+nymqLQ3W?tug_4-Kq{C%L#|oBc zkWg7Apt1#%UtDql?Dv=>qPYGgKUnCM9!kcZ^y9PAXGYjCcuOu{8K-=ZdYKSwL-8Te{vBoek|MX41zb_qFSbuO5`+?YgV2&t* z2fP@Xu~B`qs($YP1N=EU*LtD4wwZHs`~ahdT?&9GW&L*b|0-n&-s$|mQpR2CJvZV` zMmRGvK0ZA=J~cSEF)_TjI66EwG6rqD5?%%@**#2HN+*j(d}|tR5i@Ug#$&cln>LIX zOUk@xHL%zZ`x}Cg6t2(C^*tWUy}hv=>-f}qGx7T?f9fVze3d6($Ot1bfhKtYy~;hZ zx?z^(4?j)RN`r00ajOY#woa{Gzh2qj(a&UinVQus*$bNTK48dg-xz8_A^GI= zz^{2Y0+oi4BjTv5Emw*<`c~*n!KHX+U9`{tSaH*v`lg8_KdqX|f0ktC@k!U$usfku z(Cr%OwaSPZ&ehc3He&O_uK0Jv3|QoG{d2HwGIzt}3KK>cwB}>+E^Tg2-y%!b@RTL+ z1oKg$OR5Cq8xPe^VI4fF&Z@~MKU;C}WlPyWho-kXQ?4zj^eoJ4t9$@?I&$@gqV=A6cmKJY^-3q72=nBMx~q9+u21bA=?Y>#bw@018W$b9Fp*DTkT zY?&@cZPEjM+Z&9qWfcpDCDoY-v!2@sei^u#?L%ZPFXdm1%KyOs=5wh{s69UPRb#jC z?V#I2OJ)CTF7=Qrv?dE`7-O3XplcAnQ( zwtOi1;2XP8`zP*p$&gp8kwh1#QTc(%f><&^Ci$2B$HruK4ut3hRId)f*G$XEwPnT! z+}!sHfcQn(2Vk%3i4G(z={9d|siE@M<+b=H$3Hlfu(KmX=O9#wuP3Y2x80Eh{;mqx z?nSWh?>G)CJdE}Tojjl8Ta4jsR5Zv?62?Xbhw*(7RnoRO`f(dZZt2iKCE#ofZSMpP zNKdns5d1$xy=7QcU$i~E&!HOul@4hEX%J~dP-zLNAKfk8=OEokcXxM}(%s!C-QDot z-22|={lXXabM{_)uQk`4V~#Nv&*tIB#paRz4{CVmN;tWaWE}j&?mW8IgxJw9*|tiq0u*~397-bnPu~#Rrb~+U z@zL-$y^F7#@8A*Dc>l`vppyVb?26wQAI*cOZ!&zTt#el)BN#icX_Sqo>>1@_sY_M1DQ_ol2rO=~zt&uX^fhdU7wgi(`IGUZcJHJ9P0*Gv3N~GuqEVXiBqIyIByNhayw& zFYYXi=nN|>nmDS565t4YLsQL4N%{|wAw_suy`_>C$azwMMmO+k?J}{`Y=^ZmhQVEN zHSE0hu+Gz9%sNQzWia*zk=)japnls!k;Ez3@Mev@EL>T^9-jV+Ko}aUf?;zs08KYt z8cCZW(IzAP>5+`sTEFCc2z%%++3xl?-v5(kE-o`lZ9ee&BcOs(?ZE^;zo}OW&LrR^4lH0 zspw)$l)Js=5imPwPJC-E8g18!cJaJPH9xUJfZ!6wT#DpZ$wlw%5d2EHSIye5EKQv+ zUU-sbEeY2*r^$lFoyY0MD#xBQ z!-6$q4HAHerH;=cC31fq%JWP^Tbr}f;!sr*uJgpvr(4mCSH}|r;=lj;S&@49D#I9E zjPpTZLKI!J{Jd?L-^?_KiAMBPT!MZK`M`E3jazLX83MezSP~i(zrKl6Y>RgD$5W7o zOBpCWxLqCjE{YZ+c*ZZie}uW%t@&shZHtYl*%^445RHG~!kcBw*o4H!kIKOjfMaAK z2p9$F0VEUT&`AAVH=o-y0dihUqiN28&S^TA#%k|R9=1*%txi@mx=~Gk|Fh#ZydJH# zBS5O2H_&*D-pca%k(Jq6p!`4NPaqaDG`x7r2;CnZ3fOy~pZMPDP8kn=2B0P}?TlHD zM`Iw~1<(EA1QV_(`v-|IMcJ!ttEdteC-gflk{&t5V#rU1|bAhlck5JnT7RGqydfTkT9fzoH?a)AdS!~rPz`R(Ba z6sq#=kmxlJG_c1y`2{7QZ+}%*Enc9LnP9;hv&EfNts~xP(Y5pZ2lb2PqE6BN?Jh)? zUlI?;bc9s<($AH$PS{3!$-x5!pj|o(X%Ei2QPmbQ+|$DbbOfC{4EnApMmSg)DPnl8F6lMeSDDG)3o3dCZZ>NDkxD*Sa$B()w{m!B*aDl9*Yqwdbe<>o?jK9ElC21y%9lq9_1tK;kJ7ofz$Ct>7Izm z&r~l9LmV=;%S}iw7FEa$LIyyLJm1B4GxJnwcyIc-92LT7O-TM~C1heFj$kqEFf$pTRs6<^{8s?+NArfDxb`dW2Dki*R^-yiie;Rr5 z;&r>{t!z9}DJQ6=H?r0~l=(fkbM&UNryCrR8EgB0XzA9V=*fNq_U;$T&ID&w3FMeE zQ3Ve}2T2uDDY+BnV?5@Cm`;%nIwV0Gg^($&iNk__9p_O>q;P2o-plZ(q~h5LhxwB8 zN}wrIOmmJ~xnTM_d6eO^|1AHOA2cUg6-n0_j+}aDLnFKz)mWGgf~D{^O(Y=wGKq7l z7Zfdn&jF0y-K;%nUws?kT{$z7)22MuAnRfes2~{qF{mHo*AQRGuwElS-dnkJQYelw z7@b|(OyLY;jWmz@v}Wb439*3!>FdJ9XRx3R#zNxN8U&3II4LNo3mL~0de%@Vox%=( z@e6rG$!|&bjWJ^Cs=b92BYwV%#qHIzftRK+BcM>Cfc12;9}uyxwi({Z#NOI;>;B-} zc!RA0BPBIvas5FQRNd)vOx#&Yn`oS(_1QNqvq7{*Be!!4CY!o{gOk+UB;QnB5M+0I z5)W_81#ria?r(Sygxm1C4l(ww#^N`@SPIA|MWX0EPBfereM{WqGut4sq8;MhI;cz5 z{gJe(|JO7PDQhRHk#BZERB-jP-^=519c8P;)DIu+A2favV;X>8j7-~|9=^WgwKCgY z*Q2A00B&Q1w>`8wz8dqaE75=YWnNr-USP9JM=QqJHbVkw4Xaqu2)O9>+2N3sMZp}+ z5Z*HP8{U=V53#AY*MfUogYnrF^%!&6i!~(QmCdPhDMw9qjXyR`K-7FBa+D!``o@&z ze-kYAjP=!wCsOt28Ng9wUKSQv5YLiZGlqG$JSuefrLR)YycXrj7YfqgPW~jU{$-JA zBO+NQp9MDVN^bX$B35UmPmXr$YDPSX`FSO&()^Jk0j0R|GC}r{d$~!->3qad??tl%V#$(bYo6p(Jp=MI%Fmmwk6>^Caa? zW%;pNbCW=iliWsEw6u|A|C;wB&(1Qf8qV(hc*rzCRi>~Fv2dydxR=5;x|0Zx5cEA zVP<>>dfUQ)@=M$;iCwdXOfA*|YQRQ`zoS%q5r&&jLiLs!TKf_ni)j*>X3u;Qr8sPU z1Oe;l_t$OiojTWs-K1;Lj3}G@{go`HP#(N$H89o(g+(G^dI!2p~Id zL(u`DtHr_lr{!^x>^OcEv+myWh(Klmc|hM#E<3z@v7H$Z^YXkUJdP#qyZ(c`j$@wI zwDE6aaBItGWOzh)f%!`+v!Rg{DdF`~U~~rfY=Vn(jSnc9AKOlmi13~Aixme82SDHM0`XrKgp&=nB@c7i#`Uwle>YFRHs^bA%>;u=FLtPApq`^ z_dY0Ko`HDW=HB;Tn&;J|f1(mK>KygCm}ducFXS zd310-Yd`pVgVoo@-ooyp;I>rxl}4cZrcOM+kX$bl`tx7rj<6km6th09ipRuTRpBm5 zaHNz+Rz@6EYCpqoxfZDuPeYHH4E8iLo$bZ$I zqDcOKFh}5X2Km1*$8*CzS}atKV4}Bgu&aA!Y^r~FWO$%wYGk;30F07|=dfj4^X!%6 za=*fENgu&t(Mv7##+N$dMskc)NE~32-%biB;trN-rli!6dbW{sC0w>1R$RP6y9*Vn zsUNIYc~hsgBE?Td1wz5_#(g7>Z&en20(L#eH>8f(<+Q??NbBCTSG20fOqANashUFs z8wA0&0KS!W*+bTPt68YUV?wm9pN0Ylw^?ALUKRCwQL67V8x}4+jBnn5Wl{KT6@yIF zLsCZ2o=jYF#eliMlHVc+cAfs=fLIRc>Sln)3T2PEkKp|*;^de;NDOdV;sTX`-3-d@ zePrC-y+Y&iD?o_;3Imz$GA06;G9vASLtjq+9qO8@Uk=d5&J*@!fO9&lpvl5OVjKni<;(J4HDsPPQBU<%(A6Hr`N~6T6bK-) zu8a{q3#vHc=e|MftSNH}Z$gBw_zJ}(Tu=bNZ;H;SxJV9MERfqoV-Z0Aox47GSk)EoZ?Zn+*oTW)tYQ+8_#79(qx=j+v^Ro@v>Vb!`sEIbKZucl}OVKQIHYlESWb#g&*$ zP|r)-jI`xG;_4kg9B5QhlK{B-&C}n-pXWUMr04etV}U@2rNlrb;Sh#9iLfK&tL3qH z`bBIXYEASgN$`Ql)!#aH;?H$tzENiS)*oQgykS~*3180CJUae`GV3ki^Y&ICK z1bdaNU8{>m`PV9-4m5k_}!rnxX_d9pS+UZ>BLw5pp$2dn5&Rto&zG zq$~tfByv!b+T@qIx?fbGYhYV1Y`uWeHXBKO=i5>HPLJnY_js8|S%twbau80pVt@tn0a`+Nlx4;Tgj`D`J& zff0w{IP&^f7s^}IHRX}32XMctEPM)t(H?-yR&t1D+^O{_vPwR7oF7tY3lDV#cG zDJ2YlND_oP5yzy?tk?mo*Y%*ki-ZZlHUDEYs}xKck4w9?S@*$MakodfTTe?MBqD=?U!-<)$`l$rgA>Z%;oypY75xbc*Wm3*Yr92>>511pNsIt9a7TiLR|HUgYO4eY!1KTV9M(^a5^9a7mFw$Ila_gBod4ae#t2DZz!zpdLuml#6t@fHQ+p5(lzA3yiJ!L# zIQ}iYY)VnHt?Ia`eh)gqMv)LVV8TKY z+|_ni{4<2f!+RZmb=KG+mY3+OWB^L#dmAzl1~~IK%5CI4ohrejFK!!a3FkQ0H#kCC zPdu=Bm$!Y(i0U25w}4Uw`$Fn`7_eE29^mb^WnX{Va4994u^w9$Qq5Oboc)js-$* z)}=Yjw+z=vjV>y7D5KWB4T0q+w8b`X)wkbaRI@$`BCk3=k$tjYd9HLZp`MaU;&-s6 z17A*0qC!q?e#t*u8+ynzAu%n85$_1`n~BIp7)G^U5pDk}s45#LjAHRPoLQ=Nd+53o zC(;=H%f`Nz9Kaj+IMKMGH%QyF>5W$QJ-I4A1j}7dut6)h0Hj`m*zMOLLS%NAF%o68 z`S?no5}yqj@wC3%QVTX5l*gow`T=zjIOp_f75#RPqrstgJhJ5#wk$M*n~C$NXU6Ci zKd;duIsmukM4NJA0*=6-Ji5HJy`pI!G^4JB0LR2^CzI*fgDx8{A+Ez(j7es~SCW+q z*aJI_N30n>u$2NBWV1G25j1e-XP{5y6&i3QG$r)-pO)~s$DQ%|W~7W><&J#dO<$5p~@ne);95NT+_moF%pL)AeIekbhwdwYiP2Fy}EcWK!VqrAUn4)W5WCN{~Jr!zW?I1i`IpRIYG(SKE!jjUrspcPhP)}M+0U3_wR zT$pIg+6`tlOScM`b2nxsS4sZQoZ*9c@YF$4#Uby=Ng7sZ()zP-%%3=O) zma6B#K@ln^K-v1=4JM_w6ciY>MWf%MpdO9wTdsN zmuD9F$UtN8!;c*rcY^g2yp~u+c;SEfy^w6?p=YbLH>dX4as@l@S zRO#l|8?M@S{H9DH-+a&84!j>Nv$$%}zGXTQ4D)v}1dqS9C*}q#Ai(Bpp!pDJ ze<*@AgCnFAe$HYYdE1D)y*nWvzhr_UqK9f2_6e>dS}}^rZEh^CL?Z|x z%de8`Fi?JC#c2G_d4hbYzO|**gTh1Be|8b)W~3H*$lcZSnzn(xICxoN{PV5V?N<9h zFt|*CkRxl@@ZfjaUkx^vzD!fgWLN`YuvJF&MFt_yOP${6A|X%My%zj)6jznTT_FXM z$X;vyHon_iMib2UJIuxd3$3KbKL#*1;nwY{4(zwoV~oDjRfsWCOv829HhGu#+Ul1C zV}5ZZAFfQ0+3~Z?h+_qLM;~0{4Ho-btU2C zew6C2spIKTN9g(}dT?5!z{-|Vm#(mh5f9s4R^7HFIOw%Ztfh4IZ6?)Qbnenf?KniN zA5WjO9EA_6D3DQJLx5GMU^u2(_u+j)**kL2G*$w@m#w@v_Y&T2C_NQ=dY|8e-@Vk>1WE{my33s+hn!; zN0`7HfQV!-S=bYMAjga&QYc#odev2cW=c7#Dr6jqj`TI)?+L|y1xiJ6Bazw(tkr;HKoedI0BIQ-ddVba9XtTNtlHp1RA|-yk{k*gI zsf0L1q-q8x`Kq3pagZZwcub;V4*r+9E>yTP2my!~SA4EFR>5Ekz&Y=y(ryRDFfAws zMXhz?yip>Ib>Vy{F1DLsUPOjWcp;y7YGw83tv>9I*@+F>sU1&efwHt+87Z<44~jv z&7IhN(?4=_55o~eU^lBK>Ry8Eg7gWIKT!-2cQQ&W^Y1hlvbfz(mT7=XA$%GT;CXhN zAv|dlFw&1+SwfqebMx#gsAf>si4hsn#b*X(Q;=B*z6b*w#vf5#F8%pI;;q2y#=Af7 zVAoGO!h`fzZnpO^wKTo6#$?|Z8DH7w?b7QN%7X}6!^Q)Tm#vK2V{?+M3Z5}245 z-fb@+ldsjBX}an#Ldw;2#~_Q-exR_JpX_YTc>H7Nv2=k+&LYmt`apLBDPn z+*c)vsUIKvFoZ|;sOs5%^wJsG-jqH{6`QdW?Ebm;kEz}bGjBRyrCgx5cQ!);`PB0= zOSd|pu3kYGt57GA((SUknao>ahNPTxQZHUdL^i#JNsh1`({jG9(^B;JzfFG>3C7hb z;Mf-&KXCdNR7QZ!fy@rSb=MUT6Tltw#YbTK{{J0N(Z2M2(fFVnn z=;-O`>*xpnc6a^xJ=8G*GI>xR(}WvpYa_)Tdo}!3|z+3$?YjJ&?@N?Oj2%`pQ2&z5c5j6!=ZP$6|?&yP>a4-#dLZ44Potl#Zse%@)3Tz5Bm{>QAtp|F7UDy{pG{<0K4 zAOU~?YW|J3CtcmwRaRel!~Rmq#j8?41u4Ik7B4%B#_OMmBr!52K}0sfYG*YHep>6< zN-{;uDX)xn4@#A(g*Cm9>+Ji8&V`Y*iOPz4kr9IudkgmgFow3+Wn|I>)VI=hI#DJ0J>w3W168vur;_}r?ry_PD3y~xYb^1WFJ2| zjQlu7GaiP8QE~_rL6uhUkg_q}bVT&NLHMMWdO+b}dv^4C6JZ4TuGT%SCf71fn@Y7y zQcV`dVV?Wbo`_CUqvKO*YkKZX;LkBWsL3S1(t&4mBtq%eu{ecydTmkUPx`+Y4VnJ) zxU*m<;*mgeb?$ehJB$A>`wHpzK8`jWa2TiKmKPukSnpcbV zj0_Zamn~#x-(s+Q9$1!jBs1pfmfG`)5_VE+CclRZqMZjY<1(&5Mzzqj>f#f8wFl#5 zFH1_7-DQ%^T%#9@g#4M00e7vmJ?@fZ*FIoW;ujPTI2Qq~$LQt5B!$H%O(Z4VK;`T+ zO8VWvzEMu|z0$s|ZlN+Bu@?f^hjj*5N1L!I*Ep+F@rxp&WE_ozMznaP6{QbiztZ{G z=t1thCbb99Y-sG65Jxd+-1J~2JCaIzx6baM@9~}!lNdjV{_UH`GvWiw8buLpK#6C4 z`cd7oDm6T@*5JbGYteIpaJ?lejC*or{6VtHDxF*v;u`UVOOktjt3!5bedp6-&bJBD zoA~nhVE$^EtE_MX+;hy*cjrb}sZ>L@cUKzBU#OFrzwl=Hp$DXL5a^YvSQS15wJoTD zgk9kJTTj)4{1^{q1SC~*iQx3oe&jT&DdbNUkIJA;xW#`9Jh@z7}ysa z?b~P@53;dpQV2g;v& z3gX94*SGo6E6w_^T}u-Z(~V1Oi*QuEewrpOeU(Jjrw1z=74+2t?b&;~Dd~!b-ID+h zy`mwy^&3xc#rq@o(1w6Z7PeTQ&R_DhG%2X`*4CT7+Nxg+flt38PUbg26`U}r!JFb5 z9>7C|w8Y@Ct$_xp_)Xp3L)u|Hh6|TQAr>)s1 z*@flfcvGh!hx0=4a&W!bhCh#uuUKx~_Msai3TjyNdA+`8r($Gt!qCC0MF6yX>EPbx z0x$lX$*?8xn6_2`d2Tw;Rw3gMi?A$v5L0TUUoyCUx{eIYc{t3|S}S5le$;PBk$`l+ z+ar9#9L$KSTZspB?H--vX$&9Iov${@F(wJ^l^NQ#ZanDN*=)YDE~*wJ_W2Q-6-cQA zx2qB|_@o`a*}umTNBl3q=V)}~B3#nI)k3vC?=dtQIoj#3@%|;DW$iR;PL-@+y#=%D zxbdB;_RPVT~ z7Cq368?0Kxro3ZyBNmC;shk0@$RxOid4#-dZr;OlRO0kmL_ja!4}fE(ACTDjbdmt5 zQI9}x%ib^g>O>NE_thUwP1dz6aVD3N7Aj}K9DR}32LszV9|Ro4AQ2_BL<#%!o?pi} z7{6xOg=O_+cYMxBe4$Y!aTi4GL47hg{*`T}vbc8oZH3tG3*^sI8|Rr{znXuKVYeFk z`jQQ9H~dqRxzryS01=FTI;(aSo=RQKoj2N7 zS#~@uddQwAO9mHDCojJcQXDq>O%q-Z_m%W2X?lM#tW(j$)8U7&>2)D7#l)F< zi=r9)l^~!mWHAX}=A)r|#2|~Mp-WP)>DuSv>;pe$S)F5wx`8^T{YS;q4a}P)wS>Uq zi*|f~Ip*Z$F=!3Z@D{j-H=P&eQ`kqZM=j`693#>=YK4r4qxcs$*miEMK1x9$0X6=!&b7F&{Ufyca*Dw$A8bd)T2$Y^ zqE*{(x9c@7_WUJ1%KiY`ij*S64eqSQIgWYB;EYRAUQMB&w z-?t~H{wsF{m_%yyKjXnWA(a2aH3fRn1qByET=)xz7yitb=sG7Ze$ah)^_p|rpzvhL zA|NuESC;I<_L9;g$jTN$eOGe3bX-fnHL(@wcoN)<2JJ)z*+QPW+%hNFg`*k%hcCu& z_^`bBL*Ca0w<5AWIj?if5?y^t2KdH%%W=ORdVlVyegEl7Tp$HA`I|4xPrP6)GK5G5 zZ%nuqCyv)o@E-8(s5h|-DLt%qRd0ajWq}Ar+W~1tic}XYZa(v{5K$E^&Db0&Z7nCUdaBmAYfBysu4 zHGP@Ge^ON-(sFz+F_>Yvj+#h(@o6$=*ieWu-cGUyXNNvxW?xdL<=z-w^&4t8ZJ8|r zRvah&ZbAKrE`ePB<_SRO6n^9rzV)&HgTO%tE&?DmCFCSh`zNd0Vc@h2?M%ow39v!Q zeth3z-;+gxD1%y$poQ{3`(B;*sL+FIM`6|PBj-3>s8PGpT$X*LO~jt+8z%S%7P&YW z*4?#<)7# z1#L9@oiI7Ed|O-ogGKq8h6ZKH-qY&O;Lx|Xm_zF{8IYfi!q9QI!G7ut)3&nj8n-bA z2sD9P&O|}n0H92l-cR$ec^z3n7Fz%K0Yl_9Ie>-@!2?oZW4{0)mHjrx&(d$r9m68(sUvz7C}n9`?)*{0&v3GD&iO7N zcNaUYB~y#xGmbU=vV)Zm=LN(csmD)6{>Cp!!kO;-FE4}WRM=9eN5sL(EtXR_tK3^r;P~Y>zm8z#@BZN64DB979aQF3 zzQz|;D<;iC|8iKnh=Fwdzu3|?h$1T_kNlIF;c-r!vsGk{ zN)Nrp(mBORvlGeN)GriQ*f;NHgj|0%P`>CRi_QB*fizJyXN}Rto7;g}Fu$3zbo`A2;<6wB z!#g0eh0N^uv<{Ztrr{<_`LCdh3qlXjfGu-_`zO~^1!f_4hm69Qw`4KXan-PP%=F4I z6+B>#3_`WR01wMAg{3?R_XzyqbJ&~S^mN{fl}_rE5N|{=`K>l-UvU&N!OffW9^*wm zjkNoeaMFAjT%-(b`z*TP)1sN}+>BRFTvMr~>*d`zH}0E*;)FS-m2@u|g$nfCWDR~= znlWGEplk`vzljt7w|2ZQ*BgjUj><%`j~b|zHVs2>Ql}c&~-;(;^lroHT(;8b;kOZJpk*j zIZT#iR0neRCm9!L|FjIrMtU;#aH>-Hb16mknFteU)+7=Ttj^uxI=xo!Z_|-h^5NIIi^+PMMj3A7&S>-uGF_4x# z;y(K*Tx4`bZ~VPD?+b(6S1gUz9KM3k>6-bfG;uqR){ww&)%=XDYv^>C_L3vLYp=Q- zqw$c#6FBL43(NvD6H2rOZLtnx|HBy`dmYy_97{xAd5g43|FkBpTvs{_5x7#X@gTg8 zLkpm@af2zXXP)%= z-;KlAfGGm8O9sQFf<1y_AZDp5^?-7$2ac)8T;}urY_55P9tOLaIik=eBXFNh5mIY3rDkRYNAAi*N)*& z-SQUK1K4uRNWD^ss!2AtRHoIJuXgF!hfDhw9FV7{vZ%ScK81`ETmC7kP(a-EY5qWhp^a}^o|VvW3)S^}c>gxG~%GL6h|~5J-4iAkTpp7$A(_kES|e{l zFtguPADtjWFv9qy4#HDZoPnfq5P#JM%Iydia9x>}pr)5o}uG75^;waj7KU+!EE6F%9E`(t?Bj8u_)$dLoC zmy45bZGK7a!w;Pb1!yhb+IFAP zAUjasu5(E?Z2Yvyi&MczEoY(gS3ydzJQv>iJ*wuXK)m>*g`pZMAnVpL1HjGVAWdvG z&XR}QF0;G1yKt3K1d)bMq7h4zEz7A#HUKU(5P=P%GwV&9XSHH1IR%M*e;rTGfOz1#3tr+)5AF=^1K3%;jua`OywlAni?PO90IU+W}KODK;`s3L5?nf^* zFI`S=?BxUwG&l^p?`BcukVA<*0s{%{eUFzvk4j7hEMCg*VZwyXy7J%cqF)r%)f6OC z5OjzuOz${+rC`IUHiyY`V@)q?1U6PX!I4Scs+?+2i^OK7(U+H$ax6!|;I`CYKNEg= z>hPWuQOA~wDBpaGqGrS6_imaJKo0rvzJLS6@}&rX`#4PRb#MGwq>0sltiu7M16o&$ zApRiCs957(ulTwmQLLBzJ4Zx29_0Z>5#X=-M%>Gg{ob7>B?k@P zD=HsD!nVyr7H!=eXFQRcx8R9Lz;PC9Nt<$0hZ>>@P4w)`D{RZ|{|VRcPoLU?F;vk6 z{=RJe@S1v&z0PuHnG~U$N4D4}1~bqPI)Op)=%F(_8TE7(u2$zC(w0;#S2vs6Y$%tz znTeY^U3z-;^OG^g0_uz4l!`^o1-M<{Ar+Dcr@ysJWMaxdVaTMM%6*%_yaU#sbk560 zfN~+VY2)eu0tF33l|N^hZKT)yJk6ZI5YQmM9#Rb`M_vJ@cz9WjkI=Z>TL@{Mz!8d zw5UE0k&Xob|6|(^6SC5KjA&gT?6p6b&0xDKAg;}+75E%FNE4QZzmJ1@DrpggSvGJG!c*BY_q4^-PN10@VpB`-U` z08t;(LvnSbPKfUO0@yA6t2z@7d0oa0THJRp(ww)=MDYEckjZZr&`D(Dg~U$^h_L=D z7nB06)!*(-R&<~5NezF}YW;HFKzoRFExG3DIQk|rl zEMi^ZmVnkf5@+!i7-$x$4HcsM2zQhL%H1Z#HMYrr`TQ{bJ(GZ??u0e_g7`)hNQQ8& zS+l3z)=YntzfkZe(~0xNutIt!03u$)+GHxxb!KSyrw48tGm<<7LQEZz)1!KCqH*mo z#b-3qN|$Fft&i@a3@+U#2C}VNdu9Hs*mZ}zD?DMZH)(cG9jm*G(lif68p5B8r;fBX zy=^eOdcD-GA2|MHt14oSVogw3b};s}@=o#@mSM6rV?r7UX8v>-enGagd%`5nGQ!;R zUg7?_UZ`D}=~uH?Gbime{ZEioDgb3e6}7Wur4GOUeO(n1_jwiFFB`{F^Tt#lNBpg} zKo{{RS23|Ka1^cSMWu}=j~p+Svk87}1DRz`rj^=C2%$NI4e&v&B9}5SY+rIdxV5=# z`n^>}u_(2e7TNsey%7zEz{YY$t7P7;6A!fpULJ#uS*L$`?+(9A`}#^p2=SO#p{TCp zNu2ninA%a=wy0i$>Yh>Q@bI9x`wZub=a$AC{(}VZPIjy08_hOBBm^>4UyUSew4Fl7 z4MzIWd_)r_eqoc?b_d0MpZ~(pul90>kYp%ByvZElz+5vT^J6blg{{n)PY#+Ydq=bI zFB2diDx|V#u<@jP#*%%{F@aaSZ5w2-x~<;$5f_GDo(ptDHi($^M!OA8h1Re8ADyIN7#4&f$ljhba zJN!!xhzF6ZCYFjd!a>U~rrbIlp8sa`Yq0BVTr5!0GRvP7OcieQ_y7p6x4#Un87d9V z^7Nwf@e^n@cD<2MhD(HpBjqEeItS6WhLl58zW`d2w4gjaTU{c2Ic{C=<5G^9i1A&H z_mfZ)>?)dT=nFxA{oQgG)|t{A>QMS^Q+*d{OXio@!V{^o4^jC-13g&vsHZniPjeiv!)Z0{J|@~G&1qfYBOt=)tJt` zUOur7YFgNDxC>b5Q1o&D&+iEz`8nN4+o{Hq$(HXXk}98aCln(y(tx>C(1qv$5v#>w0sX>{yq++ zNJoxGSV@dAbQXM?mRv(Z=^a)pZZ7R60rOlVTg zzFGn%qR)alZ;*Bh+FU-eeXP};9w}3CEEFMl3lRaZacdL!7Do%k{oNIdtHCF=#3eyp3X5478{}>0)l&A{3a3E>*TO_!CvZoCWk%K9G z{$|w2Zhv7hebW=a83!0p&YT5MA>XFtvp(Hbocyi16V?_w9xE=RC>u^AN!wj=&d9*R zHE@+}%KsrMq7kOpbNQYAy(0f7YYhcTCC<=q_qPiuB@UWoC#~fo%AXzWPPZ(BX*0W4 zV=XnIbw>gWymYnKvTe|$pqA8GLJRHqOlaax? zWb)rZJeJ^*JTAY(I8NtuAcDMbq8pj**~gwy+_+J%JJT`XD~PJbE`k|xwK2jkp&^F- zWU}|n&0nFjG^3ZHxo61sln9B?C6>;*1cH{q!oUppM9TDl`;Tf!BsPQMXA4n#jl+jVM&x%56h9>{#6Dw=3S`zngm?uh=q5KnRShG%@Ww0$3Jg}!~)V;WFOMB9G1mK}B6v4wen6zk*`_?y6o zN>F$etExCvVNZh_SPg6K8SM+D^`B>uM8%{=j2PRPO&2t~&6#^`P!2D>EJDxr z!x$!_fTiA?-xkT7@{O=DxZ;$-7p8CS}Kd;r?57|?vNEhZ+Vw3#eUG< zTW6nEk!j5#)yGg|x$w91O;H5y5AV)ww^ZfCNQrl5 z)w40^cYTnu%QP0hvH!I1pi1;0oGpRV3Q##TFWZQ)O#EG}Ljd@q&k_nl)#pRFIAvur zb+u%yoIOj=6TOFVZd#z%83tpP{kMm@^%_93UJk;NWD_loxnck5eQE>t%#8<{PKHO_ zOKw^6zetc*q$;1wu>skW;4EV&m%LS!RnQ(D%0esTwn;+Pt?rAK#$%&P86Y`d!dXW9P7}O%nQV@@>9!p3=1c;aU@h zGDGqGmdSN}@MGhG@veS@_G`7M?$q+I)dRH5Z3&BlpCL9aM&F5`$F`p8Ns-|lpYU+CHgcWESXm)PCHys-Oz0yCg=#iI zoG1kTST^c1d9jmCkX0w-Ja1!dV*>K?_*k8ar4L|W1DixEIWPK;urqAQhUZ8P1Ay*q zYqO$Um1)d!-p4zgKbwCSFS6R|z|&WRx!LB*Q?do0OrkCFXHU{=#AGeeIF{C#eXW8O zV`0nt3UuTD+~gXu4)?0@vn-2P>xn*}{SNUDcd#-rpV#D>i*RuKVIuZM+^GKB(t@(H zi=o$cSRRFor=JM?Xv9dHQ0si7^KBR+>xX)kpYnU^k;Xq`jqDR=$@Ij`NkcVz-r6=NOPH(!E3aqjO_!$O&WU#+W*A ziK`Oo_b*M*>oHxQ3eC`VCP>|rjIsB+#EkaWjh?WC3U0k~FWP<)!cS9z$S7LLv8a_ViS?P4<&{*&=e!$iI4wE5NUWX7NcLTbe9#dTF--9Z z_@e)%18zm`e8;|>y2RWhXA1Kiv=VM~aNIo^WcMVR4pemfrb$Ue6KFBa`a8$O_G;Us zf=w@7G|d+UJzAbHj{Ggd!%RDS@KpHZc6yY$W|Hn(9X*)f3_LX{wWX|4_x82VP6^&G zHrJm{|FnD!f7k5o9k!^W0{c?uBAebiWkEO0x(G{XND)H@Bb}UxtP}m69J?(9L~Lmq?1>$E~YnA{_Zw{fZk~w+E{q|9htzsFExMc+rT(gA~Bng{GlX)FWxy5QTna^lx`cS_sWQ$;i36TI3oA9BKGj>UmYbc z=#lk0T|;zV3TW4;&O$EzZLX<3lN8X{TQ{M-WcMA&V3x%2&_)r3w&o-!=5L@s-1pL) zp!_T4(1*&cAwWR%8@!*t&ACT4HJe0kIjwe*Wv}}{n<%yZq0>=d2Un^sw*fmctUKe2 z{p;JO{9tJD%fI6mg0+miOtdE+U&<_<=jQLCh7S8RKURNzc-+$XiDL9|uIs;w#36>! zr!;k_Jcr`#PA^%1iScMRj^MR#N!M|6_3xGKcLJ4=x-+{t>kasr%EfnGJTx}nQirKW zfhJs7vSOo8;5Os1rWJXMj^>L&+r;#gDE_aB&h(1qk{WN~0SlW*oBT@PacOto z)A-2O@YvxSl#&{N2gWm(NKllFkqEVu670+Q+oH|yCbzB|EqUi;s;FEYz zh9BuH#S&OuXOaX#0@drx*RF_Bti8ohgd7*e*I{Xd86NXkr4tp^_7534%5WaHKp$emr zRE|;g%x{>f4(oG^US~Yt)1*#E*KSqqZUeS${LuE?6~5<@mflVG|%5gI3*N?R)#p${YWDFN7U^A1PL~p zfntSHj1LqE;5!Wug^m zCj$A$9Nn%wr~n2S`?5bEB_z15U-i9M~H4^`=uD>oKW)0RUcB+z9yJ zXBwzlu;UsrW2eKGI@WlMm7fq3&oF5j$i6quCt>pbT<;^p~Fs*CX=qJ*pIVBWm;eplX_K z!M^BeA7KAKlDU3i&wa%<edC0KRtI5dY6(EK`1W ziil-n4qJwC8v&~cRNsmK(r*G*f}}uylKN!kem|7d}6JVOFrwIDCHstVE~|!@qmG~os`iUL#$+8u_QZQX50w) z=aX3?{caF;lMmnrd60ZRu|GJ2^^Jx?lYU%RgGLgOS0`p84eHm`(`E`_DOdqMTO@!=j(#8@iUWM8RF=7efL!*#Yp#rh z>s=%O(nQ?sa5d$u|3?ZGvMl7&KLoB9?E^6`UlNMxh0bcEf=JJCk<(Wn1i(d>cPx0r z!lFik1Rh4*c=+F$5|Vy%C*kw0hq8RK281i?Ncu^lWW^MTn%SsJtE;=$FFtUn*9SFH za_39TyV*MQy*yJs=p}}D2v-F~*;%VGru+_M~i+ zGxIAK$+=-(oYQMdBkSNtj`9b#pNnnR&kEmRD|Xdj9JiKz)5!e1q3vU~iidSXX~HfZ zn=Fw!q>xh)8S>FX{3uoW-KK5etb1AtDfV8ovZ6HA31E+6MF5SiNyY##ws46vP| zU3<>McQye49!A`F^v}~8qWtbzgwMU+`OO4?G3jfCL?S0d#}xhh&WYW?+nj@Uu8x-N z^VZk$?6R9zwJj!>V3QNVgFUmk&mzMin7EW(@!!=`sn^mERIQRQ^ofUxew^ev@vO3) zHZ}+}EB}U90n+5@e^1qWbCPVHpYcYVqi)r&vJR(diWqS6*oWGEz88omGhic`vX)lg zFx-^=0sET&h^($^1?M z4b;;(IJsJMI(?Re1^^yL+<5vwr!|OQo`mII4_iTt30M`t&sx4zB}O;~lBtZ&BeD`GvqZy zqRhPG@OgqRux4z!Am7c8tLU_VzTZn|#z3V?{KLW=3DD7`hJ13n9`d|of&0_ZS$1ey{ybq@Vtuuo|{@%s_ zL=&lChv8H_Fke|}Yj9$TOqa!`7l=J%DLa5iO#Gf%xFlq#FI$7#8`)`4Kwkv}sau$P zUDpeV7~}PzRCuKNbI+G!Ms&72DnwO{3Y6ZQ>BG4LefCmGAccz;~GO{o$oh z6Tcc{e%~w%&|g^YsKu_@oHy@|1j3zSJ)`>bDf3lYxg= z5a?bv!-6%alg!+3S?zUUIkfc-vI8DQ+$j6+G*E?L$~p-Ez`!)!FvihwQh>7pH1)h7GW z#CLhG8_*S;oCl!wbN*eCsoV_Uvhp4wJN|wm;z}*TT=xAJv(Xgbhl9yGfLn8=2}tw) z9z2Xh{9(VAOT=8YvVQ$^zP`ff7H z8#dZlE4d2VlNvx#BIv%2fii2a?Q*us06s?C82;zm8ma=`O~l;uv25iThJdlMZana+ z%6E8$RWx)|qGlxcn2MQspA!;_=IQkrQ4X^Gr* zE>u;Q)6IBj!}<qtEp6kl9qbB%7oc@u18Y>5lQ6*g1V( zsII1F>igL2AT}T^UwoeBP-M1)X5bq}dX63SMZJRn@#DcPyYDk;sxcoPM%*a=@3IyN zzq^wN`PRc$PPrq&n1&{@Uq$pRQy60F@8YXBnRD)37?@Z;Zo0NNIODUq>5y&J{Hm;wUi2FSdIj{mc%iP1OA7!1iE-MJTpU@%N2gQRK9|ypd;ug8^qr1p0%<8w4QWDMWO86z zVm|1!GnK{tr|c|JiCR!;tyk7X@;F5{SYZL`RM1@ZdaxrFs2QQK`&EUpq_fcgkN_S= z+!*`so(xq1cN6N871q;A?mrC!OuBAG1LG&D?1dQ6c>BU%>p&YHxb=C?`R1)jyP3N1 zY#H~q^-kvKUW@yB955?}poU;EtqR^zI~-d9RlDJY&(?x^8>u45UlkU+j$K>osG-aN zlG@s}$mqW520$8O zgu@Mw^9ceQfv{_D88T3mzal~tVEclk)pjWN%1tLC!sju2f4f|a z+1idje@)F~gH-+p<=}v`zuItD*QNv2`dV5RY+P;`5KBbJRDdF-2m7?S?AtC9+6r8f z%hP^c9$s(+Nh?Wiuk({OXTB^!dJHx@2E+|h)fPw|C|70ycgqgC8XRpfczWZ!;*XW0 z%NEKJ&K&D1+-XmXmcqvlE$KZT)SU>XoFI9R3!QNRrS1wueJ}{ZEGS!~^~VNuvCW9E zeNuj^c1?9f&#Hd!z#gw3=pb>LK`9iBpd|nvM%)l@{!W%G^Ov)Q%DWyLIxa*9v}yJz zdnG5@F@;2n{D0u3&DrdkK}mUa?u)DI<(9wLf1Xz{_9<)V?d-b!$1=-=-GM5K#$3M3 zqb$n!IcWQRYZ5tiZs2Sa#@%OS z2CqQI&|8>qEFoo1l4ug_T`vk0rim(~#;RVd1tUTxyKTf2;nj4fG#4FFGPXHx(Gz|8^x z00000jcWh^3IG5AJ(0dN6X4b1*yG*R*x}gP-`CpL+sfP2K1Lj-|NgT??Qe5Wp>oeh zw~PZ=0V?Z?26D9(wPT=ad@*_TUjDp%|G)T@$p7?V`zKq@FP;6Fm1z*$PN|PMNt91w zg0AzTxvnkj?W=l4R|0DN;EkOXt<+?KhCgvZ+aCai?j!4vq~GzrS;0V26}ydjW(m~Hq`>LceV2nFW!attfp9R)QaW=i_L1$= znHh+wD|+Oh3WDrzD6TEayV9ndtoPnW)Ow0zdiLgmDRLx@Su*Kx+omWf=**N3U9XnnWs@J`8bDCNwOOH{7;LEXur=-;}F$5_Ft(8^%h=H~1omItK zgB+v4tH}nGDJ}60Ecm@QE{co|3`4Lv2=Y3mAWhNAriWBJ24=So$c>$F<0yjy==cRl zwE2^5{D3I$qZb+czH2UNNMIZA*{56`=1mv+#+KXLd81|Qx7&8^g~`w_oYNcEgd=n& zhg#Ci4t_=45dC^*8SCb6?hU{BShzM;3IetRRCbRnze*cL;ne)}tGA5DYcCG`{PBv- z{U&3+n#r4)phh1o#*^Ht$4QwO*(NKU3wabJ<5r0sjg_oPAV)MO4#chWbgYmQ+LGqj z%{G3|fT}?L4+n$t?W+4-XTwGeP`6iGk9NiwxR+i9ed?=!_y*5X7ff%W!O#Z1(*m3X zz1Mpo=XP|-`@w!*L4dcs2niQMRpkl=`o9FV9Ik2Y`_>VR(Si*i*o&M|;7 zc=N2uwZr+Y4d91-(5HtFPT!Y_`M5$8OCp9}RMz{oz$mM@_wUFEmL+?Ki{@D))((#V z4Vxf7dASS+T7}!|EY<-CGI2_Sp^P`T6XwTTGX(~MWz4UpimGGnN7Ha3Y$8>&(n@0? zrH6x15f?I?(oY@2QHtM? zPVVKq?W?K6Z^m#P%x#BU|8_K{REcE|AyCyIHvqmx94>!Lm>bgX-<<*Xd~{jC11msf zuK;pY)G=WIeeho!`%5WX{^V{AZ2j@%S=qk*9L}6y7zC#El#EN-QhK#XGN6iQ-P!%f zYwi$`&^Sj77b!*+zfRi$pY8vx6BLAVCA$acGY5~ZCl*+Sqzf#(9a)6}%t&!;t6bFB zv>`3wDt_Y>J{)d<{OSnzui_o!rM8QGc&2L$ydTm?f!FJ3F;^l4RPRYd|07QKSVWk@ zvFCL6?X%`OW*5FlYDr~EvNLArIbEa)%hc7jG?Ai z*2d>uW^^Ca1`k^vw!`uciF>j-+uq$(6YOHqcY5uk*>src$0gvVD4#^?K&2E%xhCvH z{)aHV0#wa_&YsGZl6YwB(bJI!svFF!KP(A`rYXc*?oZQm-l;^{&JYNOqpate#*6oX zJ9HopG|+u{4d7-~W1$q(_{&a1%V0Q}jdyX$6QQ7P{AYFrOK1-e&_itxtd@$KMhqA| z^H64xrJklu*8x67+=%#nf)P>|wb!mN045AkRKZ zxJE)V^*r&L?ZyMb?I(Op&w~NlG^P&stV+1$y8SEUB3f;yP5J}p??~cr8U^VGOT09_ z7Csn}e#RZoUH0De_x1WGp~_Ggb(}!a(DOpY!|^Jf3t2KSkKlQ(hhlWo zx$Qv>!CuCybxEgzB2fT-Mcjb?{#(gi2KXr*`E)w;ZEE^Sm`vhm64@x>GXPoJ4D;a3 zy|gd$y`3j7WYf1j>Tp})WwJ{pPe%Ur(6epWW+O(ze)8ZTXe>wdgB__ET5O%lp)UAn zt>3>Tk)uB{s?=Ac(Jugex@IrMPKn$;`!Zx39n;DBnisiDlZ>f_X%VgmFu8?)tH!dl z^hAg$do^CnFR_`8bs^fKl|B?Zk`o3d--SgpjCK%{N^?5EzCf=E#ePezEEzQ1sVb(W z?QH=Pv5h<{p|BpG&j^CZSHx;r!bAX`MI0u6B(#z%q4$RWbna_|vrK@ood;Js+ z1L*L@blNZDe_vbeY-IbuFm>~w%on8056DU9Gb>T1|DBC$RY#!y?gl4~vSzU)o1wpg zuijPS=)GxfvX2^#a+9)jvem?71H|7m2%bj2;_tO4OOA|2n8r?d$cXjOrtC7@ulO`1 zdI``OxP6lI#jyF^dE`P6LEz`~uZI?!2j+sva-bEaAKaz4oxcnUW z=5urDB?YhqsJ1*)Ra#SkN?ctH{K`FO%{bjXWL`MUu8r05Cp*4A!=#K}*?Ol^(G7`h zQXQGK{nl=qEVAM`Q^kG{UPG0`*0EMYqNS8OPInL0PImT$glE`UdS&dKV>JzpF%gfo;7jRtQlv}Mia53JboUBz4Ev$_UHo=C<4-bKv0 zFUbjRzrh*sn~o^`8#L&u%_VYMvhNsxjYFS*{x|dA#^tZ~GTSZ7>D_##e7U*bxlAQ4 zTAUHrD^OM)m4F#PdGH25&QES2XqP z{5E!~gHsU*^(m zNi#mR%R9@ojB?s!a(gWZyBSq$9+>O&li`hZjeK#fAri@V-rF6CgrIh2u=SEdd7|oT zjhv`u4Dyc&suEn^LrW`gKzXK0{E^;L7tMP9_cDHM0lU2CAtha!nnm0vy9&!FN#?Yp z6|@;YqkRhgcMlEf(xJsJl>YwktS7}SS{+YWfgS|Z>`}ZZm=G)_LgNvdO6N4eVb{bX zJI?&Mvi8ePrPGez{qaMKG=;V|0NzE+`cFwo3h8(60rzxNdtw*?V=VwWIq`hCGy{0< z;I`B_cWTz-@pt?0ZQrMfF01tD`R_ZilC97KX+_j22l7MR(_l_Y5^ErRJ1+Z3>`80P zzg;?-WIi+Zdupyc0|+62)r;fl^U84 zZ#DJjLs_g9D-=U#n5M4q4?N3-&!j+>Q!n5FzE#YmkH0CQ{O(LJAC|9*OghrGM$d06 zMxO!4WzJyh%XfL<){~4dOv&0M+-^8*8@2ZS>L~OTN~|n@$`G>WiJ?*@dv_-&`MH+5 zdp?D3%PYAS3zvjK#tRrv!sVSn?~5dwnU*KgvD6t`pjb54wynP8cickH1kCn__G*12 zcQx1AJ&A)s|Lp=IAZLzneIeK9Xfu#DN+3b#tHJNd z)kp{*p!X^bTdQq*%7?_{ zO#01pBAcdzfmd#k0%NjH_ixmkU1{G?LyTwzLis>$Q9ipZ zVNux`CCt9Za=bFskknJ-T@2|%vL?JEygAQnwI1< zu|hxt-bLicmxQ?!<(JvuoeqOdssg&U${9a#9!UYHvJ5Xge9$w)mV7Jo%H*PTzh%ng zwPq}Rt8FGeQL1!kzdf|QkIK`8BnM0Y-?gxY79!p>lj0auoA&i>h;7)n=kx_+C;<|1 zK9qv2jAp@2(=p<&8i_{EmAER3Z;nVBcX=xhN+dRnomG@~&Zz8WH|+>TnbuQye@gYV zH$lL3era4xuWHk0W}b=)8rk9agu}G5Xq;jrE9p;`9Lw!%ub)<~B;6FT#QMCNoszyq zROYvYLkaWc-f#~GyZf#HD?nS7B#EeU4B+kdZ!zXr4?ny7^Uk|LY5x9{n7Vb-f%JVZ z>^kG`rkEPEnkP#{ebsr+bgU2dInw}w3}U6%>qJ=H_xV!jDH)CKsdIp4WI;4|9E&Ul zl#Y(HPUZn3A)4OFiE)dQknG3qZ4R;9(JT*`C?$yDQvoW6P}_9$C6`HakFcZ#bFcXA zRs(rJKfjsHq>gS~`~;1Zds5-b?iT7KKv2z!nz$kM*BLr%Y?$>jN&BHtcr)FjP!QP< zv9Okmxr;CF0p3L<=a-};g!r5Hf$MP4RW~+3o6G|wI!()qkpY0CmRea~|9Sq}`JnM& zUdWU6(M+pf-jTgsk>=4(Oa%wD{~0`$Eg=ZMn@Q15RT^uq#jh`k7@8@uTrSjZPIk)% zF7S67gKe zqzlL+qMFKjQh;X%x#k&Pv3R6qNLYrGzLI!kXh-E6Xw}?16mpNQNA@u=aOYeG@Ff@G z#U=3lMI6!~y0M8b9#3ayQvd{j0RsR40001uYXATX0001qi+2SL(bU$*%*M;f%E!#g zvc5$m*Viu<8|^pugzI$J(xeI=ZQGVyrFD4>fRkOn8}9!!Y*P|-gI!*65dSlAgCfd9?YoTIt}{)KADC zul1663!*|1u`Z0MlGdO7z&6BFx)6ciBqfFCwGeT92ZKrLSo5BotyH75ux;^$yxp%hw={1{_t!a|O!#{7Y zXHRD_jwQ|cH@o%)C|{xI;VP~9a9=-DJB>H+@wu7JVTyf%Ciy4sFs^xR12$Da=jx{! zyr}qt@x?!dfo+rnRaKs2&3xY)3P{l3GvsK!K6_qU3d@GEt2dL8sc%kZ!p1BrlNGk8 z+t(?$v>p^!HbJKMN;;5ft@zm5-DI#>W|OS}>0B}sEpjS3r`kS!>cOY@sd_Jr zn~pVX9sr(2g!}!If}Qfqb2EE~1Ii(xjSGN^CAYC01%Og+&t7Itx8?cxt zw6-ccC}#9dGU!Aq-c6g{e(>TZa+&CQD_oc;VP)?oVnc;a-uqdvxv{7rniRaU$%ByZ zIzhs%R)Um|$cMPHwY^hU8v+kp>TLl&1s8arGP8s>`2eWI(QSo~mj{>^=+)qZ_LO0~ zfq2G+;Z>0^i!7%EzC~o`<)4}memQS296${)=G%&%OAJvn0FX(%_$1n2bL0HKH#g$N zQ=)DBHM;akGu%gnrEP3&Y-rOPYW_SUi>`8w0pB4tn}p%fvHIo!|2wQ@!UPQu4i}w$ zUi?~@QoQk&tPxJ?=Q%iC0AfzPVUl(Z8+pmfyQr_)yjcDJSE!OH4Y->0(qC^UJ2!Fi zE*|d{=@=A3Wt!V0joSx14AFbfzu%wo5^_uJvSvEm^awK%+&U3^u!tl4GW+?SpeoXn3>P0$HUjd1 zwP#jjIL*CE>I9p*lQ4JV3Vp{PACRb2ofG(DVREOnG?=#?2_cp>aFE_}Q68iV=wkk- z(71&6upFVfgh`l+<@*ivnsm;SF7!+3faQ@|SG3zgPR=w=NoX zHPrX>Gc=-nxHsG!5SswTYW+U^LuF{qV^5tcR z8n>G^h(YavgH(r67}e60yUKd)K=Wl{0`>MXye(Fj2v;wNoNeVjBSV7i22|91*oZuY zi-bm~f%c`4$$rjN>0OQ>s>JK#mBzSatzpZy^rrY%Js#))zD10W^_?GKe7b?*016;K zCUO!zlgJ4J0I0XR+3mIsHv9J6z`R;2oDZy+J&&H0p+Qg;JzW@iaIpu?W!K$r~CAN9GYBmk2)U9Y&m()dBvJ-je5(Y zA5qsw`gO&;L?`%Bzo=wN7h7p61Sk1fE5#_xY`dtAGhi2S9*%4XC8bkBM`d z0RWHLO<51d!1B-Plab7SJh^#84`p+*uK|7EaCIH0)hBVn{#QEoH(1=b#6fPRIP1=1 zTK5&IZecgx^c5zd>cT?RPeDKSnDD}rHmT69iN1}sfN*}190@KxXT38)W_yO&e(CPZ znyBzYS1hD45SH+DwY`%+vIA5V9^=J^gkVDayh|(9Ga&y^x6$(+CgH(>ne{lTwUJOA zko*w7a4er}#mWh*J?LRwuXe?Zw*mmZMI7(bn4 za^LuvdhvYsnCZL&iK6Pj zSW;cAz(KO*0*4eC0$5ME?Dipdyz}USoMWU$inK!%5h5b{)Iz!uJfwyb$8UcJWz-9( z(flysd%gW?r?DdfNC4hN93Ruymr#D$SQvU^RV7swWy=7NE^>QmitVS;Z~7`k%)iQD zZLzADU!BdcwkH~owxJIlFl}lXyrKeFXOX6YG12`^=W=4X`Th-7`RQop2{!2wjJp>6 z+xMsZLpOw}RRc!3qiYKy^X}L(By?rPzlnWLt4CaaP=emNDn83bk|4gXU`PzWN<|r3 zN>vSF6_(oOPc6cL2#|1Aik2tGtlj}%V}Uf@$9J&|Z?@)oSuVWO-YgpSqQES;-%FXz z6*`p*cfEZ)fDXPz+;8>WyAggjFk+NJhqh|;qvw^56bQST%$}WQ`>mwLINh@V!uHkb z`eTp#SIR9bP~DWD7MdBiG6?vSyn+{ElPQik!G;7{QDTuKJy5~tXR8QZm`4_silX0} zrPgk>SyyP>y`cnWIy=wwlC(1c(2E3-=3GS3{DTTVe3dr#{j@!?V^!_stLNJ^Ogq*O ze^3LFJj>y6C+D|O+oQED;JjQq)`Lwi5fxIF2G_YK%wL=xKa>G9X$g~BP$;k$EkYRy ziCG#C-evsSrcXlw0Lf{|mHN@ds3-scuUwwYAq=P?i|ju1@DH62Qu$QuOMJiLsjhXZ z!+2{nMc_|h)mUvYYKDp>5BCi>CbCd|Z5X0vK*GH_zb;KJ4Qa7NF8TqACAqf-D=h); zhcCLSfvlcxIQVg8C|TCRhL#6u_Oq)k@20t2BU20*_%S@Na>KQNeWi>+Kt^Flj)riL dFc$oaYzcHhx`t81jO7NViV>5-$M#!*006APO