From d7f89ed25fba13235463e8e62e6e41dd6be4601f Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 18 Mar 2018 00:42:47 -0400 Subject: [PATCH 01/11] Moves lists off cooking machines Moves the lists for recipes, reagents, and ingredients off of the individual machines to a shared global list. --- code/__DEFINES/crafting.dm | 5 ++ code/_globalvars/lists/misc.dm | 10 ++++ code/datums/recipe.dm | 12 ++--- .../kitchen_machinery/candy_maker.dm | 2 +- .../kitchen_machinery/grill_new.dm | 2 +- .../kitchen_machinery/kitchen_machine.dm | 46 +++++++++---------- .../kitchen_machinery/microwave.dm | 2 +- .../kitchen_machinery/oven_new.dm | 2 +- 8 files changed, 47 insertions(+), 34 deletions(-) diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm index 8218d392640..aff1b20e4b2 100644 --- a/code/__DEFINES/crafting.dm +++ b/code/__DEFINES/crafting.dm @@ -5,3 +5,8 @@ #define CAT_FOOD "Food" #define CAT_MISC "Misc" #define CAT_PRIMAL "Tribal" + +#define RECIPE_MICROWAVE "Microwave" +#define RECIPE_OVEN "Oven" +#define RECIPE_GRILL "Grill" +#define RECIPE_CANDY "Candy" \ No newline at end of file diff --git a/code/_globalvars/lists/misc.dm b/code/_globalvars/lists/misc.dm index a6b78bce94c..331780d8571 100644 --- a/code/_globalvars/lists/misc.dm +++ b/code/_globalvars/lists/misc.dm @@ -30,3 +30,13 @@ var/list/round_end_sounds = list( // Maps available round end sounds to their du 'sound/goonstation/misc/newround1.ogg' = 6.9 SECONDS, 'sound/goonstation/misc/newround2.ogg' = 14.8 SECONDS ) + +var/list/cooking_recipe_types = list( + RECIPE_MICROWAVE = /datum/recipe/microwave, + RECIPE_OVEN = /datum/recipe/oven, + RECIPE_GRILL = /datum/recipe/grill, + RECIPE_CANDY = /datum/recipe/candy + ) +var/list/cooking_recipes = list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()) +var/list/cooking_ingredients = list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()) +var/list/cooking_reagents = list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()) \ No newline at end of file diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index e379de25209..668c254fe54 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -95,16 +95,16 @@ container.reagents.clear_reagents() return result_obj -/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1 as num) +/proc/select_recipe(list/datum/recipe/available_recipes, obj/obj, exact = 1 as num) if(!exact) exact = -1 var/list/datum/recipe/possible_recipes = new - for(var/datum/recipe/recipe in avaiable_recipes) - if(recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact) - possible_recipes+=recipe - if(possible_recipes.len==0) + for(var/datum/recipe/recipe in available_recipes) + if(recipe.check_reagents(obj.reagents) == exact && recipe.check_items(obj) == exact) + possible_recipes += recipe + if(possible_recipes.len == 0) return null - else if(possible_recipes.len==1) + else if(possible_recipes.len == 1) return possible_recipes[1] else //okay, let's select the most complicated recipe var/r_count = 0 diff --git a/code/modules/food_and_drinks/kitchen_machinery/candy_maker.dm b/code/modules/food_and_drinks/kitchen_machinery/candy_maker.dm index 1452df3ea70..b77ee23c714 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/candy_maker.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/candy_maker.dm @@ -5,7 +5,7 @@ icon = 'icons/obj/cooking_machines.dmi' icon_state = "candymaker_off" cook_verbs = list("Wonderizing", "Scrumpdiddlyumptiousification", "Miracle-coating", "Flavorifaction") - recipe_type = /datum/recipe/candy + recipe_type = RECIPE_CANDY off_icon = "candymaker_off" on_icon = "candymaker_on" broken_icon = "candymaker_broke" diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm index 1a1dd34196d..fcfe84f3174 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm @@ -5,7 +5,7 @@ icon = 'icons/obj/cooking_machines.dmi' icon_state = "grill_off" cook_verbs = list("Grilling", "Searing", "Frying") - recipe_type = /datum/recipe/grill + recipe_type = RECIPE_GRILL off_icon = "grill_off" on_icon = "grill_on" broken_icon = "grill_broke" diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 289a4c66d4c..d6af2696d53 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -16,10 +16,7 @@ var/list/cook_verbs = list("Cooking") //Recipe & Item vars var/recipe_type //Make sure to set this on the machine definition, or else you're gonna runtime on New() - var/list/datum/recipe/available_recipes // List of the recipes you can use - var/list/acceptable_items // List of the items you can put in - var/list/acceptable_reagents // List of the reagents you can put in - var/max_n_of_items = 0 + var/max_n_of_items = 25 //Icon states var/off_icon var/on_icon @@ -34,23 +31,24 @@ /obj/machinery/kitchen_machine/New() create_reagents(100) reagents.set_reacting(FALSE) - if(!available_recipes) - available_recipes = new - acceptable_items = new - acceptable_reagents = new - for(var/type in subtypesof(recipe_type)) - var/datum/recipe/recipe = new type - if(recipe.result) // Ignore recipe subtypes that lack a result - available_recipes += recipe - for(var/item in recipe.items) - acceptable_items |= item - for(var/reagent in recipe.reagents) - acceptable_reagents |= reagent - if(recipe.items) - max_n_of_items = max(max_n_of_items,recipe.count_n_items()) - else - qdel(recipe) - acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown + if(!cooking_recipes[recipe_type]) + cooking_recipes[recipe_type] = list() + cooking_ingredients[recipe_type] = list() + cooking_reagents[recipe_type] = list() + for(var/type in subtypesof(cooking_recipe_types[recipe_type])) + var/datum/recipe/recipe = new type + if(recipe in cooking_recipes[recipe_type]) + qdel(recipe) + continue + if(recipe.result) // Ignore recipe subtypes that lack a result + cooking_recipes[recipe_type] += recipe + for(var/item in recipe.items) + cooking_ingredients[recipe_type] |= item + for(var/reagent in recipe.reagents) + cooking_reagents[recipe_type] |= reagent + else + qdel(recipe) + cooking_ingredients[recipe_type] |= /obj/item/weapon/reagent_containers/food/snacks/grown /******************* * Item Adding @@ -124,7 +122,7 @@ else //Otherwise bad luck!! to_chat(user, "It's dirty!") return 1 - else if(is_type_in_list(O,acceptable_items)) + else if(is_type_in_list(O, cooking_ingredients[recipe_type])) if(contents.len>=max_n_of_items) to_chat(user, "This [src] is full of ingredients, you cannot put more.") return 1 @@ -150,7 +148,7 @@ if(!O.reagents) return 1 for(var/datum/reagent/R in O.reagents.reagent_list) - if(!(R.id in acceptable_reagents)) + if(!(R.id in cooking_reagents[recipe_type])) to_chat(user, "Your [O] contains components unsuitable for cookery.") return 1 //G.reagents.trans_to(src,G.amount_per_transfer_from_this) @@ -259,7 +257,7 @@ stop() return - var/datum/recipe/recipe = select_recipe(available_recipes,src) + var/datum/recipe/recipe = select_recipe(cooking_recipes[recipe_type], src) var/obj/cooked var/obj/byproduct if(!recipe) diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 49cfc3ad0e8..4c5f07ff0ba 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -5,7 +5,7 @@ icon = 'icons/obj/kitchen.dmi' icon_state = "mw" cook_verbs = list("Microwaving", "Reheating", "Heating") - recipe_type = /datum/recipe/microwave + recipe_type = RECIPE_MICROWAVE off_icon = "mw" on_icon = "mw1" broken_icon = "mwb" diff --git a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm index 5c1ed4ac6df..c6149b382c5 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm @@ -5,7 +5,7 @@ icon = 'icons/obj/cooking_machines.dmi' icon_state = "oven_off" cook_verbs = list("Baking", "Roasting", "Broiling") - recipe_type = /datum/recipe/oven + recipe_type = RECIPE_OVEN off_icon = "oven_off" on_icon = "oven_on" broken_icon = "oven_broke" From 7a2e065a10bb58650f049f281dbf9c0056e3ac93 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 25 Mar 2018 21:44:38 -0400 Subject: [PATCH 02/11] Adds mixing bowls --- code/datums/recipe.dm | 23 ++- code/game/objects/items/mixing_bowl.dm | 159 ++++++++++++++++++ .../kitchen_machinery/kitchen_machine.dm | 123 +++++++++----- icons/obj/kitchen.dmi | Bin 32093 -> 31691 bytes paradise.dme | 1 + 5 files changed, 263 insertions(+), 43 deletions(-) create mode 100644 code/game/objects/items/mixing_bowl.dm diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index 668c254fe54..edb9c3fc374 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -53,15 +53,28 @@ return -1 return . -/datum/recipe/proc/check_items(obj/container) //1=precisely, 0=insufficiently, -1=superfluous +/datum/recipe/proc/check_items(obj/container, list/ignored_items = null) //1=precisely, 0=insufficiently, -1=superfluous if(!items) if(locate(/obj/) in container) - return -1 - else + if(ignored_items) //are we supposed to be ignoring anything? + var/unignored = FALSE + for(var/obj/O in container) + if(!is_type_in_list(O, ignored_items)) + unignored = TRUE //found something we aren't ignoring, quit looking + break + if(unignored) + return -1 + else //anything we found is something we are ignoring + return 1 + else //not ignoring anything, and we found something + return -1 + else //didn't find anything return 1 . = 1 var/list/checklist = items.Copy() for(var/obj/O in container) + if(ignored_items && is_type_in_list(O, ignored_items)) //skip if this is something we are ignoring + continue var/found = 0 for(var/type in checklist) if(istype(O,type)) @@ -95,12 +108,12 @@ container.reagents.clear_reagents() return result_obj -/proc/select_recipe(list/datum/recipe/available_recipes, obj/obj, exact = 1 as num) +/proc/select_recipe(list/datum/recipe/available_recipes, obj/obj, exact = 1 as num, list/ignored_items = null) if(!exact) exact = -1 var/list/datum/recipe/possible_recipes = new for(var/datum/recipe/recipe in available_recipes) - if(recipe.check_reagents(obj.reagents) == exact && recipe.check_items(obj) == exact) + if(recipe.check_reagents(obj.reagents) == exact && recipe.check_items(obj, ignored_items) == exact) possible_recipes += recipe if(possible_recipes.len == 0) return null diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm new file mode 100644 index 00000000000..7f66fb2d37f --- /dev/null +++ b/code/game/objects/items/mixing_bowl.dm @@ -0,0 +1,159 @@ + +/obj/item/mixing_bowl + name = "mixing bowl" + desc = "Mixing it up in the kitchen." + flags = OPENCONTAINER + icon = 'icons/obj/kitchen.dmi' + icon_state = "mixing_bowl" + var/max_n_of_items = 25 + var/dirty = FALSE + var/clean_icon = "mixing_bowl" + var/dirty_icon = "mixing_bowl_dirty" + +/obj/item/mixing_bowl/New() + ..() + create_reagents(100) + +/obj/item/mixing_bowl/attackby(obj/item/I, mob/user, params) + if(dirty) + if(istype(I, /obj/item/weapon/soap)) + user.visible_message("[user] starts to scrub [src].", "You start to scrub [src].") + if(do_after(user, 20 * I.toolspeed, target = src)) + clean() + user.visible_message("[user] has scrubbed [src] clean.", "You have scrubbed [src] clean.") + return 1 + else + to_chat(user, "You should clean [src] before you use it for food prep.") + return 0 + if(is_type_in_list(I, cooking_ingredients[RECIPE_MICROWAVE]) || is_type_in_list(I, cooking_ingredients[RECIPE_GRILL]) || is_type_in_list(I, cooking_ingredients[RECIPE_OVEN]) || is_type_in_list(I, cooking_ingredients[RECIPE_CANDY])) + if(contents.len>=max_n_of_items) + to_chat(user, "This [src] is full of ingredients, you cannot put more.") + return 1 + if(istype(I, /obj/item/stack) && I:amount > 1) + new I.type (src) + I:use(1) + user.visible_message("[user] has added one of [I] to [src].", "You add one of [I] to [src].") + else + if(!user.drop_item()) + to_chat(user, "\The [I] is stuck to your hand, you cannot put it in [src]") + return 0 + I.forceMove(src) + user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + else if(is_type_in_list(I, list(/obj/item/weapon/reagent_containers/glass, /obj/item/weapon/reagent_containers/food/drinks, /obj/item/weapon/reagent_containers/food/condiment))) + if(!I.reagents) + return 1 + for(var/datum/reagent/R in I.reagents.reagent_list) + if(!(R.id in cooking_reagents[RECIPE_MICROWAVE]) && !(R.id in cooking_reagents[RECIPE_GRILL]) && !(R.id in cooking_reagents[RECIPE_OVEN]) && !(R.id in cooking_reagents[RECIPE_CANDY])) + to_chat(user, "Your [I] contains components unsuitable for cookery.") + return 1 + else + to_chat(user, "You have no idea what you can cook with [I].") + return 1 + +/obj/item/mixing_bowl/attack_self(mob/user) + var/dat = "" + if(dirty) + dat = {"This [src] is dirty!
Please clean it before use!
"} + else + var/list/items_counts = new + var/list/items_measures = new + var/list/items_measures_p = new + for(var/obj/O in contents) + var/display_name = O.name + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) + items_measures[display_name] = "egg" + items_measures_p[display_name] = "eggs" + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/tofu)) + items_measures[display_name] = "tofu chunk" + items_measures_p[display_name] = "tofu chunks" + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/meat)) //any meat + items_measures[display_name] = "slab of meat" + items_measures_p[display_name] = "slabs of meat" + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/donkpocket)) + display_name = "Turnovers" + items_measures[display_name] = "turnover" + items_measures_p[display_name] = "turnovers" + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/carpmeat)) + items_measures[display_name] = "fillet of meat" + items_measures_p[display_name] = "fillets of meat" + items_counts[display_name]++ + for(var/O in items_counts) + var/N = items_counts[O] + if(!(O in items_measures)) + dat += {"[capitalize(O)]: [N] [lowertext(O)]\s
"} + else + if(N==1) + dat += {"[capitalize(O)]: [N] [items_measures[O]]
"} + else + dat += {"[capitalize(O)]: [N] [items_measures_p[O]]
"} + + for(var/datum/reagent/R in reagents.reagent_list) + var/display_name = R.name + if(R.id == "capsaicin") + display_name = "Hotsauce" + if(R.id == "frostoil") + display_name = "Coldsauce" + dat += {"[display_name]: [R.volume] unit\s
"} + + if(items_counts.len==0 && reagents.reagent_list.len==0) + dat = {"The [src] is empty
"} + else + dat = {"Ingredients:
[dat]"} + dat += {"

Eject ingredients!
"} + + var/datum/browser/popup = new(user, name, name, 400, 400) + popup.set_content(dat) + popup.open(0) + onclose(user, "[name]") + return + +/obj/item/mixing_bowl/Topic(href, href_list) + if(..()) + return + if("dispose") + dispose() + return + +/obj/item/mixing_bowl/proc/dispose() + for(var/obj/O in contents) + O.forceMove(loc) + if(reagents.total_volume) + make_dirty(5) + reagents.clear_reagents() + to_chat(usr, "You dispose of [src]'s contents.") + updateUsrDialog() + +/obj/item/mixing_bowl/proc/make_dirty(chance) + if(!chance) + return + if(prob(chance)) + dirty = TRUE + flags = null + icon_state = dirty_icon + +/obj/item/mixing_bowl/proc/clean() + dirty = FALSE + flags = OPENCONTAINER + icon_state = clean_icon + +/obj/item/mixing_bowl/wash(mob/user, atom/source) + if(..()) + clean() + +/obj/item/mixing_bowl/proc/fail(obj/source) + if(!source) + source = src + var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/ffuu = new(src) + var/amount = 0 + for(var/obj/O in contents-ffuu) + amount++ + if(O.reagents) + var/id = O.reagents.get_master_reagent_id() + if(id) + amount+=O.reagents.get_reagent_amount(id) + qdel(O) + reagents.clear_reagents() + ffuu.reagents.add_reagent("carbon", amount) + ffuu.reagents.add_reagent("????", amount/10) + ffuu.forceMove(get_turf(source)) + make_dirty(75) \ No newline at end of file diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index d6af2696d53..90b7b6927ae 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -112,8 +112,8 @@ ) if(do_after(user, 20 * O.toolspeed, target = src)) user.visible_message( \ - "[user] has cleaned \the [src].", \ - "You have cleaned \the [src]." \ + "[user] has cleaned [src].", \ + "You have cleaned [src]." \ ) dirty = 0 // It's clean! broken = 0 // just to be sure @@ -122,7 +122,7 @@ else //Otherwise bad luck!! to_chat(user, "It's dirty!") return 1 - else if(is_type_in_list(O, cooking_ingredients[recipe_type])) + else if(is_type_in_list(O, cooking_ingredients[recipe_type]) || istype(O, /obj/item/mixing_bowl)) if(contents.len>=max_n_of_items) to_chat(user, "This [src] is full of ingredients, you cannot put more.") return 1 @@ -130,21 +130,16 @@ new O.type (src) O:use(1) user.visible_message( \ - "[user] has added one of [O] to \the [src].", \ - "You add one of [O] to \the [src].") + "[user] has added one of [O] to [src].", \ + "You add one of [O] to [src].") else if(!user.drop_item()) - to_chat(user, "\The [O] is stuck to your hand, you cannot put it in \the [src]") + to_chat(user, "\The [O] is stuck to your hand, you cannot put it in [src]") return 0 O.forceMove(src) - user.visible_message( \ - "[user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - else if(istype(O,/obj/item/weapon/reagent_containers/glass) || \ - istype(O,/obj/item/weapon/reagent_containers/food/drinks) || \ - istype(O,/obj/item/weapon/reagent_containers/food/condiment) \ - ) + user.visible_message("[user] has added [O] to [src].", "You add [O] to [src].") + else if(is_type_in_list(O, list(/obj/item/weapon/reagent_containers/glass, /obj/item/weapon/reagent_containers/food/drinks, /obj/item/weapon/reagent_containers/food/condiment))) if(!O.reagents) return 1 for(var/datum/reagent/R in O.reagents.reagent_list) @@ -257,10 +252,10 @@ stop() return - var/datum/recipe/recipe = select_recipe(cooking_recipes[recipe_type], src) - var/obj/cooked - var/obj/byproduct - if(!recipe) + var/list/recipes_to_make = choose_recipes() + + + if(recipes_to_make.len == 1 && recipes_to_make[1][2] == null) dirty += 1 if(prob(max(10,dirty*5))) if(!wzhzhzh(4)) @@ -286,24 +281,69 @@ fail() return else - var/halftime = round(recipe.time/10/2) - if(!wzhzhzh(halftime)) + if(!wzhzhzh(5)) abort() return - if(!wzhzhzh(halftime)) + if(!wzhzhzh(5)) abort() fail() return - cooked = recipe.make_food(src) - byproduct = recipe.get_byproduct() - stop() - if(cooked) - cooked.forceMove(loc) - for(var/i=1,i`?k?%rbZqJ@p7(vP zQ{Q);U+0H=ueH}?t}*8vbBuf3V@!W4DM;gBl4Ak@fFtu>LInU2TETy5=&0Z?f}=GI z0DvUw@=?Q1;;XHpjj5HLsig$~I3*Rwwpq-xV*3sEs-hoQ>qTS@TGSC81OoEf<{c$| z=A+e5G&x=~SS-7vafkR%J=H}XdWI^bBFqq2In;H2um~4jFrOM13?Db?`k}ODO)y(Nm&)>lRdCuVrY*-<7@MfiapSoae_!2?(x1P>tAD>H)%M`P#G!FW z`I3mB>;_pjzZf$!{7dR{6~2I)j5HXxAkcSE#JncM{`zU2_jtRR1s=a=z&SV}X~fS}-%a&q|c@^q78TK*M*yG)n$|NU*e zMgGNY7oR-ydpuXL>Kb`dkpCumlh1IViStLdUpfxM{+llm3?WX|n;OPrr(C(kt^C9B zZ6%}puisAvCnC65da5vyUV0<(<4=bzJ++OoYx(+HE(WIi#kV2-#l?p$;dz}W>5jja zy2r_b6?I?cBk=PyZQj{$!cup9(#8j5g_#e*Qr)ZAOEQ9K{S8T_Zsatqg?kMxn~y%n*;fPE$E9;y~4gn~C6V(Bg}s zBM>37d4<#QGRe@M-j~<;&-M-+4(tyMSzKJ+xm~a~uwM??FE{Yp4#I>&vTJKekwx*5 zS1pm_k`cUV(Y;xb-id(U?JUobUZ8u^-ah&FEd~ca(vp~-9(ArmYPM{wR^_2IeCda9 zEJT)!bmn*|t&>7J*U+y+Z?hduEV2+H8Y^*0wI%0W2 z*D4uAOlCt;Z?o~Cv~iF9q(mDxAAJCF{_8nM)A`8+?R$Io`uUo+vTc3@%n=d#3 zct$U2r(Eb_O0|3*#lj_0*I%zjsx^eacp;zIOF=8?>B~LBi1=kQHYus7P|4Yum-ww# zXK(zBv>P?kv7&=9{I^H4t-JGkL=aT}3#EXcJ{~01Fsqt?04Ube5vH^3XTAJHm~OYn-M{BmRaMK~?_9dN`}_LDq^12g?>YzS44LNU_^*do z4d_QFQS2NXPEzOR2=R$#dP|X3j`S=bQcC*t7R}d2w|kI>-Kww{8@K!Gt%S>QSxD)L zEWwi}?RR%D4{2T9WS{b%A&R{&#B6^$JMEU;Zw``XkgM+RU7!y(@8c<5VFSpM2{hBX z(~KukK|CE9%<83n(%sJ)_=shRjp&$isG{CQvOaIKusQZYd(O>Gq9aSC;!+?yPj05R z5kwo@xg+BAa+74lMrxGr<$~?7ATg(`<0awP{TpTidB5QqfP(#Ph-@wnvh?Sh2i~w9^j~wYd>W-L$gTv)P%`$U-=K19` zyosSpP3?v2@R&?n)kNJyIdUg0)0@`StNn_jt2K1|vP*B>W-}Z;mksg8vp#<}isdLp z;h@`FH*hjXC&Z8-RqA``|sWj447J5Z%4`IQxbEX!e?Ck8B21m=*zr9fnNEa~J5PbOo#nZxo zB25RhM9G75XbnHQBMN@oV$eXA_5f0N;)BjjzI zfoA)Fg6xKyoove&H%l&92sf9GFxS1e14%ptli*Hfe%;!o+wg);oOtK!*RKYH37iO^ z%o-I&@&F*0B2cI9PbSE^=4z{!%}`PhJ@=|Am6Dg2H?mZk=7y#ByhuI2ENake4fAo% z)V9bG0PrIsH8m{L|HAOPfRo4Gref{nn}I{u46h$%?G(2??f!mXd01Q#>=%+(@*QX% zL|iMU8p^eXxkTB(7r&R6|4NY1|5eeLc<|=u^*F>~rMKI|=>2RbpUOEm z*6x(M%TA$W$*maI-^~-MPeuw!J*CTTN3;+3yV5jW37p>$Un!pbO=Z485sCWCsdM+>nNA%8#2GY_nnFk`x{b{ zE}Mgb!Pqg&>=-`57W|Ur71e|1Tlo=>EY_W?d2>_m=KPJ=j>!ixwWoO>Cv)_IDY%E8 zA13{N#vPl;YyF&yMj*iX`kGkTrRE|^thY-u44QRydphiDA4;mJj`k_Ek95b3srY8c zp0cU0wDYXKwEm6$$=}{Z*ULj3pp|0baTLERDjMRS1>z{02iTY}1nDie;2Vj3z>&dS zy%(#9^bUc1kyS6V({ZG#jp1u-xPM_87?s+92T;2BTQI#5`|u%fcZl}`+xV@^nS9e# zqN%$eT+i6ubMN6t76M;k3C9~mj>MX!TbkVYw+L*Y$)^;;BCxQvr_ASfW4Kd4v`Mm5 z$#1q2KDHK2hhZ~79Xi_arCq#x6neHK#KJf%LzTx0wr)>n5#Xz4p) zzlw(+hwN>nn(}5ZaupA@mO;Zv%kh`!VM##{cwdCpqF0-G#52~dnllVKAf@8r&~Gu# zV<*G?!!_u1BE(hxzP?tV3N>NNnOi;1A*f5gbV@l8Io2+XyVXwauneSDOAPX6AYRD2D=pTplm5q(<<)PYE}5f5h)4i zN^y?70>^hqn^g$+=cOKM(HGM#_nd)&fs}KX(T6vwc(;fYHB?sgg~;g?%s5Ix5i$pv zUr2pPiOF~xcy_B&k22mma>I)Fc^hhf#Xzqn`2J+I|vEVQd(MKV32?@hnCjU$yy%$xQxn@0uizjBhNQ1EZ{6v;n5zs zRjom1g^*WqoW8u<_l#i=^b>ubK6Se=t9ZEfHdXz-?j|>ylj@ z@}`OS6iI*tVfXsx+x0ye0|Nu|;8?S6GgPUuWlVvU@ReM6a`{f(R!RqBX`^>^G!fCc zof*TMH)3Oz@vS$Iyt!D~MlU_oTF|oxwaEM7@aVB>Ag}C;(J#Dew9+aH?N-q`*nq)R z?Ck6`R8&EE!uED~K#fC{m^paayT+<>Oe}3>MSH{fS_% zlRcui+>PzfUjrY+@l(WXXd4NnHU>A*cv|!W6t(h$63Xi3oS4)P#Is;YAU?u!J&z-u zsclJF#SafW14QEVoG2NnEZ??7Hxsaiq{SrYZK8?TBol$7S{V%EbVa|k?~cO|v;0yh z(zI9>?5n#nlPu&4V?)D|`*rAvaxE)a7Ka^t3pTis=<%7herOD2z%YcoormryxViJgxolrJ|Fy(*jK8qH!#An zcZHme;=-2=WWp5wi$}zP00s!LTYR7Ymq`2n0N(%2Z30#_h|<4!Cnl79YEU%(I3YCV zh!+Ul;8!sI8Di6XaF05tVbffmIO!LCz=A{Y$HEaV2#nN&lU3vFZe=T&9l&-=5bzqQ zLg8ZesUZ!69N&GlCJBEBH_Eg! zl4!D5wEHMVei#Y5?%uSGiQrT+f19iP1-ajY#Mzz>GLKi-?KvLmRDzQmL=6v9NUA-l zux#nlsaZ(Y21;D_8#B2`7ao#tl7H=#D>t`;(#3-Jv%u$srB~u*4qO^C!Tkr-b!fT zEc%9p$HsPVY;Ga~bL3`J)lZ3t-b?u*gUf>Y9$)CalU>oQCM|lZe}M=_dpBtJx2u>L z7@+X(0h_z{C2z61}}_xd>YHt#E`VzIYLlk!wfsRVXUR@9}rjx&C?i>FM?5 zcbqEpuuw@SJ0=?&8@Yj}qF1lnkVzLN?5gIH`7<*vb`q()X_G)C&S2^Q#yKDaTy^yx z3rF|1!cp^bd8TC{rIWsCl+ChR*y}U9;n)@VW427g@I}pA-TDc!j%Vm%WFJvJ;0ryv zxa;MwKHu`iC!v=zIlcY;>pkcg?Yu;waACB;hf}&OsDPDZ8w3DAH04&68?!r{DII2$ zpPwH%9vc($d7;+&8CZ!@6k45N!f2mf#VKQd zW0pD>8&5`$?%}(5PV)3=dR|@t4N0Cf$I3SX+EwSr4P^NH{?3J(1-~p+;D1w18~T{T zVjnb;Q75`Pwwq1wvnJSPDA__${3k#}ciahR1XF;6M8(A?)RX$K6nJpv9+|L42!gDQU*`yI)I88=&Gn7*FK=0**$j zzt=j#?FQj%hPSJo7_rW*4YxMV3GcpQ0%;`}0YCZLEfZM{5I<)iD&L-K`bznp>`a=4 z{Db2r{%;)jR`Qt}Df?ilG(`Or36Qn6F4yaR4kraE93j{t+ZrhD*S9yE=5v3mtHZZ7 zD?V;@44kk(D!nFqao#ubu(TL*30zAlaFRMDsCKFj{WBBw_b73JvRQMBOKf{1&m~Xd zOnRsoI*t$R7wgNl16;9=g1P#0uD9I*EvtT|3%x$^8|q?m69lxFjnAle*@P>nknY+C z29w&#cJ(UcT9?mnF!jEA1`)qinFw!r47hLFpuDi9&<3f^!m=Prb{>h@X{r&HtIO+4D$3l+SvS_ zouzXN0IgU_S{eY984pvtLr-_!``blyBvMWJOVwni&k8A;h>Ch?H;Hd;Y-u+(!N-}9 zSXCiKGOzNeO4&g-Kv@Td;^uP;-tvjs_`HpEu^3#bp`8&4NG2wsqT;sLAU;I3y4LhM zTnX8v53LrUg2opQbKIEu!ekl?FhP4}dKf2!0mhd{V~jM2CJ3SEHPt{s8!V*(@4(&w zJxF;hcD}~icu5s9P4X=Y!^|H$oVGD32+8l+ksGHu6`fNQl4n_*!_v{*Uc3HYfL9mh z{-Qc602&2O_Ic#hbEmIQw{;yCH|%zbugsb;U^#ht=p<;^k6s@9YhY$DtcgVB(AtTSSl{{#B?(5gTr5d>wD-4c|&x2rc@CQ!)Z#I0rtYE%sEwiNt0!QKcetJB&7I z-5&MoxSJ+18D;RwW(fnF$H=np(hXw0~Vg|B1W6>jCB# z%CnZE#RnAmA5!>l^hx*$&tWW}U-$Y64P+y2xvOdTdg183Mt;ZSZ`8Uk@|91OgWFH%US4LKLJ?T3O14DVZ&`y+)D33pN zz#bjCB0MIBSflt;Wo0E#mcd@pC&m_q(jc$*9=Cs0U{9U&uC})9YwPP&Q)+5z&)&ToGf18^v%h&hlG!4gmCBq63m-D8%Gt|;l@0lx zL^Y@G5<*E*^AHF7`}fo~%0bA|a<3{aC6!T7P%zDhw+jQmKaiB3rZvxQ&_jhMxEtWV z&dw(<&5*wQiA_voY#4+DD`^yW9Qti2I2mYBojX?;j;1B8VvO(R4YzRTgW~1F%?cnt zOb7GsUqbESdfz;qot-J!n}7fQtv5eg4ceU{8o9EpEMM-#%1Vx0)XZ1Kn9$pqN<8{+ zp`VW%r<15{yZns9@wss`GfSkjv=XRKUNbO=s!E~a0#3inM@{F1aVP_1fQ-N(`^m5p zcM@fc>GlMHY16rwldw^{lVuaqi?kHD(ZjuaK8xC&mYUj2?YlQ}i7_#M$dvD7;qV>T zY=n2Gg)?;~~7uhe870YIZH5CI8XaCi0$563Rnq@|@z*C!=W(*52c z`0(Kalb|DegV8`-MDy2vVo4HDaE;F*BcB9Q3(ggrJy_=yGBb>#7)lL z_f}T>eE>v0wpWp+6qPp5wzRbD-q@a7LZ&aZkU-$E76R(rPY6WW0P_30iqzGtaVlA= zsBq4SK9Z%K%6za97BfZi1Xm_T2zBq{h2oLnxKM9F)2On#YZje~s+3=r`$y|?>9fqj z!%1@{!Vr*BE3dx4};k70b5Hwh1JKhx%f zQR>n)v7e$VQLbb2*TDM(7Ij+Jp|vy1Pv663BXLQMeIZ&*aUIq>{a>mTciE&egUil* zq*>SRYsM8}0&kL6vKC20SjFCMQE>`8IiC8=qsAp91cHP$qeAMhUq8TzbM~MJCyY#2 zTl{T%rs2!+&{Q|7H!fmg`9rK*L&+U0Z9Y%8Laah`{?ad4d?9*Ga*a_#L59*N>E3=I zCFv#1bs#IONoTtX6D<=I#DOn(u_u6=5D$o3e=+ElvXK=WY*!mVJn=;L&cX#;8-?+s zdBx_$(8}q>DWXp;1+!rZG;W#KqOo-%u(~bkpoHuv8i~3fumwT%*Kyu&SZ+JnvC)0! znqy;Qc2w9*_9wjTl1=B?3PQ#?c{R-wy;}oB=TqufJBfv*+(p--yK2s5ZAY)rr*3J_ z=MdKuX*EuLCKx$fvUU>{b>{%#>%W8wJMS17Wk=a;ZEc+i?WXc23os{C1JJ&bJ4a%` zBs4jLYePgA?$eCjA2l~o^9?!ckZ(a{kWW;Ozr6$Txrh@yqV@`rJ<#v|k$7?49V>>n8Dggn62qhn*~czMZMK-!9` znuLgmmYyEX+#^4K{N(hM6VEr6UC4U<4MpbI!U8sMYmVYF;Mcl@MSp9b!;-`xst7f1 z8u6viENiGvfe*Q)V<<`)IDQvAPd*nTObKp3oRe~UC^@_cxxd$4JfOI{Yp9=}KD{w^ zR?@1-a6CmCS3jMnNH5*2;TD4oT9$rX{??6vIe!7tX5r!C0Pz0(`|YpppTT^Q(!~LK z)`C-CF~U(vu%ZqM1E*lv5s%pekqTT4hZoAlLe2hJ@SJ4WRelQj$EI=geN;%u?^mxm zgfq{Idu_kUE19@Uc|6!8N4&w~a{7A{yBA!El5%~YEQtg%>r2?2!rSAwE5A@lotnu- zK9sf{4j_B=|4~;~9{tv+KU+h`YFL1x-Av`>?X3z-3?i==6^xrz@sZ-OCl?gFafiCO z3213)UENKPr;inUGKRO`olP0n@?nHbIodxVFNW>D;LxJ+G&g>sxYKVhbrRjIWBkJL ztcj}NeyS8c&xmuh=4k*hE4s!cCSsLjhb~)ypm6;m>wVoZ(Jqj+V8Shw|5_P$wRg+R zo!7{&s85+Pg3XuyvzuGvxQrH52D0FbUph-%)l zo(UcMDpP@wYRC1{G8y=S9q&zlJ8KCOjtSg6MgBB((lpXlD|Dcd05NtRjqH)*C0(-G zN_Jd39Tr9dz|nL()A}fznf9T3_UCJfVZt!e`gfl*&j*=>ccPlf;Gcab)1D0CnLoi4 zH}=sIfN|o6m)>(}J@o#O`sd1>tEi5W7IIhoX*t~5Q!6}SAOXkRSn4&0=%;LkD!ib3 z-_2YH$~310b`iKtXOWrI&d=O4wCB(ytA<`?R*xm4exn;M`9&`c7Vqw9@w<`1* zPlD^$UqHv`p~E|bP{Pu8B97P}oG9zQyHGyr-^5R8c$Ol36MTkM%J!JnJ#G?dTIDGT z=O+-fUyA@yX|pp3FZ&PQfPRI6m%vfDrUV?p&(XWeQ7sCEi3qV)7`t%=Y zj-T>}u^Z$?a(jAuMkeaSSOSBB7;K)QM}a&s5(v1F4N(7$*~QdA0G{`GI7P6aFeFzl zek`}ZWzroDT6_ydd1R=FD!`cZ@b>yNaBL_=kV3o0q6_rG<=~G)>hfs~4T(seo}K`f z{sXSja7wYsa(la2DvJk1stTc=JiyG(@r%baJ$i*c$-QhWGj9=We_ujfo#dgexEROt zZcW%|fHW&NH?yp4B-42k$;hp|yd3aU6u$Pw!orhw)us@FABo4_KpO3Ojr$?2u3QiJ zlS%FE4W08dd@%}FnsF&$Uigxj2*(Fs?@U`uOTS9XRWL8Im{8%vw@!}t_j!t>{wx=W zcZ)Fh?xwRbS>ofdfLpe>YldW>ih=@6PEO9Ni+RiAe#rfkA3uHwsp7mga05Kcj;wBP zw}hoZLBSyhO-+5u?dEkjdwtjh69SI%PuN`s-cq$P^PWD*^7_b^9)Z|2IAN|Mb| zECKD4c(Nj?wE3C=Vy48hX@H-yfGdK>qg1+7kx{ z$H>^gOHC{AhX-K8$nGh!JM6y=y@d0h%=3QG`n~|}X z6=8MXchDudaIu+E zy2S-IeU$Fy_$>Jw1favXsU-0pgl%mIk7<1ClfN=G{=~sl{4pNGb6X3Oil8*zzkh!b z#+rUv0tqX3T*BDv{0UT{T#$izm4P8dcmDO7D81#A`oh5Hx{u_F;IquYZ<~XOw|9Ox zu7gAVxiXZgZB+aj2W?{o&s+O^F8C~s>}=+(vtx>Cjbw*y{DKamf+Myr90c|M zR5-%)z}$R1#7xq}4cmBgE3`TK+M1=&v)ps>O6Y;|EgGKpz_1`9Qqz_Jb4W_p-Ep5UCFGv^PI|YE+sslZr3>QYq!(DTPGI%Qp9sFbTm{eq>51zX79&FA`r~PQs;;X5(xdCGJk8&oYv%X2Ef06Fq>09$^z`&Htzyutq+vnvCMPFN%+1dV zoZnc&;>E|Y!S#S6C`x#=>!p>Xpsva^FP9mV#%$x&3hY!7T%R})QRvIa{QL^?3bjuu zQX)8njRL`t#^`-6nBjiX4?@p{R8-vP$Db8<7w+jN6lD|ptD-%aOx*{FKsc(l*K+)a zf|8vYl|99NZz`WJMr$3cv!OiJq*svWZ}V|e%Z-%%F=*7Grmp+4?w}`v?rJ+TjOd(F z(Cv!V4~N2Uch_uoBZ#GWd)$c6e1^5NtIK(iki_@<=V9T8Mh54jk2k4Wox_S8n8gPk zf}7m^v6&*pwUYs~!N`LF=szOT$OzI|pV-kqCrZRyS#ZjcPc$Ns_Rr ze4Tyg%1@J49}+g05)l_?!t1af=QA5ZBdj;db^%)s8yQgo>ltuC?E&WyH+6k&ZT~>c ze(fd(2Ms%`ek-s)TY=`eh20u;R-Qj%q)d^9n)g;I)ocVDxhAM^ z!{wJ|7xvv(XCse$&;93Pwh$G?6I>GOnQEt{Z*JsG@9481z8KP>0Ul2T zF*iX_6}Fw5J-7j+W#1b5f1mnWXR%YrnPNJgquJikK@}`ke7uug%DF}edW4KxTQAD_ z8q4mc%ca6Mcv>kvhd55!$lELj(9s$JvahJDNe2Db*d$;CQ*{$oK)GrnXU5s(k&9 zyl^rQtQ>pBBtUr}7@?!2grAX-L3Hp?({hI+{BS)Ct-gg)J*F>aok3nxng?_iYt;3i zdldrdh{MCp&xVG_{=&BiHH!`up8bXt^PHayhSGjgG*bVQ2L!YOgX%!wanH^!^zL^v z)*}xrfv1hUuH1VC7y1vsdiC?@5xkAYKGM4XOM&Hol7_KJt9yHUiwW_No-|RPkCz4S zv{OMkbvu!VvlR|^u~@9Pum3riDx9inC}y-r2=)afnKi&4a078pVd6~qGjUdrdpF65 zxLG*(Ok(-Z4v&anAq|-soruR2{oiY+8&AEK!G%2m?$qrBV`@+zs?QNyEOsbh&T<~J zzrQy1J+x!7jCcecp=WYg9-cq&v)Sf!-+QRrHP6dF|t^5-HXF%=zPM@*zm)HX|Gfm~ywCpnFxj z882N|c27l0AWT~P_JEYn4j)J}am|*NvjSz%v9e-)PDeL7I@+c<;I=!#@J_VdO6vR4 z016(N_sHKbI_4%K52K*pI)}Ke5)d|Koa&Z5c(S2~rT!e6dgI%rfCwZl-UONvMjxOg z#Ks!uA39Hb=)XQqplQfBUxUHmz8o}`G_8Yid{6Gg_dRrt+<~M1`9B||{9JxN3Kk)b zMDWDi!{HgbFi`7kCUBB+^(!6TAMnt*&`#;*}vde?TlsXfVqeTHiY9Y zVFm^a5Lv55i-I^iONN}vf2hO)`zLPutRFK+l@7?+lK`|luL1U)P!0jSWD;Hp$sd_@ z`8dVjxhgBGFSjqn%_TfYTpOgpS!33%_r1Tn=`gBTZU2E~Vp+3yxi^i6go@4jG4;sO z+aFuh(U{)b4_kD4wxV`s!nXwO0*Hu!vpqJ3JqZ)m$7Z&#qBRkD&X>qI^7Wg9ap7J4 z0yti5Qs;((^*Tz_h=>TUwYAUK)B>a+)-f?LQA*x<+){LO;;KYoO-tw3eYI2(M{fKn zVW0yQ4GFOH{KZLSVpbRMb_0oru0Tw4(wLhhFnom;o7{w(!pL)LH<8s!gd3dUr^XU$ zuM6SGo~^ASAa4(>;FQ&YlroE6=kKrmJO!99&x|HE2Pyrq5$YQV@QM9a3_1W$?$*%0 z4?5;%?Rk+;h5`yk82OerMm(@vt+%H=@ZorJ$iNc7GC}j_<-DfO=(VGQsajqJ+M3Yq zQO6_TV6)%-I2pgxzI&2U z^hapjS>jedsesS_K3%kS!kHifskltaH@)c&ac+)}m6nNAB-a2APLqj+g;b0C-N@o% z$kCCN?~fk{0JC0WKw27YME7P>Bd6sop|)BeTKkBNx~Ee-P6nAN;{F=V3=1%LKn3i-!Y3p49+F+`@mNz& zig>j$ydex4p|9Zb>u9Jvsh^)8)zl5~3_!P=oSP=IbwqKfL zKZ9*WwPjGqA}P{CwQVjCnAW3=j!qH0NeIc?MK|0(cqh6YytvS(WNU!P{XOGpw<1JD zM-JbNg5^0^-o(30KEw0)x;xu0vBSPBg1r3vj@BLoFgk0KS1hSq_);WbX~FoZXvGhg zDljMK6}Yx-;C{=`O*wgAwRKz6Q0~z^jl1^;2TO9HRmq$|by*@UhF3kL{g7sur-*`* zz#Ad`?zp4QsN?*u?sj0|RduCRdT(#7)h&CF{cOa!f&TvD1eF}V}FIy@n_Y!t9sXZt8BSiOx1T%=~ZxAu?*>Fc`Z-<9o$SC z-G^=5bU1RP&!pvTDKgsObR2m!4tIIWS!BQA?t1QjL<=XqtGPUJ@Pb0l$R!g@AgV)NkMY;EA8#l!5>XhS!8&>C&!MAjiP98 zy-cdI=2=t<8VVvAopSC)+WmOnj0{1U17qU+OPlClzjhJ`1kbzWYWUpl4YY%#&oMGe z$7gkZc%~^yNS;Z%PN<=On*Pbtihf1>=1$PwY1}Ixv2tG? z?&aIl}8ZX@V&2?j0S&M|p=a|z@KiBLf+jTk|qBGAX;DczEWYPsX4-BV7CAMWKV%Uq^cD z2@@<)#D~W3*)Em4=^U|=Jf-#p#~wD|*HX)Va~f!4=W-%+l>LBal3-Glw8g@pX;`DPy%HXo)=h) zS7FOV=W$@B7{>UT9NqFlAja%0BrlYs;TBnxXYD7iaPn$zfI4PH|FXK3si%=}8(7)$ zSW0LZUW|wmJsgmM$~ox)x-c-IPwJn+)mqvN$Mm>AP345tdYmRMTYLMP?c@yiJI zr;5NQB7%*kWl1eGIQY7j>oetUkj}VdfBfVxs(sHzdKbluNfT2 z;li4j75k}PmI8V>Lx_hYO_G9Qd+H*lnT zj@P@7#}$QF!AAg~z(V*=dwG7Q+z_psnsQ-b!8~9V3?oQ?ent{d1?#u;-7nhp)Kd1Q zifn4H7-TYkfq{MQJRTL_-*+LUyRNcZu~hsHR*nnSXlCEO5l~PBfeGihe z^osfQ%euF>Hy|Vg1^6d(5fU;}YfUHV#aI5h3)7;_8wKQn%UJ!t9~>M2o|A>@NI-O! zsw)AQA%K+WBPgT_y-j?qV*}csxY>PEq4#NnOYJ+F-$HeVEPO zjE`9OJfNt&{QSDbW66~K;(98+F6Md`i!Dz`{}59|+x zN9fhn>J^xa5pY31 zh6ZWm-tgL-dTLw3^zzOxKQ@;$lWhM_#U5reLgqJN!t1f$1ae{WA3uIPl0pZ-^1*t_ znzAw_)yeLYjecbvo&5_Oe+^;lYa2@K-^e9XJJ~G0$s=pSU|D-3+T=UA(akQ`-552xe>>P+^2jz){JQj)8 zUQ8Mv!HgkDD<*s(v&Cb*hV1@uv%E(Q#W=6I>rQ36qiH$LYv#r$Bl`)KGp>d59|HQ^ z?H*v8`i~xFoWfF4Qhwuix@6JO_vJ5ToxoEv>DL&8Bf3ytun-&oz;&z7I(<1KNmc7+ zFilrX3*8-M&ZWp;!rlG6Y#8^Bxp8T+-J%R+){#l zCEbm75+%WWAqr4!KHJX8&5h*AJejIBV0p1WOKf~YOhTd^$H2fQZ2g6vOTc=9+x5a6 zq$vNeQJrn*({sAAINC7E=f?cYB?BTRCVAsnWs!DTk1@)ZFImr#^i9ttG?)d)7$nUL z%%rg}nE5CXejxkVa*b1ee{1Y-C)!dj zegCvS))ok-ohwm;;8r{rF*2*FsscP`W;A-S3diiUNZF0BLF|PFmJ*GjF()p^u^GZY z61i>sQbz=EX@rVo`5>bC|^}wXwl+Qu6s>?&VqFwl4 z5<%WsLNag*Mz?v&J>Wr4VH!TWo=n3rF7p}BE$;hqgXE1+Z2$=^pkcmaU_MUJwYqCj zf%R}#y>`3vGx3MQ)3c%rL*-D`$e@rANpNY!k+V3GKlx6kdJ4`FTpk96g-NTaJ+<@} zzCH4>_#Q4sXKQ5kVcfJWcscc%`LZF;H>7CU_2TzZp4>}z4ToZfXZLnppxHg@V=P?( z&$yh{Ub8*VS@fJrzQ}Vpq^en=Nf{EM@w7K%!>UqFrQhD(R+^~Jp?I8c(ub-1QC8HYdIw=CO!V6D#~-OWzZVm}#XX zfZ{J}I4d6?IcTS5>b}!i`h6x`XmI3iv4AZt^4M--8x1#$hu5w0Sn0RqV8anvD2t_L zT1}=g>{q%-Ab-L9)ab}at7F3}_^W-~smWHo?49=zDi!vkJee&E_8&7QzhWSzt9YJu zNUMU!H>aqz`fZ37BeV_IUD)M#-*~32NNbk3XuyM5Qj4=T92^|_{oJX5r_U-ICKmU} zA9^s{di9v_oGiGL7KuJ~A(8dBiQ=eq`(U%cwxhbn9gr42x2x%KfH*13LIKMkZ z?HPdSAo*)sCia2;_;AS;#)>K}o!Q*Hv`d*B5b+Qs)SKfI~@cLk4lLfjws7o`vVA&QoYO2*BXiJ>z> zkLxn=IYSTE?(p8SWw%p#1yTf|iy1?`X=@)V8V_em95AmQ506aNkBlnqbcGdfq$2bT z;FV2R1Qsr7pph`pO+>LYUm;HGI_j3rsw*V%c!5=F{8^lzbyC=&w}aLy=9zy`KB=o` z*4LARIT0d+3xi5Mp7*I|G7w%|RPZ?LuuZ14u2<&9ymd|v0^|J^7YG8-;pqg@{RcjS zUF?=5#1@?+>Eh0(gzEkul--@ecDGr$xMH*$9Ntp9Y(E2(UrQWjZtjbLSh zM09b5JhE32-W!#BA%L)E6P+=63#4UbA%ltT#`4#T(kw_Izbr}sQq{gfU_cEnh-M1( zLet{Blz)FdU`3$Vb3BzgFLMscXTMWl3zEC$3mGf;yR1Rbk3^8|1RhVXbG2+jFeLP=Qz(j1SN{&s z-qF8+!bXMNf0IkjUp%vgPeyi=C9+~KAI@}pPz#yAZlMN3Q;Rmk=$OJvqf^iBWK*Au z%nTa;Ph`74dRnMniVDYH_EVnc*|o2kJ9WCK_QbdC^=d|2 z<_Nq9X33S*lp}7Zz(V_yC>ltA?-AT4j1e4TE@8n9V3w)BnEr@i0RJ1Hq}~B@8Au7( zx0lxB1H3PQ{7en$u66zj7ArT&xuWgh_eAm1rJak%KP>%rjM5}+-zT@ZOIesUm+-+~ z&^phjs(KR}y;F34Z+h$mDL6Mhbl^1kyjq(BsifS`z@&_G^HyqZ%b#0G3M;0h`(gORBNfv2%X*dl)fvBU`|QuDhA|2Clh0lFdi-ws&Gvo{G=IL` zq1icSmyh~fZ>X4U!b9>VJX_d29DV^YX-91BeBOC3`V9_?-5J4ghEpj_X`f^cr~(Bt z3_~_dx?1c2jp|U=`dpDk_>^Sh&n%bM8*wQ{dszI&fK6$L_nnqvJd0JEri@Pr-R6jb~F{>jT?< z>N35?=U)2(;h^!fb;GcV&XTLyCN9XGT~l>As_h+Onxc0>3okaiG7y@{T+Ao0qTrUBSs;dGJ8OT~Y8X;AVix zUBknD7VfiCU@2ujd^lh%ys4?l1lK<}*ou}(w{k{p(nAaICj*^ZVr#yh|Y$flste_*xlWIz9)F;L1NRw z#bk#E6oU)_f5vk+eHJBVCHI}Gw<*+jpV+DRmaLSsWUA24G!cu<+=@j}7dls|xj&)n z>y{^Lu~kb&o4yGTR|=@zYW+MoM1Rv50l#jGf-pyqG@*MtxXc`o%uw*wk_%!DKbTI< zz17QZecb-$&6q!k;-%mA6(bNdWbJntvIp=OU^6Y6e5E0Y5)+R^Mn+D(ar@kW$D%lM zg4+1Mg1D9H)uh$B;Eu{$6+MwqDeVaI$ZFoHqR*}=kg@83g%7URU)kFx0! zq@ZxYASp~IrXg(g0SI_ zO3-VjiB7;N2PVduZij~MGC}-sqAH$2Bc}hgJz!^W9Y6j&KVRbNwQDM0N*>|IB8)sHCJIiv(yS#IrzkLvfo~Shx zGrzbE3-@Yf@|mUP#nubTZpV&%h3?$PZsMMHcG<8UDHFeAYc~gOAp_p)E-R!ox|7Ab zVGt%cYuCnFs=5+2Q+l$v7K?u4R}fnika@EShaH>>9^Y6r2hR3Mu%aD3)nhkosCn_r|4+(v*~YZ6;h zeEe$aRxM0kIgqIf6vFH(o6YmXTnAFW(KD@Ti~-;dp%-M_Qx)LQ&C9H^%>0p;%O6@d zu%GqZc4lWPMa= zz<32j%y~iu8eBQG`!mcNty!+UdYAtUjW|WNi3wv;pnt{=I&RpnBdNYrxXQO`%jlbl z(>*v5;S(1|;_>#Tbdxq-B3qbKK%k;$QtgY2L}am3WK(^ktFc$}$^u=ctV2YTO95M5 zaAvSbv5;C|9J;U5hCFvF2ViR*fn&|D7WnDhK5oWWA%BpZW^({$`1hY3ud}TW<(p)u zTpQN|80hJ~y0O>9np~MbzkV0QjC~hSkatl{)6Zy+l)iOUD(o`cQUCbzFEcR)jrpMp zO~o*UQE2jz*U_ut>&q3)iIf8@xFfuq=^>06s=U{XPMN)yB`m$(k}s@=nl1nS)a4*F z>MhY{B4EmL83=A9k%Q5t{D=gU1FjDs6KqK#YR^?0Zq^OG(USs^2bwz!ZJe-fW>)*L zSRmuMaF-iq6EI*xCe5}bAgt};UV&~PgHCA`@AsV2s{E9nKUH*XZj{kx=|T-=*U7^> zT}g~f>rTSbZ{=qge(rkmQ7lxw-omGVqB^f|-s!p4{}~sa1q5IOMIkaX!rwHt{EyE z>)FW+2ww^fJA;BbXWnsj?zwsxbHi!I_2x7l1)j%`laH-tsc>^iZ%wc5yZqSx`NozG zl3++=J$Y=ez35n~7-q$5-|he(bc32(Qnj}X8Hq0weAQ=Qk@!CjoZ;uVIHzR8f9(u_ zry^-zb-ITLw3jewG;uy%L1Y0i2>7UzuM1S20IK&*p0ibr?}ttSOor)WU<4_D$$bVd zx|7Gd=>t5*Gl;;br%zR`MujX@Fvna|@#QkGvJ#x{$y_PL1q|7=p}YE+q|KhVb|;L? z@qwY7=S%Ue^W3Lln*QL;Ei9gaUgwtonpCI*#9XnRZ zs7AeGpYran%y)r0=LH|D#)cS z9i!0huhe~thue*fk3rw_misFM4{r{HXljQQ#c<+P`{88ml zY%$!XzQX|?)Pn}=HCU~t+HGr}ofQ`^Lb4=?xvLFb0i2E>ot-99DW?Qsw27!P>~Y!~E^bEaP1k4j z;u}08@EZQCH*fv4f$wIS!G?>dBczkMlGt@|>jd%;fwH4al{7^#@j7I)`W!^cZtLmj zGy?4pI?Uv)s1t31J{Amxzi;ly3VHRLjWU`_Z8Gsq0t2$2|AXD6JY!!b?Y^Az2pW!Zc%7jQOGby!tc}^y%q@zr`_Cp440eUKmnhRKJRf z74Mx{u3;!wLKvPK0*~U@Fp&kQdYpYKzFxjxM^Eq7>b>B_K2ejlP2SUoy*FoCct0eF zIqKg})b5;(=^AulW(uW`k2*Pdwsqh{+CO?n))(ouE~c|wKLx+OvSNtjg_YZ80UPCE zvZlAnveWhIhy7HnD{0y3qS zTpd5iGZFFrM0W_2p0J@|#fq?9-lZUt4rtOd zpE-v6fqwK}k$1Uzw z+C}T%YQU4`ssxL1p2VlyAt5@{xl}|iK_+X~$PJmi$RmLzbmeIn_yT}wv! zfWVSwf;_X|e>Q%$KW3;VLWAYNe^;Qi?L13WS#L-xb!Eux6c;89D}DD1e5rG#f)dHK zQNgw_O}ItWlXPBDQ;W9@yWXOQ=pBfq7s|dVb4kg?xjiK8RZ0z9L=p-G3D`os;V5@9 zyFp}@lh1qa-376*?VS&;fI=WBk)roKVWVPl4$Y|Xv%ZmX)6UjTXKX<1S=XRh>_6@L z?xE}cGq7;X_ACiO-mRHg;y<3N7|=XgY;ogHPf=%x!|dOrL`0~V|9eemeL!3Y9T*N3U7{#2}vXSTw^^}MlUGBs=va_LHI zU=e|99|?QOz{YD{Pdz}a16$v)Zrs*-H87$6DI1^V0nnE78?r?dFW;8~$4LiqHB9+Z zr&mo`$Iw(T5pS;xrKvx<=oLP*2EvyHJ5+qfd4spaFe(KPB0gdNfV|eW_{O?Tt*nAZ zrrq8rqPmywn&7@O5C=Jc1oao@Tbgk{v`r0UM4-V6;&8g8` zY*TA`*Uq(egHC7veaR~eKhLXO>l4)g2P*|mRIAlXzPh8MYIDrOpLtje!x@hZpLyrV z28Hgoi+z8j+O)uKz)w+7JfChjabg(&9{0JJ4j=zx8o7+yukXU~VmnbmGR1^;FEmp` z-;W6|v8*`#m&DH+38k6KwHV(!>m+=6-_BizjD35d6(jrQ5o`49A|UKbc>r^z?c$Imk51YcnjelMkV8TP7f^2r z@U@qdVC*CX^5m=Y8MGhYLwqeLa@7~Tbi|f1a1)N$`(#xDP`?kKza!gV1+Hu-?Yr}$ ztwLqmY`e&#R=q2Mp*6J*mA0QljAeMGzw#(HB=vjw)tHVe){NW!y`s(xwm z=A&PDKMH7Kb0m}c6nr9zy)45R4d=A)?4dWZ2N&+;Va_y!iulMz)={nw*CSg zy$m%##&(sWWvt(HyX0*>SNEO6!PDJgX(^6PAIlAFir{mnG;+l-o1BzQYE{s>gW*Kb z0V?62lQFDOu}{vv<7yRDZ$FsIJfim#CWF8upCdl}Eun zPvsW^_8s&(z-TMcqgk+JtFVw&GO@?d#Hj7}zycD~^xV@F=4CG*}-wg()XL5<%xKb2A z6_PXqsKW8Z@-UKDxn+&VSS9hRQ~m^w&Ct-0`Khi$MiZ{J+w)eV%x{b0q1;6BpHyaE zPkm>eQ;1s}LpAvVKlz`CSFmn&U!yj0GQVTFBqjBNn}bOZB*^+NS$N=I)dFqFq5(Xq zOXUQatG&T)4e8|{5C9TB+%`5d3UZ7QMH}3?BSvvr6@;65#>#%B%M=A9Hfhg7D8g{*KgUy6B zHdcWr&wF2I#?*qm*G3gGRQy_3dcnlW>2SRUn1;kN zAhvs*TR?ziFSpquXR=XdcwRq{?b6;fo^S7)me+??&&OYf9{6vVEx*X`qfZ%tdJfY= z#*2?_^R_vMSLo_ec!>jReCt(`UFS6?i=JuT(vlzkzLq+14u%K?Ta#s>qOe!{58&Eq{pEOyXQPsPvLVO zkNq!vx!iRP!d9o*-KV}h9wZzzrqDO?Wt}M_aK~VkVDw_SNk*5GU68xm3@YVh%gu$2 zqc!8mfB2rXbY^LRyFC7>NG*qK!Cf!XBb(j?HdL=|MeqpsuU#0(>b&IUn41DbkvAZ{ zeMeiHo`%ZY+Y7AuE&ABBsAcZEI(tW_U$uNJ_=5T~H=WiWdXD^AeZ5jw=bxk`m1zT3 z#bOdHRdxQXqsaI8VWyH<8ESRG^2UnC=hi=RnZwY@yedBE$l;vo3ht*PAv=m@V!E7Z zZ+8EPqaXO|J#3w^5{NmW#QUmdfcBB8^ycTIT!B|X?){McqrBruAK$GzX-+2E5-IC*)G9Mxa_X;&D4pnna}+W+-zefr%s)MpxM?J zMo;Z-f(v{-Ug+FNoz~NYORAGcp8l2taF;>1AQL`h+)U#Y&l>>>?}8S6JOdPRhQz+z zu1NhMa8RNfGND*&#FsNx=-qUU%!Ra22S&F1T|1ux^xP7auI>BXk{GyiE3RM)`w||l-(LXI_hO?C} zcu3ZN`qoHImX^4NAYJX!5nL&?cDW_5If5E4a?&yl_weuljG=$b!tId64^2BeOZ{QU zH7^v&3K z+flTFuI5%NGZnEt{&Zr%UI{&F`0(mTyepWL64E`F<9#lKq!-D3lxNAjJl0WS3a>?a z1#aHWXrt%~mZ$#l2A$uvI!LIcW;g9@jW2B8YLK(`Sf7`9>mBguDh4+E^XFrrRCfL@ z?Cj~&_WL_a0QdZo?4u04Ro3O*9?|2>eA3p;At&fZaIB`pGpA4A^gY#8&yA%ss4wZA zFq+b6cm;G(SiapV4A#EHT6MPJi|FzD_YsEX?g(i4a-Fbw7}W~p;8QklZz1Y3ni$zw zoGCGRdPz zom)-d;dJDM964lI{t&F~rrbUOVf7N(T(>Zs)VektN`ook%csi#;nh?Fu zkng{!lKZDltMj}EQ$xAVSU(zuPpEtCE;*Q-!sF}y=o}?Q3mskZV=3sXB(Vigk1x`S zew3O@2kG$$W5h(HHwbTNHo!=OBhs4x<7JcZ#<$k(hOl~oSgQw=F=si~Ou332G;Xnf?COGPq(%LZB&H;Dffy3*k)+Gg0#ez9pYA0?z zlGlvKzNHPJFrw?Lyf75%w<$sW9n2fa{-Wa^Yw#?fW>te#ZUilb-`(|r04PQJH3Aqq zx7(Qv;^RNXx7l+nO6F0}Qi}38u z-cB~cBP1kilh@Q^Q@epx3)-g$3%t1A^WYLASzYO`*8v0r40tj9u=Wy9>JM`0x~rcO zuMC2Y_ILs-^Arl-anNK>2~UW#3-9IN#gjA;nWg7=7O|ZCzh@JZnc-TaQ`{Fr3Erhg z*iS>ls&p;xicAC1!Bd#Wur>VS%OXf1CJ3Xx0QR{x(pK1Xe!=e`GG}9|Dr9##oT3)E zIu&A^Uce)RVY3&OC$rs&`g8tcRoFV)8~`yy4Cled@m`bDJgxR1;YNkGNlV^HG zeT{l79AtkZ&%YIK~?;fA9p+br;z(k?wb3Js~D zmz0QPMHgNrUoumKRFVp<4{#!ni-B2qNnL$p`i4Z`Q0Mgg3&b9D=#BK~0sO6S1nmlz z!uS_gfC!FF)Iwf1@_7|d)dmh4xnKEUX)j$m2+2ql4cxZk)8l0h%RZ>bN^#s+=%HjanrwQOyUuI=-K(fbQ05ROX zJD{~ZWzmIT@&Ila+00-DyTzx>$1+`OG<3}p_8u7i7+$bxm)u^ zIGwe^0dBmpbUF=yb7yB-V()tC8qh9@HoyJK zc2eHf*fzRWJ?maMIrc)O{&v|_z$Or`rhC8sjj~M4Qp#50A%w9G;R0E?<#*dmI3l&S~zs$ zavXn{X{9DwgIXI)+FVZ6klwENDl?mnMT(zPs%6$3*3`0-iRumA)u?jNTp#5EwFMyH zRIGW*L0b3jo%T~xhrJ7N`v^P`!Q1g+hiH?x{!tmuS{L(h>6grTcH*DF_4%+fG+RLTPQ{Q@>{hUc= zu4eo_Fd(X+zypX?X}(_>{HSwxzEi!_PP{59Dw=KE-rhce%){FMQuoMehGA}e+oouS z9uQo<8$TN{`7msui#$XA=`26*F&32&w7=j|)$Uu*aa$U$#$2mP;CxS^en_onFnEr~ z+7-29W%fuVr-kXgx97Xx0QbSC@!^tEM-b=(!NaNhi{v4u5CVfA+ogrwd-t68zpN$! zD|uRuElbr=jb8G8FWlgnIfMa>wM!&CZUJZ?$>HrLug<|K$HQm!u)lvtwzgh>aOpTr zLLR#hx7-Tfomy(mp;Q#<_?-9Padqn`i9}6SdMMW;H6SWEI;*6~VOt4$cWe`(w!x81 z5s_dh)hR>U72@q!zMFfm)Yg=9R#~^*@{ke^Rl%^+eJN>ZEEz zh*z*uxa~EvIxE^O^377g{_DY*U&RV3(OPr>TKaN9D z5rz?C*bNe(nROn%uo0_dyFj28MKHQMwlGLq|xo*U`OPD>lc1qroH1AcTG z5Qd<z8FUWp+Oq@R$*~cTf(=)UtY_9+@5Wu z4T0iRh1Q(2|9=02TK3!NFAqV=Ms5v@J9!?NQ^Lvs&)7*k{$i@P5=CMtJ$G2ka!_bC zT@M>EFjaDXpzD@Zi^ttYkzJpN$^lIxT~5H~#y=bMTA{AzZ1dAElwg?{cMlfmbx8CM z4oxD;al&kul)~xzf;b8LA5m3s4kEOZx0Q6B9C|+|O2lb2?sVJ`N7FSonUCE!8#CSP z9))#BvT)nW@)LkxsgJKcd^ev^q@#cWt%lj1LyK1lA-&qCy^5_qm1Np%c~LMW6;!Mu#lzQ$$b)`cZ}tSMXHNJPFYhuOEsZdEEf6ZD?y_*Ztw zk`7Z#%O7_#Re3<3YaB!|?`h<-$@qEmAl-&OUjyq+6uZEwkwD7Ki=mpiD4t=XgU4g{ z8MO&EYDBKlFYs{UmI^83W>px}6L(yJ6@+jb#=OucHn7FK=-MN%nnbcKmn-Rvp8U6K zR(FI{(_!nv(3C6A=C@7F^Bc%zDocVbeQ7}f4W=JTka&D|x-Gvz;{|BVHdP>hnyDH` zUu|-5y!8?C95Jlfi2IWel2>!H-~%RLj{Mo6iJDDrs3;w1e%npwX2$uh@ly39LNK*t zl3jufiM-L`=H{mHPE+%0b)Mxp>#G3w2#dV2ZDJ#}myDX)bU7I<@??$NxOuGJH>J|X|uuPZBEV~$n}!wl%g@E2azm5J8u zrsv;GqB0Yz1^?l(&yN&w%3(?`8L!#nX}qpK*9Nnv9#Ayv_VVDAb6^cvU*eKTztVs! zU`-mut(_KnMo}*gC=RTUPuz@#lA=B71SYVY!Ze@)m|z& z#W-QUqw-DJ9beZCz!$9$f!w!v|6DYym1mb3G5fY`L4H9Mvz(N6b(T91OO|y)GB2_ zQdJoRsVl+?FgOJ=7*w{YhIM?aJ(hZ90@w8+JxGqO>gVWBhP5KK(;cu9ShefG`4`)3 z?alY*yI#B32|=uyu>Js5AQM9f@>9zjLix-@;u&g7wsL!_;I3}y7p>_BRZFA+&XZ5j zg~r>yqvzM*BL<%6L}Zx#MdCzMf)3eJ6kU!~Dt)dmxbtQ_SMK%gqo1>wBU6Y(n*Fbr z-Yp>^!AywNx^;_1>3{nr8rjkr#MxrcCxbh7f|tC$Z${Z&UJW&id7{xIwPzm`8l6J;=FVW1_2-s(vFO)905iM^=#$R+~^Fb)~s{1Sf)Uxil!^Yzgi zQ`Ut(wzG%M(TW0XB7gsr0Joizl41=EE>%_4LoIANxyy3u8%FA6q$`d0=&r+m7HblY{M{S-7dwn><2`EI8y^?_=}z+innMD>z~ zM_ScA795|R?h$3L>F(sA$Chkwf{!HF!XFSFu7f6_L0`v2}k`_Jjn4!CK0 z;h*eBQFykz4?DP?-i3?5`d?QN+;eK~GT ztIHKDqH=u6wzi=-%6`uYAXhiZ$J@fBEFGIvwVRaHv;+eT*q*~87P zsfEVE9X#9W9D5xohpDQm{TvwJ`5i)62vxa{w`*+wHX=+t;e^6PSXBbI?imQqcT+*P zmCbEAAhLlTs`Z~UgrW(O*%`8K>Wo()4x79I=rDT2b>d)So85J7(((+s^VM|31mZFa z)vxz$7~T__iZ0)`3+2KG;#xJJBLrN-Ua_SwN{_>F?Z8|d{%2!h{)!iVnJ1V!r+yG+ zNs#+iTl>T|8p|{F>V;qp7}L;=2Bx&6mycBh1RxBj*(dYqEs;~aU8vIULLJ)+Vvi0& zK@%2?Pdc@ZjZufTd~c`0MYvaO70Fo*Qx}i4>`{xq3pp+Hwwc$a9u`sJw`P1de84?7 z7n2DWDGQVl?2-F-*XWindp2C8Y0XwK!$G#1{c0J7??-1tcQ$9w`u(P7{~jM(k5Kw7 zV;;W3#tT94xbE%%ffz>;4uB3@8QA(B;LE2I$F0Yc8boRlN_vv!;oP8s%7uB=L+^}{ zl=X?>Dtp-8NS(X66!Z0S6kj2flGo%Xl}B5rhkJqUlJ?BQi-1P(29Rk=v){aV6JFI> z0^Pf>gxJ;>Qe%Y31VBI}cnR|f9;cf)TUF|;&xc z3u%OaKXf3>LjE+8^c2feoBaYVy@5@^^uE!sAbcI8xQE7LM9x0`Te|i>zG72=j>`OR z>Fm~ZmsxHGWbq;7;A%&s*YBUX5GJ8*etrv?IU@OQ1L^jliYOh`=_tXXLYxh)5(pRc z;v=NqnsVvRk|bwUkw${QV$h~^=%a0RydiIoBIAH-cqb?*$Y7d@u&I1{T8Yz)8T}|u zU$1o_p5u1^l6R|n>s}D{@P0S9Df06XQ>574yQjBni`FAk>>?wPK?9kkTY~4`Vr>G% zKatmOE(V!Ruv|b39^IcX32OY&``=%>R5S1WTbN{h1zo$WXHHy8?ZbWk29Ao;Su~p= z)B+rb^l!Q&5QvS}L`6mARCeaECe{(d*IvXwf6)R)Sg3VGDPgmtB-X zm-l6rJ6qq|p24k8b50_-ty&l>RTjL|;x2{&(X)$McdgPCUyvKNnn4^Z7}aOrRBqBS+lY@BUio`Hs_)_L5t*2nz(9Uc3v-k>p$)f=qO<7tH8OI4M72){OQai`m%>UQz; zTE^~@AD8?eczQ6{t4S%Pd5K;@`&GZVd8+{wu2(q*dA7COnh)ZrVy;CSPT^kl;esg=1sgAdY=csolOljFb#)g zGN@{*2xw6QogJ1Y#z&tQ9ko$bIdz6Xi;C2A=+8?&V6MfQ@c)<=amClNYO9cgR*_~7 z64BJC3EX-1xecqezhANL==m;MG3xkw5KojZ0Y66h+-Sf7ubuCu?KaydsHJUOfNW9* z!3`(disY)?PM5hpR&~VePP)?a%KhzH*U{C25~h1wVB`CRT&zjIb6Ok{{3-@4GS|`H zgF{b}I&g&#ja(FGzul(&knp1Fz7(RbUh_PENUKM22> zB*zFKuA2_M~-Fet61p?OTXoU+jm}A60i!#JlY!|LEN(ge9Oyql+c_@r=UgP_a#CS;ez=j!r&bbLkED#^TF1AMTyF{Jh+1@rHGV2ZgrB zM};y$hpM7OGLsDosD&7m$(;j2a853L+lU8lb=H^IJ4_K_A&Z=w!k*i}8Dr2EQ&`Dd zyJxdrMn>Gg3hC?b7h4W_^5N}U7*J_QUeJ^6E-ogguRatw_v3Fk4umN$9yB*!1<5E7 zEtWGAywtI`tRyN5JA64~cX?B?FTiccm$RjL1A9JlHtS={zBnyR2|_(7oAg?=z|OyM zfnz*8Pk+76$;hE&53U6Pibf^>iP5ha8{Gj4Cl;grQ$@S8WSRA^*(Fn0^4G!&xHx=4 z>#vE{c*dVs;;-$+h+w!G_BS4DMGGJuS)n?4Gryy9=KO1-J;&-t(qs%`8le9eYsRRf zx1F6o{z}&ZARh_HLs?23CsYq%s!lp0ZOUiK zMkXnt%&biukaIVCQ>sFc&?`P^zrwTZ2Al^BG{+ic{$N9Lu~N8MEc1IZkZx zNASizy&yMwUL7OXoS~g?r#2nO>i5Kn*@$Ki=O-nqvqUL)^}G>iWfBTUzEwOw??9Gp zTJ+UKyx68)v6B!VEG;?ty^8J16H2JG<>ql@sHpxGG~+j+V0EE9uVDU?e>X2 z0mWX|ulpyEkN4qfwS4+|9X=a^0jkH6Q)+hq9TM&Y81p##v?zGFlBhq(Db2|pve+20 z6ZA%>U!c0U;Aa-#8411mFW5%)X>;nW-gm~6PZ+q0+P_P(X^qGBzD74cXfCOXuIxqr zoooR!e$d6xniFr5T`WVk?G_7~lZ<>r_x{rudYyq)0;MZgl4^MJ)<-E(+6=lV`bbor o#!I_-_4t7y)4TflihacY0*mK`{{R30 literal 32093 zcmb5V1yCJv^DTIBcXvzB;KAJq2@ss%7Ti6!Ly(}s-QC??g1fsr1i#o0`M!VEzE@lO zc2gC&%-s2TpFVxM=jT^BDHKFPL=Xss@=01;5d?zBeESa%3tTzjtoa54L9x0it2>H+ zcQCX!vvoAHu?B%$Q_B)$ZMIm@gT^lyN^ct%LnEuXm_n=rm6wV&PdV&kJ{j2ZPcBgJ zuAftUtu`;B!9j$h6kzu<;ZOfr(YJNxbwe9}JZlSQghR-R*T9vtnW>P((5Llv-Ha>i4oWgIhTcBb)alXvW%^Eg$;5~ifgc}b9>ph_F@ljM!&=HBwG>35_zj~x z1eb4GOvrYSfRT~#S3{;am9aZ)Avb##`FFOt=08TltPF`z;e6zbJc?Y^24B~LwiW1d zp{ql&PTeQWe$tsAf)g|QZP$1k4|i8O@5Bj0h?4fh%Y+CXlF>A!sz3SAwpN^T@|nfW zRY!`rN?W(e_)31UCf=!++}+GIiz6`NDF{?qA$5lSkya&Ik))g|-9NkU1DP}0krSRd zar{BkQ~l}KI%+0kJ7;HHSvHGnAA_@P>@#MT ziSN+gwlSFg^H^;^lqYm){X?=uO(YX$_i58RXPJGWWo68)n!KgJ>7%+ZE4m_B2WPj4 zmg8_C!5#>aoG-V(j~6uizxU3SvV-3{GoFzq7&Pgiyh5}cOWDTHF0p|?$1_KR8+=*Z|y6hY{I@ZyLvts9dckBVUW{C`X4_{1CXy#G6!15+v` zPw2)iPz%Gs=%=V~5yV=bCxjCJ8D5!Vz@4w?@+yx&1a6a)se2zrn(tT=ET zACdqaxUUZn6(I=Hr4SOzP--3x#bNkj-azHKo-MSmD@%&s9*@`EK@NraRb8Ey&&t}m zd|)}c-DVT%;jR~XW%JL6zkmN?pI2mNcIIqTz_XDm2Jk7rj_XQ9Gs3xOgtim zl9rYhdUyQ!fr}FI&-nO$K>k48T#pgyhljLLhq4>>8vUHT0nuw_T1d=`vzGI%=ezZR zmh<+onHgn}u&QeO4tAwV+s@t|{o1c<0Vz{nA}(uWctpgb!=od_!J#1qE6Mg4Z(~?R zm=3Mp!&M3Hp`oD-wWiw zx749e;}&3t=Sj{|fH*Kcvs-9T4^H~5uTLRIy5g@ifMz&wM&)WCLb)~KVgQWees?%> zOZpRx^NFAzoQbUD-*BE*2nA?y5GDpXdq!Lwwrt>^;o&NyAo0u8k8QrnLm08i)O>wWXlq1WM^oSK8;O^v0cN(S)E`_g1e%w z`7w;Kv%5H_$tPtnaE2E3`*$EoU!S_*CGLWhlDM~2HKO%e>knx;IZ5H;_t%NRW|Ydn zx?3&R^Jr(p#|JTL)(@_&`@tYhEG`zg@v))_aHF1*Xg}RmPFx+F!8SKH-=Ck7{Ddc7 z=wpV`<2tw0l-%fKT5%W`xPM%KJ*$jJ_VD;SL{r=_Eu&lV^ce#p`bH463x2nv)W1j z`q}fhj|ZM)#dj!a2tUb`Jt=@lqwqHYHK;qg;OE83fzynf)c}Rmg zxXEEZIqr+Vs+_co3zr|H{8h%;nRN@W*^S6PtDIx?IOjbCL)#T}$!^VQxL}Pv-B37E zR}c>mj{p+x2VpfeH4w;){v)x=Fy04spVZXUbl|qIqSWb)n)}+$Rylq6XpN(yZP|^r z(-#PT3_={e2Jc(#MsGW4=mj^3^2JJwiuPLw9nVv!_K5ulJRMOH5r{do(qBXhDP$j7E z@&$5N9(;_~bt4_vd3kxy5-!8mg;Xnf2oa81LU*+UbEy#{A&ZLU} zjKq4FI=%EsOYoL2`Q&~HRf!(z!e+tOXT4n)%dt*OP*$E@Qy+E_hev4l`33$OjvpJa zuj`7?@qBY!SZ=X}aJBzl1 ztBiXjwYWQ!oL^?6v{}z6v|(0`iNNGq&V7vq$a89`-b3(%xMkd&xaN!0@A7MFvCYiP zK8V`!ot}Ql1Wt3u^Ro{B>k69VP>Q+~qNd;(1k%KcEMTGnOL7dJdECPtQDr}Vcm(_M z#8O`lyO8qrkIVl6n^~?jvg#ep6v+)y1DJHZ?RQ|4OUHc4!PD=!izZDr1Uc7PvNpo7I(L| zkCx^>FG>#47Gw=WPPlt z+-6}Pr{bHLp+-#S936N4Rp3x>CX_gJ);N_ac^YO-OV_kU02bPO956K~&;@J_u=H=| znABL>pa+8}hJ9v7qU4G>AjwBd%r?l@J?oovSGul&l1rtdmb^gYoEtEUbgsN2W+6n7 zbKABvHXaoRhl<@kd=tKzU>i6nNxq_8e{Z^^g8nrIcBi=cO9lL(>6+JZhjuv^3^MGz zlFglVh;3TSv-Ikw%wflE<+H1y{Y~KV&%0w3Pc`Yo8Y0*r?kNm$rWlNf8fmFd(7C%e zY7Q@f@Up_?6phOXd{8m~K-pKfGEH?m=KFL>r`vCDE+S9`8yIbU!Nwhf0DaI+g^K;b z^4Bc`VhSr~L@LuJ=ee20W5YsPx*3r%WvRmJ4ZHWhyq6_c-2N4R0yo&hA ze$%=8S^8W)T`(s*TeM1Wxk3SKeK@x1sU3wo%e{P2OsD*a**c*Wt(uMaoMT}1E5gZT@{7ljfW>L zgGk1B-RG*QEBn%?k|#PN$ty!izFEcBL$puEQjT(f=6&y9T01WI_#reb>~zUx$NKR+ z@|6K_En7obn4a(ru(|!xx%JW0D4NJE?9M9OW_4+m6OPVY$HjaM3|hTPn{H~`KRz8Y zKdtXq9`1JxP(3_^UXu-t4+Jx)UR%55TwKMsCqK1x6JbQf&+Cpp;88ZLnr!?g)C$9A zVkm2&=MHMY_zJkIhaV}o7|5-PRPLJfC?X&o!tjroH!-Ew3yQQHWb*Y6s;<1BX@Ugc zD42}Y-CP1A;{+L=ejgz@J>J{J_`MD@CvlxI z+5%+~(Bl##pVw34iIoijj)hAP-HPg1A+q?Z$X^j+M%{xFwok&wqLJGf z4OVGEYPjje|JfcqP0y{%g)E>CgWNLxop~c>8kXFJ=a50llynO~K;bh=5}tdFm)!$C zO`3+)pLrOPOul8fvnu=06mV`7+RWd-e+OBjv<$IZj+G(a1~!gAL{14G8gl-Y%Y3^q#+iuFI$D#k&%^kU^2t zidrl9nC*yIyI|Mk_8oD%7bXRjozc1dQ8C>*JK!V@vzw zz2eKM`_CWy9yoY-RIIED&KjVnD}M9(_wb!V3{8)~VSFGa8kUKihiO^%_MYb=)cw<; zI$#ixukc9ogyqH;2WmSXTRH9MI3|i<-qkHJWEGt*e8zf#lMn_7bO6Oy=>LU58~x|% z|1-V*-)E@^p@2O{Q|0SS`Y0C-t{M;cJesy)m|nGyZaBG`24-_u3KzjB4DIU zVHqruXS_>koBn!2-DJEWdyX$SXm6e1y5-_|Jy1c#_TR9ciOr!X;r+d-&W>-jY|Ii z-}F<{k(NS-&cXq9H`O(%;5?5a+!r~79KPc%xMBG4!BIUuC1p4o;ekvUMhZPZH!34z ze0O&j0<=VAaXN>Ciz_238DJv@j3Zzj0~gEWngX3rSj84v`KoC&568oH=m#04*&saUptX>HM@F-mxGn1YhXfvv`^aBtT`J#;G zz&PxWanL0ZMog-NYaGPBg_@v+c2B+nBNL94!52JzeAY>Ts5743^x>Acvo4*>3XwMF9G`?!gY)xWC+nM`(rznOask zjh->5q1Uo#=iJD?fB*g|;mD@_hs0SBg3HP!gM2{WN3VxGODoBd=Q|5GWT2_aXy9-# zCbAj|fIM#RI<~Xi&lK92H*Ym>Ph*{GI;|yrh`0#NF|3*Ij00E0A-Jq-`9&Jhc(^Pj z_tzI$Wm7mKUIn?2-q{GBxDV+vL2XunKqa%qL;i)DSAQD;3a7tcWtgb@b;E%x*>lXt zBM=zQLspH`+i(K8A_EUPXqzbPf|iJIIJk_;zdF62nlICH}6ZesX(TNqDI2t<3}SdOE!XTJQlV;ID|nZL~LrVV4=S^wBEKepU4qg zDM-#a$Z9!2P@)k6+-dqMF_KA9s$fAg;pg8#j{_`BnXw5yOY@lU~36X_Tpiyf1?sn+u8jJDh|_izv}(HIpWGm zhnbSecr)CLJ%FWN?vAN?G}YilQ)v)?DFnKg)A*HH^__)K6V~uyix|YUhO>jvZYsEC z+Ow>X9uNL!+v8Uor9+9SN#Sa`k04mVU=O_{VQG8 z_)@_1FK#OVHcDDr;T9M@3aYBG7W>j5&MW;ZQ2-mrNekmHv;iPs6@0ljOgQ#zVqMRO zOuMjx)hXJPg$F5)76HKxh(R(tr=67gO3#aAQz#1J0sloy`thm?s~yh$hV$6!X5)jV z6EVnlvGVXcsNVEvUV@tw*QVy%7tavwbk9Oh#|Px@Nr&a z;N-o3=b?kV#b8AY2uU&szKgzvEDSQ`9_zGNe}FG510f4p1RI6GUwN@hbm&bk7A&@} zuT_B8yhEAsE(SbdB#{n?XD0a9-W)l2zz$Oz*7>D@JF3k1W&gd?bN+T@{SJr<%l!-m zHVSEofyT37BbR(=!4$x>XR`nJ^eUi9h`ccfMP(^r2Gvp)1)?_%E(@11G#Gf61-iox z^j}bhy$dd;sNB|l6({w|9eYYiN zPF>wB6N;uWXUfBO4ID|zXPZ%Dhajx~{2BvG?q^(c{4)|V8UcYctk*?N4UMR%D7}W# z=4Qg^=xFER5#ySHz^@fA4V2HwG+^h$5#V`Au=6nTpwQuQro4)6z&O=Sd(q1aVbtKD zw6dBS--oO0mxkHdS%R(aIx}3nuelYzf&}QBH7wgh!@~~E*sr9jx>uQAcFfEy!S8lWtGiH8P|)&W z<9Dt~W@OE1uX;_zO_rhSG*LwiW?{UtsY2Mn+(8iU&hlR2hiBfS`)aW0OgFOSOy zre9#uRTQ&}yuOSYi@#rkb@;=dV5T|TkoE8+G|Byhz<3kU{?h#B+yvp+GXN%R$7sL} zL`Z4*qr<~B>=bGh!RHK;@1OjKeL2W2X35)}kHbQzEXrPirp0c6h6svnu5acQb!+y0 z-iTc8Y`gN2ka6XU66`TivUeFB14GZRRjIE4qyT37QUkboKw*9Rb8E|B=%BE&a$<9P zoLInZruXcf$#^>B<1bDD0fD!Pptk*1KH6^G#a3n3iByO+NX;kVpo7h!?%M#aO-)Z{ z<-K5l7J*+p zN~e@LKpdAa>-y4LuHDj}CgASe4}55y+x{~62jz36+ofCSN@Xwnk5bO0%9!oSC8IA^ zM}3|)hP~khc6RH_K?gQZmW=kK8u6F2L1kkxMj$Z3qzN?^=~iR-tlXUZ83%QfWbQYj zD1|+$39jq0b=oV81EQGM+S-qni`5d&U>GFa%$l0%L$|r0p74A?KL&Kd7&Du6UM!q8 zifCn%faYdiWCAwv+bWDRJC*1DxnlyDreZI{lfoF3rZjZ_XlW(I%z+j6w*JJ`&Z&h~98XKb2S`D~ z!8y=Vk{5WxZq^8mXyx)^u=r!kE{Ort3;VT{6E!L`5 zR@j6Rrt&Q(4KjH*H{Joa&ZaQO_)%}MtE=er^sy>Z+cV0v{gh~i=&-ASbrTSg{ItJ($d_W*;&5rJrr0k1PqL%@y*x1>5XI9KEuAq1V9k# zAq8d3DXJwvmCH5a+AHs8vAQ}N=mlU@xQ=H>K3Bbvb;^h6(+YsR#q@C_n9(M<>>JC-k0Qnw1HpxULwAq;?@q^)p0abRdHWa(LnriqsAEs>?iK}f*T2gJ`T4vj%dtAPW8njfQB)d4(UryW+#5Lz&jA6@+Sl3?zd~Be znE(6ZdL{wO^QefK1{{|o4=aBEuDd=B0El3wLT&H`jAguKt)jr zc?o=2y&k2zdb>F?kjf^1cXeLMELj>i;OMt7;?ixpYJ~}e@`XMR`siCR)a2iJ# zy;3Zw2JSwsoik}{L7LZGU)6401D`GVT+hLsRQTR&xQgkzqV&#-{(5s04uD963Ic*0 zeKs^n9UW3Y6!dBv;!pH`kqQMSoJlHtl*YNOz=j=pF}`o@`os9+$tvwuNC3qXRdq3| zNuZC=;jmTk#AjV=z5pGt{j%@%6x@zBl)%ld7L*#;NH}0`gqfDb3fRrwQz17B&YXn> zbx`NBO-BU4tW?CVDrrUef8ji0RsAp-&eIvmGfH&RozvxfMFIWtkEz~uJFc0m>{GF` zY&zTTaQSFyr$S8hK4q-K!;_6%6fZ7uJm&r9#@=3WFT@46@=s3GAZu|+&^<=Yq8BQe zV0fGR9bjUh43EDEw`Z$J!k#qHw*?sOP!d|ReYUFK_YvAl#}WB+uKOy!Uw|L*+Twl3 zI_!a#yKUzxbZy>}Wx((84n+zE1|-0A@Lls@huHTn%#toE%V(kV+3~u>^0h=ne0M&d z#9@+>C zp>CQC4@l5Li%W%eZEhU3$Zx+Ap=@-tiK@AoDz2rYJ(C$HI=cM@Tuy24JzD@Da)AH@xJ_64?Zl1ut{@n(kYtf_QE$4fmT$pHNV@oOv8Olc$Av45LSG*K{nm0*>xtNmNMSvo_IPx9v=M&r_?7NR?b91UMd1|5yZ2B5( zQ~(tgMf?UE2Y_W0A+Ap22R62;u|%ylci@KKK}X?P06B5IX5$x|@bVWbU{l7y&{^-R zQKY%|A}?0a&!)_MCuhBL<-yP2GROm-{w8$nyrF)qYq7CzHOc|N3D&D0-hiuYs=4Rj zNC=qlOQ}4%TXr#`oGFX_1lUYFr}$Mm4-kQG1IU3vMrIR2Kv*WvEfo(z0?>>Z zcdnb$lf@c#=hLP4!#)6yVE;ub5Xx%U@2bpbVst}x80+OduZF~Mzi2VXh>Nr@i^ZbR zQGrE5a(XGK>>?UcwD{p$-5fxjBqpPY!;4?APOt#~w%NKH*W

SGo$O#M~Y*{4#@` zTToy@5t$de{^@vGkmr11WI^3lMIrKIwf6-&X0LsEU62T}6)D^^5L z#)RVf!SQ;<&2LJk`^OY7Z@tr{x>Va@+&)-k@QYI7^8y(=(;46Uw2ju$#A_DH_mg;H z$44D?n!3tyIu_6C^sUDe8Xa{WDOq4iwbxr0Pc?3a`|a&*SbfIT)!AC^)L z4;8?R63ntOZNz{<$Wgt^yHw^bN z^?jDbGmlFS0O$g0Wv5aFmuGDsC9I{q7G88r_CG}kfxY2>yD>n(`hUXhHO$U8C3X5d znVLjbM5dy+h2v?X>fItLr=q5=jz7P)W?ilR!9yiNRUt&<`GUiuv3_^>QT&GycDi$i zG3{ZHl}yJgm)2=I2lq|iupAPRDtAQVD_3&L7(lnMo%|+}e-p*)-E7^cH|hVx_^WQk zrvH9Gziue;b?pBi-D(RT96Yk2kXcfvXJCL3p2o-!m=$W%gV?I$Cl}=imFhwLNzk_r z^VxF&+#XVL#Km(g(5G^fl6sTARScFLbCc&@_MqKv?fcZVJPd5f8?Pdy_#x_GY}}8* zW%ldZD^)@|T~GX`0bfl;TLwe&-P(lwQgxrTPK2Poysd5Jz~k3vURdLgTanBFsX?t- zEdBP5TBUFAk7MmzLa~9vcV3O-&)T|b`8jp%iqg7#p14k?eT{b8t;ODMU6Ajr7X9e* z@}Bth`K#AL%(<|oZJ23sPr1bwwAI3dK<=oYjF*thUax_0g!mYO%Um&h_%{8`4Yy8w zl9%6CM{8WPU0u8KP>N*&%apf~g2^&yK^v`Q5v$1j{1ozd&s1%I+|*>k1r_VW`&#Ed z2eMt8>$is8GG?0p;tjAEV$hc~UK|kr+0qBj^xIqKgaJA!A+urJRGrGsLzm6!Tt>~# zGOeE>@`57ARfa6hjDs1v(s#PAH@Yj{FZ>ET z{5l*)Mn>nyLk1EI&>eLy*Vz|oo0X&}(#osTdaOZc&+Ekp=XnI9YQeux54Vyu=&BcF z{I2Lq1#-Iu=Fy?9T1k;K01fQ{I=2Ij#8N{D8VJ6Ob^4~?>Bp}4$6a!ZsiXgV1zGad zXS5rLOA?~#m0p6@j!*ZHd0)Y4-uhi=pfEh<{vZ^h`|j7LhpW(Ra{2Iqw07m(9=+oL zaQFt0!-AkgOorrp;H`z6C#Hc~b4*hp}6?RO+# z;8{4ry)+q})gDbnqY~h8q1V(JjWX0>F;P)H&Xnk+q{DfxF%2Lz@dqqbI*s`~cP+%v zbuLP;sIt7gK(e1|Ps;ojchPLjm-s5?$kMKsKve7;6dM)QNfe`l5no9%NZ?lc3V*X2 z5s)eM82NR5RT}=^g|swpV;RZ+{?NZ^P<(bep0g|6z^gHvrVjROVk6J%&j}Pf{z@M1 zs!oIkT2!$j^SY;S8D?ydF6aC4H}|Cbw)ZC%zMu!Uxw(0&oLZU2cgUv(l!LN{wXLn~ zZT%|sOf%?rK?K3J=;Eq*@#KVfUyA?89d}^__V;`#Xl@2;)@zxHyNSANuGv6gQnkWL zY9VcMuxx2G7Qd+aDQ_~XT(BFDBS@r_r`FHwN|4-vf_; z00DaU{(X{MhM<)RGS|9CO{pibpa(t$1qHs47k_ecGO&uL?E?b?IYmVX8Qw2Ecb!mZ z_g3P0D$qMqJ^|+>7=+P{R>4^Xmm!~|r3dv$NPwMW>&1v(`^pz^seN`xXzGB%X|-ge z(P&FCu=m^Y_~)f*RtB(l8j}{HC03E}n!o|E>(WtF>?ZoP;1Op~r(t(AL#JM*T3cVg z84fC58POs$9 zZG3wpeMm&iDWj*!Y=z^?^DdTk@MkL|3z6VfvvJyw9#Lt^9;C{Oi zEk$~1VHiDJtWwe#6@?CT-p;Flf{KCu2!Rw4f^#-GIca+Iob$6}@0ycTZJ?mf>-Q0J z%4<*-7*H+j)lXB#4njWnr6Pa;;0SvNmcFogmXROkz2gC zl66DYdr-dek2a98jJe`#2n}H2;~z}kmZB61Woj~Wn@FpS4t3$Z&;mkLc}PgeL@w9T zZw586#E$|MX6{AU-Y5%kBYxnfXM#$Js$F{RD~KLBWOF2B&=nv$@H~a2BT_4p;{9TP zwnp2vJ-PFr>l}q%WN%`Zi0l6pp8Yq)Q)mvwYrEmIC3rQRFMF(HB_T5|qB|@EsAL7S zXF;ADoe*b#elt{08Jn1Fr`WW2MNx=-Ra4t<2(*=#M}q@FKtND;I-^$C)O@$nR94=( z19DS-6HpQu=nSqEx*gUHttBN$tE;O|cL4r@>bqS|7ODmZ2Za?BqG5xNwG%IU`}!b2 zf=lgbNGM2RQto_$Pa9AT%epOIt2S48 zYVPWK`}^tJAy_ps$gjnnp?gQ9`04A}i%UuX>$$j@*WF%!IbHt>42lcGC*TqU67A`> zy<2t3X=x!!VAhq?OewizfGm(t>!yknL%JE7{p8TBrV2CF{}VXbexx7OtyYR!aduGxqjhI!!(OE?`6XCny%Ku$CwsXFmLv<6 zC&zh!mzA*O-m>aFe)@^SplaK*y$u1{3xV&w8!PEDsLHIn>o4m!*aR5<>Wji-i{NIe zl{;nQ4(p{f0f}Ef!#vAgz6i+2MNpvcM^6A}`~62e-a;%YtRV6%C-NYaFc{Dd^D{!h zOaKu5H%JqN(;Pne0x2gfhJbIIMfvEsIPFoI_W3aat;?>4p$=u?Gcuz3s8P zzry?7oILS17fBSN5C#$fP-hAnXoX!sqzYluzmWdnP?kR=i-$BiP+p__{ZQQDnB#;#a^gLr zfr^cQ7QCN7BnFX{#jy#j^87^jK?tdY0y;sIXmd*okhq~_u$q0i0+S+d;-q{0{gf); zjyqi-uhx3{^8CnZJc18gh`&aN`~>X5UkB9yR77DDu3%tVAraMWGOcynyxAjQ+(Td+ zHbk9BU<0AI+~zsNB~$cK(Ilh>RB9VsC@DX}3n!dBM?=uPV_}K%MwK32CEx5gS?|cW zM(9c8x(YR0eszf-mL~K4RU%MWRD*L}b~=xNCxE^;0dWsrreAgI*=@b7r}I9PZ>&|w zI%sx7ak5gIm~|kTZ!V``VXSV_MdO^!bQ(my-mcqO5FM z$1wY3aLY{nYCLcA%T;U`@3__`P00JmMYDnQBbd8Yc4{{ zzrF~gycoZFcm65|hGpSnkA?Ele!ujLx)RN^od2zQ*ge@3WfZya%^!}Zg~8R^NCAa) zxJ+6hWX}gu8mDWF9f{9jLm<>wpl9pJ^f=T($pOM}U2&glGts-gBvcF@!VL|_gscB&r*!}LzNnKT2`_vv?Kj*3fW-Z(U zAN#@eS3c~u@HxJ@t|2&d_ z=_yd$6Fw$1>2etgQP>2A1mJfIXSSwenL;TDGK9_Y0Pi*4xk%L zVzBQF)IK4QZAJqLK9K`Bpnm-xB7)IZ>x&WBDmsQ|=zj{`&A88~&KBg=Y>DqM8Vm;t zoYx}+IU%KGWU`MpC;-l}X=uA5wK5p3YnR9KXs3CPZe+~VTeBWd#qL01jYQ@*mHLd& z^Ou2*66%wT%$CRI`_vcI2%vIB5PHC~_dD?2=E?ER`U{Fg)n>%~u|+qXbiM|tX&E&L zvy!il^SV{nE9VM|)j!#jyiRV4n;ILrKV6lSmEHWQ!Y`8F%OL@ZeFD%}&6PjO$Z)H_f*N4fCcoi?g5r0 zFH3rJxAYc^VH;T$6*9XgmuY(?m0773ZA~u=dJVltRFB;o^G2X^>u2!I8_5qsCV&JL zmXwIe%A%;2YYiQe1mYJlhkNnz@?uAXh;oYpVpcbr`lTX7!mC?)R@(-kJ`S%sPRk~8 zS`mUa3WT2NBqK>tK-?~8#A`qHNkE-|5nTX<_uFtn_rCc97PW%pX2LV=WC^>lNP%e{5jHEXK7zxdcSyxn>GBdWU7a%cjgD|?d>kAEwkS6=}M zu=Ka*uej&04~)oRWF@o_ief-Xp@7TdX@lX_-YBS3&GRP@u%@7mpET*6LNAwSAHG$K z#~$m~3T~JRODcE${{7pIj*c!QEDQ=HE+zFA2k|+dTny7nS3$f@AuK#xTulwHyQk+= zN7nNh?BoHwfMFyWU>&~J6pJJ;KTx-43>`@t;p?X`-)*=q4*(*=><#{-8>svSGD;mG_ zw6AlSgqrD(8ORkO0BN>(C`*_M22n9F2#{fa_~bP&e%Uz^Y;ShP!GS4YTb5(aYBG}TsI})u6~@i$udo|Ts1ik`MomT zQzfwJ6UHTfH8Z1|nwml^DrPT$a3q9Fj~Hob;el}0<9d2>(syFwYi(_9 zCcytmNJy|@Fp_(U*I*?jC|Cs3BfXl52+{G0!p4f}wJa=qXN&2zv&mI&I9d2HL?(ye zk$*yf9P7TJW0OXfpwQTswGp1yJ>p1+oVPy0G??7UwLb5?CWAH(C4~09`0o(jy$kPj zKey`Mj%0?`3o`}jy}sBeDE`IiSkWfTdeCZi{5j7kWG8H=vSO0q*$))3Qtac&Z)GsI z`TkwVat`zYU}7wdFIe{#Jm38En)H(4kltI`@q$cck?$(Ijz^hUUCmaWmj{C;cux+{ z{d(LtcfnEQrDP%KGwQQK@%?KkRVI+`2d1mn=>u_acqjtEJK0~I7H1S+UtbxQqC{_O z!67HDQwY$uHp1KIu(_}d@|lG-3hzP3V3)<|CYI5d#k1_m|&{}^z{=)688Sg6`o0&V0FQgE%OLT&_Ya(~Xrdw|!E zmIuxOAdTGb_5`EtM}Cr5-!Y79SEw|v*KTpP1H>Le`9v6U*2VtIskrUy_oN zh*J_|a*9zx1UvvCConM)-_g-gZz59!s1g?c{5h>X+ZPq{_3j^8kZcH+9wP`wN$zT0-x8_nFV;ysVO`bzxt&t#ViHW)XEmX zFVuYlLzL(nl7Kw3alTk1l|b7o?Wr5$bKM<#0B1`A(NvtQL=3^|@U6v}k;`&{#8w*FE1NaHN&PFxv};RlziCR(cHQN+&1>IP_%aL2PW(u zSp2dFwwHc8&{q6pp*TR$z7fcK>V<%YK@r_oDS7N=LdSdQriHd$`z*^4K6gG0Bs`0k zmy=^fWCmp@bgPl7QGaUdVG@Re(=2A14!_nw&+^A4u*%PX2KQ|I54=nkE z}{{t&f?<=&&v0nl*SKvbM93YXQiO`i;bjEDxOq2+=x>-UoW+Wu$R=B47(5rtxz z-d+v|kOt`oUUa%YABZHoJ7TBPY_RTQ;CnG{7`fhP^ZA8l+I)<7W@BVxlEPmWq~yO& zFmY1wYQzifb6BYz3DzfMK~Ia=M;G+K9Q%DLCbs&0#7kpc@*d}SjpO;SPs>_$$`%@A zde#_vKgdE{aw=@`nO*f@1%7?~YMrd{svPd)dO;U6HopdEeYZTtlcAK-z4%z(Rv=)XKAJ%1Gx+M;m7*Ld%QCC)XAuzzp-~=P=K= z<;SL{CqZ?`yiA%rT9%~}^K}-c=gns@PJg_0P1esyo;(2m1=73Kc7Ol@0!_Zf7tkMrlG=y-QB zqriijHHtCN@%;)fL=HllVX{W|6}OP(yZ`EyZKA&~GlX6QO!Y=vDn3#URgX(4JPCMjJGd{`7Et9J{!I>BOA>m|^ z8$s-*hfQ0vhVUqaAqNwB*Kgu2)uO^NGd~YX zAl239nVJf#BB#m6E z?EzSpb^zF`%A|?VC9h*ZO$I=S+PK#46 z@+oD8eoxTiDKp=r2sX~C&)mssO9Jptm4hp+$@Rgcdb1-PNN=n6Cy>l$ZUElb9E})E z^6F!L^*{FkftH=0P;fe)(8_ip7AP|ju&DKb^ns^aFO1D*f{HD&4Kg2<#9Fh9EX-%` z?r+J6EvfuT_w7gK?ND@1VB-tD12HqSsNKlR3 zx7Rw{9>4XEIl9sM3ixQiL7`(}idqR13RmnNIBY_Hrp(9KrhQA}FULap)awSE&{z81 zSTJ&^Pi-JjKZ%^b`$whae0P^7YRZC_jt=YoyxW-!gt{KMz)PcUdpH$w#9OxqwV)H2 z24v0gPV5^d|A4~hOujO6TfG&n`!516Zu&EGTW{I7njj($H_GBM5~~OCf4s($D zUC{iuPWECs8vRXDe+~LqTKaz|qy1MyD%uOY?^^H}cH{N>xX$NUU(#{#c;X;zF<(Br z1N}j>{>vw;M$om+ryACi*%BZh zfUveW0bCX210-j#KpRY}OLZ1Jc|xKgv>d0#<_n-Te-s zqnd7)g9&}pI`h}$9}dzWo%Kqb$Q2hj!KYy^)Z@pLc6k8aU;PaX4LLYDd7mb<@(hJU zbFKxlm=BJD_d*}Po81h0i-|!Qk0uAMwzyEy(7*xjaEn`7mTE5r1;Kied}ff#Q6;-r zKR&ksmtKrMC0KF9km~~NIhUZGZ`Nzay z$_|uZqW+c17zG6P*PRGy5IQTTxO2r^wFx%qsVH zYMy*hn1F1Ys?%O9fvx*LwE(GH#GE+EkrUx;?Cjce%f%dpfIJ5hE=a+m;Yt(gLR8t1 z>?)Sf-~gB3GH|8QfB`01eXX6R6gr^}+PFTPMm2k@ACadbr;vPp`PMali$_cx4pdYH zABbA>a-<4+5(4ptvxXvg%PJ-&M%kkJ7J;L+*0p`-mYFdf4b-UafFNd&(^fvNH*1Zy zmb9tjY4Wg-Qdn3Rf+fWXyo4zwu(-HLZDg`t8(;^)*`uGoQ}j^z!^E4Z=`gPQMGJIt zRz8!jBnBvelvGsTaXLSg#lv6aN$@s>AmQc>*V2L@02y7l+Rf_jY&FKLuJeG%XKYNa zwyy4SJxyB^XymK5_Gky#4FFzlhrRIOYoI2*_i}px0~2%W@&*kFNvT!V-JMTJm$PDo zvj$T-E%C_nxtgu@vXOwfeLfVZ@Qfp2hEiRg%d>Xy=1<;Tk4Rs25Ek|S^yQ2A-MLqA zE{8=_VxsBYCyg4|PZo2Tl*p(KYK8&A0FZDi z2uuU^6ra!e128E-+3&XabO^;YVgh7~l1(2Gv8cav1|VR4{JhWXYTl`V4y^dag>67^ zaLbd;kZb{T$t+^YY^bJ98%|eO7tl&+ZWZ;rcY46n@TjQ$Ku-0K%|6|SP#GDS>J*oH zxtQ7h10jfwzB`S}0JwpyPcN$*6R>fKi6NaC&m-1J_bvGKI>(&kREGx#8?q9vCIB!O z(5K-xhFT|znEm{}`g#wjCc3a|bV6@}fJzYv9i<3Jl^Q`rL_q1%f{h~5dkr8(=|x0D z2na}Tg3^Q_MMOZFNCyGwozMx%J@Ng%_1}N3yRM71OlHo^oSB@m&-3iPXX3kBFUj5S zBbAT(M@KLF)|Ai3Mkd^^vVm1hPF6OwfVF75JuVRt2UTbouQ1n?e%HxA_ZdTsPt;8L z6_+?Rf%&qB*Tp!+#N3<~!hP{s*}>E>HOoHQMMD*A2w_F~aKT(qCu>`T8dl5LPEeqT zAtWKXxJc%~t6TxF7O=Fm#ChAIoa&aT2oJ$M0?ju!^iPId{CWO^ff``;O#|jY`~9KW zG%4G|I2v$_mX;RRMQ#!6(H{PE7QMOIS&lJ^qo+bC3v-1k)>3FWF1fkJ)|DcdOef}| z59yDeKV^+-mv2~~b3=8Td8t@?AGO>P1YrbX(`F2w@OXL+G#$&ob1U?(()z$fq#a1l zvcD8DNKDr~bJGG9Q4tt9Q*`G0eReg@+0SSI8WrD}yK0654d&Aw^Rt?eet3BmmGwle z>(bH^!p`mzpqDh3Vc6t~X7mk)IOFAZoLOL(WBtBdx3$eLnNoHeyc}|Vt=rHJiC-MHug3}eEjgA4o|6j>l(1)LK*CVzdv*WwJxKVVV}M# z2nd&HW+YMld2Q}AvpB?_Aawlj7YDe|W);JG8p$1cQz!oHC*^XVPKJ(IO|u1SE|$n= z7_<7G!sL}+2!|hDH!PJnK3Jr!SdsCTcs{UVap@%#rrZo!_hu?btYARrnBV;5=b<$9 z9itZ?F*!0~=glI7FO%k679p82%MdIb6+Ru))g2ArhF7pf_XW7Qx$zHH zc#4)@U=2JC)S15j$qU5sCwt2keJF+1ZH3J zEn@f{59MyzknvM0^Kt9#2K)|Ybwk}U!~FqVw00tL>xkq0l6}jw{EE2v;xG^Zg!CT) z@|)W@0-zm^&*!I(oX0CuT-Q3u?>uHI8%3Q&ldW zAHNisgPmsCV=LKu!dO;;xKPeKcZHTma&$e z%C8L${fh{ePlcNl*8&=+fO;D+49}AB`~mZ9pQHb^g`7xyZQIP1>CmDY74>)j)F>~k za;KPz1U6_0_z%v&wWZ%E0r3C0bGMc$?@@+8Qw z^js>T(K4wJWZ;|@^E@)%dg*RDtnv|tIA=!E&mH6&A{{_0v0Nto$(QwiEMfFSZ?*N! zVDDBs3jvLMi+JkT>%3)$8#ivS22#~mK5VCP@(ECanmHIl4ySzUOhqqLTh)PZe5GkE zc-$I-f5iY&c!+B1Ms*tVe+c`3!5Gfpbpz#P@?qr%T(hw@D`Lsp$?q&0_EbANH9XsS z`1z+_yw(@gGb$z2_@iF<6ZXSbzTCckjL#{jEZb!Rwl?%#M6(!R2lFk?3j0!O`X#6{ zQ3eNt6r-ZIfk=*iyhiRf?@_)g5T4Z0pX}N?HSQV5>6GtY@CbZKOqff-j1#(KVE1Mi z@)qWF0y|~1R-)APqm?5jkLr%G$dbCSB+P}GR!qS2)C;{e+U|=CA4YUQl&MKkF(|vK z*!#VS2}jGzyz)OH5VPN+P{~QkT7W{U5gw%U8}QKKD*Qo3)8RpWe$zSN?*KeYfCCOK zuuu3O7n^SjVwwr5a;%W`I>$@S236qha{+ihJUVJKhbAPlfK`qT7U2^~BoKhR1sEn+ zpZV+sJos!1)C)ya-!C2~QM9e(4{Z(19wm)esbbsTYO^w36sr>});-x0pSE6Z(KO`j zh|!v>+#I=VbQ}ZP1-ZV#`hseTuW069^seLT0jFYk9xeQ9y$+ncsC?ldzx{}X`2us~ z-#7BW>)|<26B3n%i7#c7wOE;Afp7;nE!^tqQU@G-pe#PA-mdV1&v^62Yw7{OcTZnG zlt(=xtFn?YHa7O-XMicyZEOTZFGTCDDz1~)TrM{nO(ZcjwO&~4T1XkSF(xTwHh8i* zHb?zo_9ysyCXaDc1Y;7D`lSj8((kN zDB>A^5i_QInrj#DJP!?>hzK$=G6IGH-5qRh8*0u|7`RZrUPtihNg~-6b~s;ead`3z zN>!J%cFNyXS2U0u{ow=2l34KHQ=8qvgWv(QRkJ1KK)>wzrEi}aBemzr?b5x@%`|qk zFyzh^+iOa42JdAgzFk5Bwn2OoYdncOlqEc;lUvgmnKKj5*SM}s_IB2qrhx@=S*(fP zDi-qg55VUIq3#vdXn!~(J^AA5N*s#6QJtYoH3x`$fKnT@IK-_ja*tn;58K}GD-l|> z57$8+#nX}*s1l&&9s^syE4L2$K`Kky5JkYBzTF(mgGoNOzj8teS(_F)S}8TMZ|N;6 z-aDjJ3OufE{djojW9qlcEFvt-!ET?&&LiG#<>sKaVNL$!$xjYbXyS{zkf{4YR;jl_ zmbYJHUikEa$hNLA$%su>6Qu-}4Y$rKoq9^@$oBc@*xq?(u*8{V=4rF)12KoB-zGk% zly}hdyEolp%03@Rh~Zp4J~dK8Zz!^85ppKc&HI>ar8TPx)31YAaS&&}DQDtftCmzy zi=P#)1|1FLae&`b^KZrn2aHWM=AM?xlRL^yGV294 z$HN-l_r3Rx8$9=JsyyR@gj?Z}m)ERvs|h`IO)c2XwS&bNr!r%=I-z0Je;TQ{lR#jb zH9h}UL&?HH*;xgc;#7FWRgb^!j_hNKZs#2>n|oHLXu;kGTI-bEyEHxbQB{}1iS5g) zz^vxM;nobRoYTAaqz}EbX1&;5|ITf&L7$G*%Jk52hf|>_Ojch!OIow%%liJNEO-z% zCy1c%o^K9ebo(XPweoKG5 zq^3U66$L4T$APZ;A_C|{6lBCh`GiENg+Q(ZW^yrkq+AVS}Bt2x&8 zqA7n{(fqqlXX*x14Vvk!9VHaKd8sRk@gJiR5GC`Q!%^Eqn&xh!;&b!Usk@PRf3uIq zQ4pK+&O+;Ka#e+f5V*OA7UTZ(!^qO6+A~W(L3=}dOTR^V_Sg8nJ2%cXEL=5?8Y1?_ ztgVhCS#G_(j8pup_xlG7w>;%*VNz)($SO}YYxT7XN*(*}oN9VSkVWvLzdM$jnwK}m zgY})OVb`LAxlH|7*Vk-A_K3_0mDti-a*{BYusH#sg-;PyDRQAR>m zET6u%DHc*V*xS$eXJwck(6f`z+f~0WOxYt5=8cy>Hk?GPJ1er6` zfB^(B1b)kW1||(4Syxb0)B*(Es$;{wQ1NBd&^QIzNVhF&bNBhwWe3uM+sKt;^J%uubloS;L+M~>l!uw0 z+rREy@7mb7Rs9+gFkuTHQCS`*+Vt?xxQ9onUgL#Fr&7Yg!XUg7l1%9+_&O=+ z{UP5(e8sxq8IY+4SzZ(Ap>&Y>Z78e(d9S~5oQe?{ir(+b%6=A)H6a25zT|ewn{UwT z@N!@NH37?1@?{$TJnGE`jJVw2z-6AEo2J+Wwmdss4gl`&rf_uxVoY16scHSQVf&0! zQlwq)uGRAPosQNcXZFsRO9u3Eh4rRAD*nh+av*ftK%biv^tRM7@7(95$WP=cB)3*$ zgSiWicW!`tHNo$ajEDzoJV;Rmfg*p5Dor}I^6?-o;%U*sF_@kxt&4+fupuAhnyKUhcu#6DtDB)Bx0WLyvV9;D+*Dd@KR%)0?E^>Eeo zXy-{yMmE*3-7kvj@dxHJ8R%lwSVeGazR&C2=4m!CgrH|56|kI}u_P`zQfl`0g&=lu z2U*0OU{2mKX6-ap$D9vqP(#{L%s%DIR>=}2H0AdCeI?G)T;Zi(;k6IQL`eqpk=;4a zR7lUR={Z?Wx%UzmV1e9Yx>eKD`>7I7tg;8wOACIDGulP9W;@nFPKN6K?>B!)>+9?D zH;mr)>|ZYiAyi&8Xj4AQB!I2jTKT908re90{``4kkuyJtHxZYL{}G_TS{{M`)3oT| zvIxn;#)*+HKEmM*iio<#m^Vife8)Ro;zv{kpjARXQUhv8Q*wcTKg<;x+}&qQ7lT)s zdP{fDpKeW2*?kM~uz-T6BJ~FS^7jU(ZXAYq{K+4d9%RA7o+YwybB4oYlS!Z%J6E&i z_*-?DVT<6)SQ<{hFO`%Pnz<7UGqG=kj)6@={sPYv72tl+IUhI_07V7I1g9}rua>xj zB}#j|*b7&Cgy$0-uf}vxO`12Zhg%OC9M#p;Gd63osZZiE+OQue^a&Pr_O!@L~iVSQs<}du}{9?NSXSu3%w1=r@x;zc3 z(+zdMor?CFY093NM7hmV23lG|>0 zwf2qkw|8-t(I4Ho*voUVeidn6nCfe zXI=r2*t*>FY}upfdE8OTUxGO1emp<)2vvFG_kQlC1=>+4211%C!BZA9ym=+eriX%F ztw;&)kNRy`MpvNtiu-`7m~nLv=-^#sxnPBT*RvTVE-iOeS|jJ*>LcKhH0zgoE%`E02P&uW#F+4b8Xa z>l+x11s)8EQ9F9#Z3{i=%0a3iyv;vF*4G}*BB0E8zQW?nrw<>#ZK84jkBSju1vAIv zjh=KlX1(+oPDzlLk1vn9Eq;sT;>Bpdb!tuCA`uO#0qKc1cLZ7KC?bRMDS5tA)1v>} z{C6dAporJTgx1m<=czCXjgs~5ch?3#boTZug`>EVUVUd&39kOyYCBT#zyetz2Se1% zh*3QMny->e(XH3;|#jqd^ebgAX zK@f@$yzE05sJ6|RT3p4eCiq}WpZt~EL{ruFhLYb6PEJnF0aRBWV)Rf?q}mJ}U+|-+ z$H>swI0$`IliAb0!vjtS;y=k=pU$QVdpP8wcnm#tSL@ZbCT?@1rF8CimZi84?{J+f;6BY}$ zLFKoQudl!UpiB$N`>tu1&H7%Efg@kBT(ekE&0lLv3_fm2c`k=dP1L%bm2=AIG|dr% zpy4rwk;_XXKy0l-MKOJC9D{UOWUNQSt*6v52sd~4#FP{b5Dg|fRXf09n%|(0l%Lp- zRlQL1rZ3)KHvq{X#3^d%@z3h{iPLHY64CR0GsmrcnSH|0pQYnH3m@WqP6e?$#1to(wewM&+yy zCmWsY*PRm7;o{#ID)8Ou&i94U{*BLF@>eBWBF)v7_IsM`@ zsJ6h-jr{c+6q~6Vi6x@%^)9sGSjut~u|B&`*vR}tgj6kGOk*m@$K*s) zbVpzE(d-$?y!`$W_Tm29^|ohTfaAD zgJWYWgX_e))`8Vd z5CIr(_e#ubbYC%8MA6uNPk>t;w?+nvzgTd#Tbfvtm@{6~ z!MSfED?M&9=>86m8pACV3?$Z*ynSnw`~63+&`M$KrQyN^`V|CXcH1T<*F`1${YOrVmhEr}GYb$NC2NlxS$Uc7ZATy`%XZ zAePWd+}qqiBVf-Y0Lr{h3pHi7{S z(&1EAyH^u@q)=>M&sq-{d=69z_DJcSAzb@Yjktfx;9#l1NpY4lPVtKDYg#66_3u{# z0=P_Wy%?`?o&!p%rHu_Qzdfx&MjE)}+sQVC$ZWM@fvI;fi%T4FF>c)aw3on>DHP7K zpv)}_-ep1*Gfl77!+4VQ4ncBqEzduInypNxdXi>u!U#$CbyCti035f9kVJ6(0E3TbANKWYVaT0FjoREbKc z?C}}WT1EtvkdYA!5YC?=6Qt*=?4xgVfTYxL%KPPd`LGC3m{2}GgkC3}fyR-+8!ZI# zTQzf+0lyUrj!9x7CurXq(hoiBNwE+f#@$%Mq6qEk-l_2=jvHzWgL&f*f))OxTk4b$pr10bv(q%ohUFsGwqO%<+&_TZ@{cuP7qi;!0$n6tF=`e7K{=vcLnVDQ0O<>AU+HPa^aY6A~`LE0L*Q+R~9h^nySttMvv{|MBW8>_$FPtw?O(9YYK5>w134PmAzY zO0gc7pG$U$2M7Vl%JP6Er7iVCkjB*BsWU+<&q>_1>3!STgKb?LAH!}PUy|p!Bgm|x z;sQBy$XmPLc-Q$@?MDbHt8-0IR&z^-+P$WEi4if#@HeulXxC${qJcPSJhL;Bs?-l} zUDm8?f-9(24!F@B&PU6TJ|%mmCk!ua>9ABf18x z&t75_qot`yVD;UCzD=Aa6WZP=z6hATz>BU8?cB5{gKw#Yk-V0rv3MTCBbx+L#{teS5A?UN4gP-{?^2&$0{BP33dCYK{TO z$jgICeb-7gq`h5TCDT*_6=0*$&moAdmH3VTU>7s!U2%@aWDsY4CW*#<|g0G7}k*SnmpC*s?P!(Py(wvt-|1~ zf`^-APYyZi&V_vZru)itQ+sn=AynW9F#5ahEbb$K>+}q-~VlEzNK3t|7 z&k#3liR?|(W*oVv|KYn)VS>YH$i+&{@X#r%GG;$bt+d(ic~k&y-IM&e+%9+20fPX@ zy5ADf;a+%jc$y;yi3TFRU2A+_2a?AUfyW+z&j0eWjc@~^m`aJLT$(KBCmG0^Z$zv(egq?QwE&&$nYr{fUcNCvZ)~7V6US)b?P{onj z@U*rgI-KMD-K;Q%_H=7kmUv-qc9q~f5+LbM6bL9l7SY^V@>BUFHdEk8%`moAd3{g) zB5LCc6XJBgefIQ|`)KeiR=Q087U8x9-<9$gJelK#2in&EGL;~L}8 z^!dBMseLBi3Hp9fMSso<(#cd}OBT}m_Ff~p!mgk94)_Yh=SnqGctM$)IgF*Hr4sD1 zNzc#`y`A-UpW%icXaE#=&Mhpy{L$B=+jne*4(9a@Uxiqt&SDP5$3iA;lXCw*Q|cwc`JC9HpVZWZ_<>sJeqq+Zbp z^Xj_sDwX4U(7nX>7PfW!+BeJS+3FNtt%~yTq^5F&fZZ1L(u^ABZOgPSf8&F{1l3Iw z5C>QW^v1;afUU=K=Wpi6VRne^w5wt-FJ4Y}inLPyKFGaeLf*yzhh)$9A;35jtCEFK zt~C6i!d<7{!F8=8RHU#vfI7v{tSpFHp34jM)Hv~dE6_~$MHMRBepes8RgJTqR(snKNhJT2iqM&pTDa2ZnG84 zkjfVZgN0V11S{RyIl*@FWt{6dj@IM6mXjUElkL+X`1=bRE)1^^HpK~GL=2@oPi2IV zHe5qv0|(iNNDGVd%bxs&g&f_p?)*=rrPSrH7-rE0U%Kb&A?2?jCw zAe_9);UCg?l`!I}Qxw_6A(*W7@hk}f0?vCskJp|hHF}lm4NIjJ8a^b1kdD-#Fdb;% zQ+c8D$B&(3zblXgScd^UX;xcwe`17_@?m6<_vREiR8B$#0pkP; zNT0kfI1H`=-e6#bassPafvK>wgf1aDxnTza5Wl~WBaZ76LG=W}iNF6{0Or&RI%B3& z`8?o(Qv`p-VUQrCTXtnd(D`N&0-7v3rZQORk-q6g)>+cMoXf^SH!Tw*_%(<(<`oErP0P-c! zhwb>>MsLQ;wX6peiOx`(ZYDn!dK|Q1i~qAH^`+GwTAyqfUYxNAxE9sL2w*h5~(2_*Dq|L8OPRf>3^??n!=ehS(>s?8o^YPW~ zd5m&mT2;9Hn2K1RKd5)VLaYx5m!uqi!5)P7Ng#k$IhE<4vllMhoRlTaTJb7y{9Hcv z{*xo04e*&yJH-dtEn($G$w6&KQb z*gud5c79aE2N(RiA@Ek8A=^{JRC;Xs5E>>I0w`!;<|ktKK?O6(P2}`fXTl>)&m3TK z)ExnRN%{#us8Q!5E|Wnj238wYSpQk{-cx~vU*{eXd>2w%;SVIN@jo-lOEa^#vw(lb zFDc20#qV(%;s-H+eYOmyfd0NdC|oV1&>(+*6mQ!V^jH|v_ooV_t0UQ@H5QCrOheKW za2blOURWC_^N3JgbOFiUM0xf~^z;x55;aN)c?ey6>`%}S#Gi(M-!SRb-^UyZ9#rlI z;4NiF=g+@MPYNxHqA9swMG;BQ*+Ta6$}g=`Q1KVY3J9{st%$UVn?iFYNFJk{>%R7v zBZT;CKPgATJj#k_^m;Q^v9u~CM&SUuqib3t@jF16sp0M}Rigr!Wv;HSAbTweEb0n$ zRZe<07n=gorU^mEUBd>1c;0VsxfoU{`b46UqJO6d_Va_&c>F2n*xJojfY?<7?B@F) zOY^=P7U!d=9*vD)IKvfmco$_7sBEpQ*Tn|wC!;j|v5pZCoKWbBu7a)*zTCr1T-xJ-TiGr)B96z5`JdF&Nsv`zI~44GJW!CO!eH6coxCaf7Xf?@i41dz`@Yk~J_pf||n) zeLUXuyva6vXkf*~m;?XbG}?1GWb)t6tuV5hQy4Qsu2{7d{s>uhpXJH%jjhUkML5Ca zEVMx;127r*yL>;O@Kx3z+3pk!Qc^LYP%35`x}M$$Y4?r5?JC?lnaXzFoP~?~?X@1{ zKb4lHWbgA`foCTC@!BILy9>qYT7~R8G{@X$hC!Z-7bO*Z!}FL2sL%gKLi?A_ed+sz zKPIgZqekejOq6)91(8!c$9yoAl(Q!t6^vBHwT+C(uFh&BN&?S=M*!Urx-geF=8NBJ z_!>M#m_RsTdF07knGUUln;VV%4g7Q zw*}0`#w5V7aIc7aWwWT95=wu%c-w%vrm47z>mcX-#6IO62=+R|S?w9s+dGYKBprCU zrf|RK-34{tlEvO^6+_m#WcNyNgv^#-HV(+F4p99csa&cbi8BV6X=l!H~c1v5s{wr|) zPLW+EJbecmBkNb$`jz@3J9`E2!i1VO1N2WU$%9p=P&$>f?$=I#S_dtp4sJ3!#v*J* zS|ZO{Y*IK)3Dq93F8OU+cH;I!9$|jsyHLX$lQe$JtDo!Z>h|~6v+1VEe1On#acX^V{8HP)$OCd9ECRl+)65rY?5P#Zp&eGJ zum6PV{F(KoJE?*Jhbd(1bM{x+>uwkPw63uCN*>TV@u^=~{on7{uwd$}{!S6d^oPqB zy^?}2dBkr5^_+92*Up^JDY!|>auuz_g&$-gk_0zMlLpcDOL5t>O!TqXMS@ho0=NgtxeLtH^U-Vd*WR~X$q;cQ(F*~ae(IdZdS z5A%K^tPH~gxiU;+ijkL1q7r^pDxnH(|0*_B!6Ao z#Lk~Q&U;2|Gk;zOY$E9~A{58?MVh+PpQax3mwXYy`~LC$k2l&U{SO#Z4ETKyN8}#) z)=$8RKNVtH*4iur`1{fX&tLt5nC9#b8uj~hW8nAig?>ujPhbq#cGkN1UD55xaz-3w zz8;|hW4#lkDS`PC#B;&&+HD0mBzI+ac7v3><>Qn=*irpG3QYug0$)k$$oVgHgn3}2*u2rWxrqaYm}fXKYTPm zv4iwjaaKjE1ab%MDB^Y)m@w+Z;e*t!op}}enlkZH@BKeUVH^b zKmPy!&#?t8B@(ytLt21YBsFRb`2a?|0Lj|er)YWe*R&^n%e_2p|4u~)LI^LSqST%| z5qKFD6*~It^@)Hh@I)p9DW1pQ6Yzn;`FiC+C%;R{pmXc%-1qKH_|<>$Y^ZKcH6ZkT zmYs->TlhWr1a%Zy^ZC8Qnkj&G`>Cp9kJZfA7}Ny^zz!i8L^asXy1fidlELmN8 z#{ISUA`bWD@+s!%s8{Q@+trAg&kuh`oqvbMh~{B@PW`|MV(gNsw?$0cg76<-;h&F= z@(WyJV@^+(ydoBh#ir)%!p&>qa`}b$wpWZ|e6}@y_99;opcJH%!L~;a9`SKua90-> z#lfo8yzwpAHWw~p()T*?>(Nn{{&9~u<_@SzqOAlXHLdgCCOLprL0tg~Fs*w`4UUYS zadvjrGyn#X#hq#NcOdaH;7jt)MqQ2gI=%HHuB)8 zm8a8IX(EK3`NQa;6P9Z@5#y{ME2T-T7&n2R=8cQm5k=$ja5sy^2W-uNa_oT_VUFC7}f|C!J*pr1faizu;D$SCQjqDUIS zgBs8NZV9jb$UPc)!uZk56h) zFd=uRn4YVxKb+R}*GirNr}&%PUHE^fRYFdH9Ml$=0+5k*UIedrJP(pJSv4&!Ey1ik zNDvkWpAgP|jVjz$sd7H&5JdQ>*J^@sm>lDFaHmIykM>6p_<4)-HpTMd)55`jE=!@sLomq_kl7q7ScbzZ$aF>u z?j081d?clZ@(mN@e_?gHbs8#84HO;s-i`Z{AnaA+| zDOm+d(!=BKv&Z%*?Rg9QcX+Z4JKY(Ej>rE>>QGa^H&G2hJ+=|dq@q=SZ1Vw>y!h&N ze=)oXb=O8Pf{ruldRm$+_7~xk{$(O4p8nq5mc^s)0@@3>QvBr<;_;X(QpxE%i-o9~ z{|c3Zb4@ydEH;#o?Mv*|b$41cXl1~r$`*nxqOUr>P^poYK}0cjqXWPiVf zI|t;Usqr8}|K;n?ve4^R-oT^tEeGR~UDm|}h2H7Q+0!Z(TxO@>cQvLy-JcnFvNt_{ zbWvb;JTkg-#bgV|!cY8oz3|2z59whJO2{@RM*s^BA2ufNXA-1{$GCN`pu4b}seR7y zD-ET1Barb43p#NDze4<*CA+d~^iT^QpT-_=i@*qCaP#8#$@yVcoa8KT6QC?-RR+v* z=|8NSQ7bdD!a~D`I)s~@sy+D2fJz+_KX((qm0l8*EwK|hZLPd`<5CQ6hA{SDvH1J{ zim56uY7#f2&%zo0JD<*NRdppL8t&{5pEAKq(EOMRPT|Oy&qx(D9fx?_63bJwi?f=T zyMtpcs>k7Pe?MGZy^i|}wi>Y0)y@kMcSuo?vj5wpEya5G-zKxnufaJ%JG3&TGHkIg z5=W+|H7`;(EBB_w49Dk<;nSqK=~O6=NuF*7%z_qUab$`^&R6`p77RizsSjde)n zHf0uvt7s*~5Fcj{VA*ilkVNr5m*7^8=MC|IZnce*m=nih|UHdWelK@a<&o z&Y()BEgi-GRo?#p-p_?!qV%LtM*}#DtB%j_wEO$NS2qO`%;e?4{2bu;ll9F!IzCR z%SJGA@bOeve{w}VwvA7GzeWs_fF(*79K@r5zyze7CFNG7wtufU1HG6;RKPE^s;l3* zi4R|tu7Z`=h6y=pYV@P2BJ5wB3S$ujf!Ats1JM%EI0XFT=A_p2IiE0GF7hWnbdGQx zOlORExQX5UHJ0!HqDA7VXd}eH?EWn(KtN%9RzY*iY-Bqee4c@fVOq4b+yLCTK#DZF zW~PA7LKi`5O3p84g=9 Date: Sun, 25 Mar 2018 21:44:49 -0400 Subject: [PATCH 03/11] Adds mixing bowls to vendor and cargo --- code/datums/supplypacks.dm | 2 ++ code/game/machinery/vending.dm | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 15d78f37276..700103bb2ec 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -934,6 +934,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /obj/item/weapon/reagent_containers/food/condiment/peppermill, /obj/item/weapon/kitchen/rollingpin, /obj/item/weapon/storage/fancy/egg_box, + /obj/item/mixing_bowl, + /obj/item/mixing_bowl, /obj/item/weapon/reagent_containers/food/condiment/enzyme, /obj/item/weapon/reagent_containers/food/condiment/sugar, /obj/item/weapon/reagent_containers/food/snacks/meat/monkey, diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 4af01736028..6a23da1db9d 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1209,7 +1209,7 @@ /obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5, /obj/item/weapon/reagent_containers/food/condiment/saltshaker =5, /obj/item/weapon/reagent_containers/food/condiment/peppermill =5, - /obj/item/weapon/whetstone = 2, + /obj/item/weapon/whetstone = 2, /obj/item/mixing_bowl = 10, /obj/item/weapon/kitchen/mould/bear = 1, /obj/item/weapon/kitchen/mould/worm = 1, /obj/item/weapon/kitchen/mould/bean = 1, /obj/item/weapon/kitchen/mould/ball = 1, /obj/item/weapon/kitchen/mould/cane = 1, /obj/item/weapon/kitchen/mould/cash = 1, From e78bb385e2320e3d0e99a6addaab4c735a14b205 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Mon, 26 Mar 2018 21:37:23 -0400 Subject: [PATCH 04/11] Replaces obsolete HTML tags tags are obsolete, replacing them with tags which are not. Not really any major difference, both are monospace fonts. --- code/game/objects/items/mixing_bowl.dm | 2 +- .../food_and_drinks/kitchen_machinery/kitchen_machine.dm | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index 7f66fb2d37f..66b4a203935 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -53,7 +53,7 @@ /obj/item/mixing_bowl/attack_self(mob/user) var/dat = "" if(dirty) - dat = {"This [src] is dirty!
Please clean it before use!
"} + dat = {"This [src] is dirty!
Please clean it before use!
"} else var/list/items_counts = new var/list/items_measures = new diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 90b7b6927ae..68c08951b05 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -174,11 +174,11 @@ return var/dat = "" if(broken > 0) - dat = {"Bzzzzttttt"} + dat = {"Bzzzzttttt"} else if(operating) - dat = {"[pick(cook_verbs)] in progress!
Please wait...!
"} + dat = {"[pick(cook_verbs)] in progress!
Please wait...!
"} else if(dirty==100) - dat = {"This [src] is dirty!
Please clean it before use!
"} + dat = {"This [src] is dirty!
Please clean it before use!
"} else var/list/items_counts = new var/list/items_measures = new From 3f1b2b4d6ef80fe118f4da4f3b70b89f32fdafd3 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Mon, 23 Apr 2018 21:43:13 -0400 Subject: [PATCH 05/11] Refactors stack handling --- code/game/objects/items/mixing_bowl.dm | 26 +++++++++++------ .../kitchen_machinery/kitchen_machine.dm | 29 +++++++++++-------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index 8fa92b91368..ec9b6af8fa9 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -29,16 +29,16 @@ if(contents.len>=max_n_of_items) to_chat(user, "This [src] is full of ingredients, you cannot put more.") return 1 - if(istype(I, /obj/item/stack) && I:amount > 1) - new I.type (src) - I:use(1) - user.visible_message("[user] has added one of [I] to [src].", "You add one of [I] to [src].") + if(istype(I, /obj/item/stack)) + var/obj/item/stack/S = I + if(S.amount > 1) + new S.type (src) + S.use(1) + user.visible_message("[user] has added one of [S] to [src].", "You add one of [S] to [src].") + else + return add_item(S, user) else - if(!user.drop_item()) - to_chat(user, "\The [I] is stuck to your hand, you cannot put it in [src]") - return 0 - I.forceMove(src) - user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + return add_item(I, user) else if(is_type_in_list(I, list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/drinks, /obj/item/reagent_containers/food/condiment))) if(!I.reagents) return 1 @@ -50,6 +50,14 @@ to_chat(user, "You have no idea what you can cook with [I].") return 1 +/obj/item/mixing_bowl/proc/add_item(obj/item/I, mob/user) + if(!user.drop_item()) + to_chat(user, "\The [I] is stuck to your hand, you cannot put it in [src]") + //return 0 + else + I.forceMove(src) + user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + /obj/item/mixing_bowl/attack_self(mob/user) var/dat = "" if(dirty) diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index d13d80600de..41fc6613f31 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -127,19 +127,16 @@ if(contents.len>=max_n_of_items) to_chat(user, "This [src] is full of ingredients, you cannot put more.") return 1 - if(istype(O,/obj/item/stack) && O:amount>1) - new O.type (src) - O:use(1) - user.visible_message( \ - "[user] has added one of [O] to [src].", \ - "You add one of [O] to [src].") + if(istype(O,/obj/item/stack)) + var/obj/item/stack/S = O + if(S.amount > 1) + new S.type (src) + S.use(1) + user.visible_message("[user] has added one of [S] to [src].", "You add one of [S] to [src].") + else + add_item(S, user) else - if(!user.drop_item()) - to_chat(user, "\The [O] is stuck to your hand, you cannot put it in [src]") - return 0 - - O.forceMove(src) - user.visible_message("[user] has added [O] to [src].", "You add [O] to [src].") + add_item(O, user) else if(is_type_in_list(O, list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/drinks, /obj/item/reagent_containers/food/condiment))) if(!O.reagents) return 1 @@ -155,6 +152,14 @@ return 1 updateUsrDialog() +/obj/machinery/kitchen_machine/proc/add_item(obj/item/I, mob/user) + if(!user.drop_item()) + to_chat(user, "\The [I] is stuck to your hand, you cannot put it in [src]") + //return 0 + else + I.forceMove(src) + user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + /obj/machinery/kitchen_machine/attack_ai(mob/user) return 0 From 6d49034ad5541021dcb5c90ed93cd7b55c4911f8 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Mon, 23 Apr 2018 22:27:01 -0400 Subject: [PATCH 06/11] Begone thot! --- code/game/objects/structures/aliens.dm | 856 ++++++++++++------------- 1 file changed, 428 insertions(+), 428 deletions(-) diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index f0a4d9551f8..c4506396f45 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -1,428 +1,428 @@ -/* Alien shit! - * Contains: - * structure/alien - * Resin - * Weeds - * Egg - */ - -#define WEED_NORTH_EDGING "north" -#define WEED_SOUTH_EDGING "south" -#define WEED_EAST_EDGING "east" -#define WEED_WEST_EDGING "west" - -/obj/structure/alien - icon = 'icons/mob/alien.dmi' - -/* - * Resin - */ -/obj/structure/alien/resin - name = "resin" - desc = "Looks like some kind of thick resin." - icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' - icon_state = "resin" - density = 1 - opacity = 1 - anchored = 1 - canSmoothWith = list(/obj/structure/alien/resin) - var/health = 200 - var/resintype = null - smooth = SMOOTH_TRUE - -/obj/structure/alien/resin/initialize() - air_update_turf(1) - ..() - -/obj/structure/alien/resin/Destroy() - air_update_turf(1) - return ..() - -/obj/structure/alien/resin/Move() - var/turf/T = loc - ..() - move_update_air(T) - -/obj/structure/alien/resin/CanAtmosPass() - return !density - -/obj/structure/alien/resin/wall - name = "resin wall" - desc = "Thick resin solidified into a wall." - icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' - icon_state = "wall0" //same as resin, but consistency ho! - resintype = "wall" - canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) - -/obj/structure/alien/resin/wall/BlockSuperconductivity() - return 1 - -/obj/structure/alien/resin/wall/shadowling //For chrysalis - name = "chrysalis wall" - desc = "Some sort of purple substance in an egglike shape. It pulses and throbs from within and seems impenetrable." - health = INFINITY - -/obj/structure/alien/resin/membrane - name = "resin membrane" - desc = "Resin just thin enough to let light pass through." - icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi' - icon_state = "membrane0" - opacity = 0 - health = 120 - resintype = "membrane" - canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) - -/obj/structure/alien/resin/proc/healthcheck() - if(health <=0) - qdel(src) - - -/obj/structure/alien/resin/bullet_act(obj/item/projectile/Proj) - if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) - health -= Proj.damage - ..() - healthcheck() - - -/obj/structure/alien/resin/ex_act(severity) - switch(severity) - if(1) - health -= 150 - if(2) - health -= 100 - if(3) - health -= 50 - healthcheck() - - -/obj/structure/alien/resin/blob_act() - health -= 50 - healthcheck() - - -/obj/structure/alien/resin/hitby(atom/movable/AM) - ..() - var/tforce = 0 - if(ismob(AM)) - tforce = 10 - else if(isobj(AM)) - var/obj/O = AM - tforce = O.throwforce - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= tforce - healthcheck() - -/obj/structure/alien/resin/attack_hand(mob/living/user) - if(HULK in user.mutations) - user.do_attack_animation(src) - user.visible_message("[user] destroys [src]!") - health = 0 - healthcheck() - - -/obj/structure/alien/resin/attack_alien(mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(islarva(user)) - return - user.visible_message("[user] claws at the resin!") - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= 50 - if(health <= 0) - user.visible_message("[user] slices the [name] apart!") - healthcheck() - - -/obj/structure/alien/resin/attackby(obj/item/I, mob/living/user, params) - user.changeNext_move(CLICK_CD_MELEE) - health -= I.force - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - healthcheck() - ..() - - -/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target, height=0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return !opacity - return !density - - -/* - * Weeds - */ - -#define NODERANGE 3 - -/obj/structure/alien/weeds - gender = PLURAL - name = "resin floor" - desc = "A thick resin surface covers the floor." - icon_state = "weeds" - anchored = 1 - density = 0 - layer = 2 - var/health = 15 - var/obj/structure/alien/weeds/node/linked_node = null - var/static/list/weedImageCache - - -/obj/structure/alien/weeds/New(pos, node) - ..() - linked_node = node - if(istype(loc, /turf/space)) - qdel(src) - return - if(icon_state == "weeds") - icon_state = pick("weeds", "weeds1", "weeds2") - fullUpdateWeedOverlays() - spawn(rand(150, 200)) - if(src) - Life() - -/obj/structure/alien/weeds/Destroy() - var/turf/T = loc - for(var/obj/structure/alien/weeds/W in range(1,T)) - W.updateWeedOverlays() - linked_node = null - return ..() - -/obj/structure/alien/weeds/proc/Life() - set background = BACKGROUND_ENABLED - var/turf/U = get_turf(src) - - if(istype(U, /turf/space)) - qdel(src) - return - - if(!linked_node || get_dist(linked_node, src) > linked_node.node_range) - return - - for(var/turf/T in U.GetAtmosAdjacentTurfs()) - - if(locate(/obj/structure/alien/weeds) in T || istype(T, /turf/space)) - continue - - new /obj/structure/alien/weeds(T, linked_node) - - -/obj/structure/alien/weeds/ex_act(severity) - qdel(src) - - -/obj/structure/alien/weeds/attackby(obj/item/I, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) - if(I.attack_verb.len) - visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") - else - visible_message("[user] has attacked [src] with [I]!") - - var/damage = I.force / 4 - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(loc, WT.usesound, 100, 1) - - health -= damage - healthcheck() - - -/obj/structure/alien/weeds/proc/healthcheck() - if(health <= 0) - qdel(src) - - -/obj/structure/alien/weeds/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - health -= 5 - healthcheck() - - -/obj/structure/alien/weeds/proc/updateWeedOverlays() - - overlays.Cut() - - if(!weedImageCache || !weedImageCache.len) - weedImageCache = list() - weedImageCache.len = 4 - weedImageCache[WEED_NORTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_n", layer=2.11, pixel_y = -32) - weedImageCache[WEED_SOUTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_s", layer=2.11, pixel_y = 32) - weedImageCache[WEED_EAST_EDGING] = image('icons/mob/alien.dmi', "weeds_side_e", layer=2.11, pixel_x = -32) - weedImageCache[WEED_WEST_EDGING] = image('icons/mob/alien.dmi', "weeds_side_w", layer=2.11, pixel_x = 32) - - var/turf/N = get_step(src, NORTH) - var/turf/S = get_step(src, SOUTH) - var/turf/E = get_step(src, EAST) - var/turf/W = get_step(src, WEST) - if(!locate(/obj/structure/alien) in N.contents) - if(istype(N, /turf/simulated/floor)) - overlays += weedImageCache[WEED_SOUTH_EDGING] - if(!locate(/obj/structure/alien) in S.contents) - if(istype(S, /turf/simulated/floor)) - overlays += weedImageCache[WEED_NORTH_EDGING] - if(!locate(/obj/structure/alien) in E.contents) - if(istype(E, /turf/simulated/floor)) - overlays += weedImageCache[WEED_WEST_EDGING] - if(!locate(/obj/structure/alien) in W.contents) - if(istype(W, /turf/simulated/floor)) - overlays += weedImageCache[WEED_EAST_EDGING] - - -/obj/structure/alien/weeds/proc/fullUpdateWeedOverlays() - for(var/obj/structure/alien/weeds/W in range(1,src)) - W.updateWeedOverlays() - -//Weed nodes -/obj/structure/alien/weeds/node - name = "glowing resin" - desc = "Blue bioluminescence shines from beneath the surface." - icon_state = "weednode" - light_range = 1 - var/node_range = NODERANGE - - -/obj/structure/alien/weeds/node/New() - ..(loc, src) - -#undef NODERANGE - - -/* - * Egg - */ - -//for the status var -#define BURST 0 -#define BURSTING 1 -#define GROWING 2 -#define GROWN 3 -#define MIN_GROWTH_TIME 1800 //time it takes to grow a hugger -#define MAX_GROWTH_TIME 3000 - -/obj/structure/alien/egg - name = "egg" - desc = "A large mottled egg." - icon_state = "egg_growing" - density = 0 - anchored = 1 - var/health = 100 - var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive - layer = MOB_LAYER - - -/obj/structure/alien/egg/New() - new /obj/item/clothing/mask/facehugger(src) - ..() - spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME)) - Grow() - -/obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user) - return attack_hand(user) - -/obj/structure/alien/egg/attack_hand(mob/living/user) - if(user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)) - switch(status) - if(BURST) - to_chat(user, "You clear the hatched egg.") - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - qdel(src) - return - if(GROWING) - to_chat(user, "The child is not developed yet.") - return - if(GROWN) - to_chat(user, "You retrieve the child.") - Burst(0) - return - else - to_chat(user, "It feels slimy.") - user.changeNext_move(CLICK_CD_MELEE) - - -/obj/structure/alien/egg/proc/GetFacehugger() - return locate(/obj/item/clothing/mask/facehugger) in contents - -/obj/structure/alien/egg/proc/Grow() - icon_state = "egg" - status = GROWN - -/obj/structure/alien/egg/proc/Burst(kill = 1) //drops and kills the hugger if any is remaining - if(status == GROWN || status == GROWING) - icon_state = "egg_hatched" - flick("egg_opening", src) - status = BURSTING - spawn(15) - status = BURST - var/obj/item/clothing/mask/facehugger/child = GetFacehugger() - if(child) - child.loc = get_turf(src) - if(kill && istype(child)) - child.Die() - else - for(var/mob/M in range(1,src)) - if(CanHug(M)) - child.Attach(M) - break - -/obj/structure/alien/egg/bullet_act(obj/item/projectile/Proj) - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - health -= Proj.damage - ..() - healthcheck() - - -/obj/structure/alien/egg/attackby(obj/item/I, mob/user, params) - if(I.attack_verb.len) - visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") - else - visible_message("[user] has attacked [src] with [I]!") - - var/damage = I.force / 4 - if(istype(I, /obj/item/weldingtool)) - var/obj/item/weldingtool/WT = I - - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(loc, WT.usesound, 100, 1) - - health -= damage - user.changeNext_move(CLICK_CD_MELEE) - healthcheck() - - -/obj/structure/alien/egg/proc/healthcheck() - if(health <= 0) - if(status != BURST && status != BURSTING) - Burst() - else if(status == BURST && prob(50)) - qdel(src) //Remove the egg after it has been hit after bursting. - - -/obj/structure/alien/egg/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 500) - health -= 5 - healthcheck() - - -/obj/structure/alien/egg/HasProximity(atom/movable/AM) - if(status == GROWN) - if(!CanHug(AM)) - return - - var/mob/living/carbon/C = AM - if(C.stat == CONSCIOUS && C.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo)) - return - - Burst(0) - -#undef BURST -#undef BURSTING -#undef GROWING -#undef GROWN -#undef MIN_GROWTH_TIME -#undef MAX_GROWTH_TIME - -#undef WEED_NORTH_EDGING -#undef WEED_SOUTH_EDGING -#undef WEED_EAST_EDGING -#undef WEED_WEST_EDGING +/* Alien shit! + * Contains: + * structure/alien + * Resin + * Weeds + * Egg + */ + +#define WEED_NORTH_EDGING "north" +#define WEED_SOUTH_EDGING "south" +#define WEED_EAST_EDGING "east" +#define WEED_WEST_EDGING "west" + +/obj/structure/alien + icon = 'icons/mob/alien.dmi' + +/* + * Resin + */ +/obj/structure/alien/resin + name = "resin" + desc = "Looks like some kind of thick resin." + icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' + icon_state = "resin" + density = 1 + opacity = 1 + anchored = 1 + canSmoothWith = list(/obj/structure/alien/resin) + var/health = 200 + var/resintype = null + smooth = SMOOTH_TRUE + +/obj/structure/alien/resin/initialize() + air_update_turf(1) + ..() + +/obj/structure/alien/resin/Destroy() + air_update_turf(1) + return ..() + +/obj/structure/alien/resin/Move() + var/turf/T = loc + ..() + move_update_air(T) + +/obj/structure/alien/resin/CanAtmosPass() + return !density + +/obj/structure/alien/resin/wall + name = "resin wall" + desc = "Thick resin solidified into a wall." + icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' + icon_state = "wall0" //same as resin, but consistency ho! + resintype = "wall" + canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) + +/obj/structure/alien/resin/wall/BlockSuperconductivity() + return 1 + +/obj/structure/alien/resin/wall/shadowling //For chrysalis + name = "chrysalis wall" + desc = "Some sort of purple substance in an egglike shape. It pulses and throbs from within and seems impenetrable." + health = INFINITY + +/obj/structure/alien/resin/membrane + name = "resin membrane" + desc = "Resin just thin enough to let light pass through." + icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi' + icon_state = "membrane0" + opacity = 0 + health = 120 + resintype = "membrane" + canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) + +/obj/structure/alien/resin/proc/healthcheck() + if(health <=0) + qdel(src) + + +/obj/structure/alien/resin/bullet_act(obj/item/projectile/Proj) + if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) + health -= Proj.damage + ..() + healthcheck() + + +/obj/structure/alien/resin/ex_act(severity) + switch(severity) + if(1) + health -= 150 + if(2) + health -= 100 + if(3) + health -= 50 + healthcheck() + + +/obj/structure/alien/resin/blob_act() + health -= 50 + healthcheck() + + +/obj/structure/alien/resin/hitby(atom/movable/AM) + ..() + var/tforce = 0 + if(ismob(AM)) + tforce = 10 + else if(isobj(AM)) + var/obj/O = AM + tforce = O.throwforce + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + health -= tforce + healthcheck() + +/obj/structure/alien/resin/attack_hand(mob/living/user) + if(HULK in user.mutations) + user.do_attack_animation(src) + user.visible_message("[user] destroys [src]!") + health = 0 + healthcheck() + + +/obj/structure/alien/resin/attack_alien(mob/living/user) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + if(islarva(user)) + return + user.visible_message("[user] claws at the resin!") + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + health -= 50 + if(health <= 0) + user.visible_message("[user] slices the [name] apart!") + healthcheck() + + +/obj/structure/alien/resin/attackby(obj/item/I, mob/living/user, params) + user.changeNext_move(CLICK_CD_MELEE) + health -= I.force + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + healthcheck() + ..() + + +/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target, height=0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return !opacity + return !density + + +/* + * Weeds + */ + +#define NODERANGE 3 + +/obj/structure/alien/weeds + gender = PLURAL + name = "resin floor" + desc = "A thick resin surface covers the floor." + icon_state = "weeds" + anchored = 1 + density = 0 + layer = 2 + var/health = 15 + var/obj/structure/alien/weeds/node/linked_node = null + var/static/list/weedImageCache + + +/obj/structure/alien/weeds/New(pos, node) + ..() + linked_node = node + if(istype(loc, /turf/space)) + qdel(src) + return + if(icon_state == "weeds") + icon_state = pick("weeds", "weeds1", "weeds2") + fullUpdateWeedOverlays() + spawn(rand(150, 200)) + if(src) + Life() + +/obj/structure/alien/weeds/Destroy() + var/turf/T = loc + for(var/obj/structure/alien/weeds/W in range(1,T)) + W.updateWeedOverlays() + linked_node = null + return ..() + +/obj/structure/alien/weeds/proc/Life() + set background = BACKGROUND_ENABLED + var/turf/U = get_turf(src) + + if(istype(U, /turf/space)) + qdel(src) + return + + if(!linked_node || get_dist(linked_node, src) > linked_node.node_range) + return + + for(var/turf/T in U.GetAtmosAdjacentTurfs()) + + if(locate(/obj/structure/alien/weeds) in T || istype(T, /turf/space)) + continue + + new /obj/structure/alien/weeds(T, linked_node) + + +/obj/structure/alien/weeds/ex_act(severity) + qdel(src) + + +/obj/structure/alien/weeds/attackby(obj/item/I, mob/user, params) + user.changeNext_move(CLICK_CD_MELEE) + if(I.attack_verb.len) + visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") + else + visible_message("[user] has attacked [src] with [I]!") + + var/damage = I.force / 4 + if(istype(I, /obj/item/weldingtool)) + var/obj/item/weldingtool/WT = I + if(WT.remove_fuel(0, user)) + damage = 15 + playsound(loc, WT.usesound, 100, 1) + + health -= damage + healthcheck() + + +/obj/structure/alien/weeds/proc/healthcheck() + if(health <= 0) + qdel(src) + + +/obj/structure/alien/weeds/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + health -= 5 + healthcheck() + + +/obj/structure/alien/weeds/proc/updateWeedOverlays() + + overlays.Cut() + + if(!weedImageCache || !weedImageCache.len) + weedImageCache = list() + weedImageCache.len = 4 + weedImageCache[WEED_NORTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_n", layer=2.11, pixel_y = -32) + weedImageCache[WEED_SOUTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_s", layer=2.11, pixel_y = 32) + weedImageCache[WEED_EAST_EDGING] = image('icons/mob/alien.dmi', "weeds_side_e", layer=2.11, pixel_x = -32) + weedImageCache[WEED_WEST_EDGING] = image('icons/mob/alien.dmi', "weeds_side_w", layer=2.11, pixel_x = 32) + + var/turf/N = get_step(src, NORTH) + var/turf/S = get_step(src, SOUTH) + var/turf/E = get_step(src, EAST) + var/turf/W = get_step(src, WEST) + if(!locate(/obj/structure/alien) in N.contents) + if(istype(N, /turf/simulated/floor)) + overlays += weedImageCache[WEED_SOUTH_EDGING] + if(!locate(/obj/structure/alien) in S.contents) + if(istype(S, /turf/simulated/floor)) + overlays += weedImageCache[WEED_NORTH_EDGING] + if(!locate(/obj/structure/alien) in E.contents) + if(istype(E, /turf/simulated/floor)) + overlays += weedImageCache[WEED_WEST_EDGING] + if(!locate(/obj/structure/alien) in W.contents) + if(istype(W, /turf/simulated/floor)) + overlays += weedImageCache[WEED_EAST_EDGING] + + +/obj/structure/alien/weeds/proc/fullUpdateWeedOverlays() + for(var/obj/structure/alien/weeds/W in range(1,src)) + W.updateWeedOverlays() + +//Weed nodes +/obj/structure/alien/weeds/node + name = "glowing resin" + desc = "Blue bioluminescence shines from beneath the surface." + icon_state = "weednode" + light_range = 1 + var/node_range = NODERANGE + + +/obj/structure/alien/weeds/node/New() + ..(loc, src) + +#undef NODERANGE + + +/* + * Egg + */ + +//for the status var +#define BURST 0 +#define BURSTING 1 +#define GROWING 2 +#define GROWN 3 +#define MIN_GROWTH_TIME 1800 //time it takes to grow a hugger +#define MAX_GROWTH_TIME 3000 + +/obj/structure/alien/egg + name = "egg" + desc = "A large mottled egg." + icon_state = "egg_growing" + density = 0 + anchored = 1 + var/health = 100 + var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive + layer = MOB_LAYER + + +/obj/structure/alien/egg/New() + new /obj/item/clothing/mask/facehugger(src) + ..() + spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME)) + Grow() + +/obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user) + return attack_hand(user) + +/obj/structure/alien/egg/attack_hand(mob/living/user) + if(user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)) + switch(status) + if(BURST) + to_chat(user, "You clear the hatched egg.") + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + qdel(src) + return + if(GROWING) + to_chat(user, "The child is not developed yet.") + return + if(GROWN) + to_chat(user, "You retrieve the child.") + Burst(0) + return + else + to_chat(user, "It feels slimy.") + user.changeNext_move(CLICK_CD_MELEE) + + +/obj/structure/alien/egg/proc/GetFacehugger() + return locate(/obj/item/clothing/mask/facehugger) in contents + +/obj/structure/alien/egg/proc/Grow() + icon_state = "egg" + status = GROWN + +/obj/structure/alien/egg/proc/Burst(kill = 1) //drops and kills the hugger if any is remaining + if(status == GROWN || status == GROWING) + icon_state = "egg_hatched" + flick("egg_opening", src) + status = BURSTING + spawn(15) + status = BURST + var/obj/item/clothing/mask/facehugger/child = GetFacehugger() + if(child) + child.loc = get_turf(src) + if(kill && istype(child)) + child.Die() + else + for(var/mob/M in range(1,src)) + if(CanHug(M)) + child.Attach(M) + break + +/obj/structure/alien/egg/bullet_act(obj/item/projectile/Proj) + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + health -= Proj.damage + ..() + healthcheck() + + +/obj/structure/alien/egg/attackby(obj/item/I, mob/user, params) + if(I.attack_verb.len) + visible_message("[user] has [pick(I.attack_verb)] [src] with [I]!") + else + visible_message("[user] has attacked [src] with [I]!") + + var/damage = I.force / 4 + if(istype(I, /obj/item/weldingtool)) + var/obj/item/weldingtool/WT = I + + if(WT.remove_fuel(0, user)) + damage = 15 + playsound(loc, WT.usesound, 100, 1) + + health -= damage + user.changeNext_move(CLICK_CD_MELEE) + healthcheck() + + +/obj/structure/alien/egg/proc/healthcheck() + if(health <= 0) + if(status != BURST && status != BURSTING) + Burst() + else if(status == BURST && prob(50)) + qdel(src) //Remove the egg after it has been hit after bursting. + + +/obj/structure/alien/egg/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 500) + health -= 5 + healthcheck() + + +/obj/structure/alien/egg/HasProximity(atom/movable/AM) + if(status == GROWN) + if(!CanHug(AM)) + return + + var/mob/living/carbon/C = AM + if(C.stat == CONSCIOUS && C.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo)) + return + + Burst(0) + +#undef BURST +#undef BURSTING +#undef GROWING +#undef GROWN +#undef MIN_GROWTH_TIME +#undef MAX_GROWTH_TIME + +#undef WEED_NORTH_EDGING +#undef WEED_SOUTH_EDGING +#undef WEED_EAST_EDGING +#undef WEED_WEST_EDGING From ba0b89c93ccd391032cae10afdbe64cc06f4ad39 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Fri, 27 Apr 2018 23:12:27 -0400 Subject: [PATCH 07/11] Refactoring and rewording Moves recipe list generation into its own proc and out of New() - Makes lists only generate/update if not present, to save a small bit of processing on the loop Rewords the messages when adding items to mixing bowls and kitchen machines to sound slightly better > Also refactored messages which were split between multiple lines in the code to be on one line and removed an extra space in one message --- code/game/objects/items/mixing_bowl.dm | 4 +- .../kitchen_machinery/kitchen_machine.dm | 66 ++++++++----------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index ec9b6af8fa9..422bd29ba56 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -34,7 +34,7 @@ if(S.amount > 1) new S.type (src) S.use(1) - user.visible_message("[user] has added one of [S] to [src].", "You add one of [S] to [src].") + user.visible_message("[user] adds one of [S] to [src].", "You add one of [S] to [src].") else return add_item(S, user) else @@ -56,7 +56,7 @@ //return 0 else I.forceMove(src) - user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + user.visible_message("[user] adds [I] to [src].", "You add [I] to [src].") /obj/item/mixing_bowl/attack_self(mob/user) var/dat = "" diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 41fc6613f31..d77e73a338f 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -32,24 +32,28 @@ ..() create_reagents(100) reagents.set_reacting(FALSE) + init_lists() + +/obj/machinery/kitchen_machine/proc/init_lists() if(!GLOB.cooking_recipes[recipe_type]) GLOB.cooking_recipes[recipe_type] = list() GLOB.cooking_ingredients[recipe_type] = list() GLOB.cooking_reagents[recipe_type] = list() - for(var/type in subtypesof(GLOB.cooking_recipe_types[recipe_type])) - var/datum/recipe/recipe = new type - if(recipe in GLOB.cooking_recipes[recipe_type]) - qdel(recipe) - continue - if(recipe.result) // Ignore recipe subtypes that lack a result - GLOB.cooking_recipes[recipe_type] += recipe - for(var/item in recipe.items) - GLOB.cooking_ingredients[recipe_type] |= item - for(var/reagent in recipe.reagents) - GLOB.cooking_reagents[recipe_type] |= reagent - else - qdel(recipe) - GLOB.cooking_ingredients[recipe_type] |= /obj/item/reagent_containers/food/snacks/grown + if(!length(GLOB.cooking_recipes[recipe_type])) + for(var/type in subtypesof(GLOB.cooking_recipe_types[recipe_type])) + var/datum/recipe/recipe = new type + if(recipe in GLOB.cooking_recipes[recipe_type]) + qdel(recipe) + continue + if(recipe.result) // Ignore recipe subtypes that lack a result + GLOB.cooking_recipes[recipe_type] += recipe + for(var/item in recipe.items) + GLOB.cooking_ingredients[recipe_type] |= item + for(var/reagent in recipe.reagents) + GLOB.cooking_reagents[recipe_type] |= reagent + else + qdel(recipe) + GLOB.cooking_ingredients[recipe_type] |= /obj/item/reagent_containers/food/snacks/grown /******************* * Item Adding @@ -78,26 +82,14 @@ if(broken > 0) if(broken == 2 && istype(O, /obj/item/screwdriver)) // If it's broken and they're using a screwdriver - user.visible_message( \ - "[user] starts to fix part of \the [src].", \ - "You start to fix part of \the [src]." \ - ) + user.visible_message("[user] starts to fix part of [src].", "You start to fix part of [src].") if(do_after(user, 20 * O.toolspeed, target = src)) - user.visible_message( \ - "[user] fixes part of \the [src].", \ - "You have fixed part of \the [src]." \ - ) + user.visible_message("[user] fixes part of [src].", "You have fixed part of \the [src].") broken = 1 // Fix it a bit else if(broken == 1 && istype(O, /obj/item/wrench)) // If it's broken and they're doing the wrench - user.visible_message( \ - "[user] starts to fix part of \the [src].", \ - "You start to fix part of \the [src]." \ - ) + user.visible_message("[user] starts to fix part of [src].", "You start to fix part of [src].") if(do_after(user, 20 * O.toolspeed, target = src)) - user.visible_message( \ - "[user] fixes \the [src].", \ - "You have fixed \the [src]." \ - ) + user.visible_message("[user] fixes [src].", "You have fixed [src].") icon_state = off_icon broken = 0 // Fix it! dirty = 0 // just to be sure @@ -107,15 +99,9 @@ return 1 else if(dirty==100) // The machine is all dirty so can't be used! if(istype(O, /obj/item/reagent_containers/spray/cleaner) || istype(O, /obj/item/soap)) // If they're trying to clean it then let them - user.visible_message( \ - "[user] starts to clean \the [src].", \ - "You start to clean \the [src]." \ - ) + user.visible_message("[user] starts to clean [src].", "You start to clean [src].") if(do_after(user, 20 * O.toolspeed, target = src)) - user.visible_message( \ - "[user] has cleaned [src].", \ - "You have cleaned [src]." \ - ) + user.visible_message("[user] has cleaned [src].", "You have cleaned [src].") dirty = 0 // It's clean! broken = 0 // just to be sure icon_state = off_icon @@ -132,7 +118,7 @@ if(S.amount > 1) new S.type (src) S.use(1) - user.visible_message("[user] has added one of [S] to [src].", "You add one of [S] to [src].") + user.visible_message("[user] adds one of [S] to [src].", "You add one of [S] to [src].") else add_item(S, user) else @@ -158,7 +144,7 @@ //return 0 else I.forceMove(src) - user.visible_message("[user] has added [I] to [src].", "You add [I] to [src].") + user.visible_message("[user] adds [I] to [src].", "You add [I] to [src].") /obj/machinery/kitchen_machine/attack_ai(mob/user) return 0 From ce2f69bf1abe8da4b858d8906266f0f0811a8cf7 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 1 Jul 2018 03:47:05 -0400 Subject: [PATCH 08/11] Addresses review comments Lots of comments. --- code/__DEFINES/crafting.dm | 4 +- code/game/objects/items/mixing_bowl.dm | 6 +- .../kitchen_machinery/kitchen_machine.dm | 74 +++++++++---------- 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm index aff1b20e4b2..4b783490568 100644 --- a/code/__DEFINES/crafting.dm +++ b/code/__DEFINES/crafting.dm @@ -9,4 +9,6 @@ #define RECIPE_MICROWAVE "Microwave" #define RECIPE_OVEN "Oven" #define RECIPE_GRILL "Grill" -#define RECIPE_CANDY "Candy" \ No newline at end of file +#define RECIPE_CANDY "Candy" + +#define RECIPE_FAIL null \ No newline at end of file diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index 422bd29ba56..da02182216b 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -32,8 +32,8 @@ if(istype(I, /obj/item/stack)) var/obj/item/stack/S = I if(S.amount > 1) - new S.type (src) - S.use(1) + var/obj/item/stack/to_add = S.split(user, 1) + to_add.forceMove(src) user.visible_message("[user] adds one of [S] to [src].", "You add one of [S] to [src].") else return add_item(S, user) @@ -47,7 +47,7 @@ to_chat(user, "Your [I] contains components unsuitable for cookery.") return 1 else - to_chat(user, "You have no idea what you can cook with [I].") + to_chat(user, "You have no idea what you can cook with [I].") return 1 /obj/item/mixing_bowl/proc/add_item(obj/item/I, mob/user) diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index d77e73a338f..49f53767c5f 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -116,8 +116,8 @@ if(istype(O,/obj/item/stack)) var/obj/item/stack/S = O if(S.amount > 1) - new S.type (src) - S.use(1) + var/obj/item/stack/to_add = S.split(user, 1) + to_add.forceMove(src) user.visible_message("[user] adds one of [S] to [src].", "You add one of [S] to [src].") else add_item(S, user) @@ -246,10 +246,9 @@ var/list/recipes_to_make = choose_recipes() - - if(recipes_to_make.len == 1 && recipes_to_make[1][2] == null) + if(recipes_to_make.len == 1 && recipes_to_make[1][2] == RECIPE_FAIL) //this only runs if there is a single recipe source to be made and it is a failure (the machine was loaded with only 1 mixing bowl that results in failure OR was directly loaded with ingredients that results in failure). If there are multiple sources, this bit gets skipped. dirty += 1 - if(prob(max(10,dirty*5))) + if(prob(max(10,dirty*5))) //chance to get so dirty we require cleaning before next use if(!wzhzhzh(4)) abort() return @@ -258,14 +257,14 @@ muck_finish() fail() return - else if(has_extra_item()) + else if(has_extra_item()) //if extra items present, break down and require repair before next use if(!wzhzhzh(4)) abort() return broke() fail() return - else + else //otherwise just stop without requiring cleaning/repair if(!wzhzhzh(10)) abort() return @@ -282,39 +281,36 @@ return make_recipes(recipes_to_make) -/obj/machinery/kitchen_machine/proc/choose_recipes() +/obj/machinery/kitchen_machine/proc/choose_recipes() //picks out recipes for the machine and any mixing bowls it may contain, and builds a list of the selected recipes to be made in a later proc by associating the "source" of the ingredients (mixing bowl, machine) with the recipe for that source var/list/recipes_to_make = list() - for(var/obj/O in contents) - if(istype(O, /obj/item/mixing_bowl)) - var/obj/item/mixing_bowl/mb = O - var/datum/recipe/recipe = select_recipe(GLOB.cooking_recipes[recipe_type], mb) - if(recipe) - recipes_to_make.Add(list(list(mb, recipe))) - else - recipes_to_make.Add(list(list(mb, null))) + for(var/obj/item/mixing_bowl/mb in contents) //if we have mixing bowls present, check each one for possible recipes from its respective contents. Mixing bowls act like a wrapper for recipes and ingredients, isolating them from other ingredients and mixing bowls within a machine. + var/datum/recipe/recipe = select_recipe(GLOB.cooking_recipes[recipe_type], mb) + if(recipe) + recipes_to_make.Add(list(list(mb, recipe))) + else //if the ingredients of the mixing bowl don't make a valid recipe, we return a fail recipe to generate the burned mess + recipes_to_make.Add(list(list(mb, RECIPE_FAIL))) - var/datum/recipe/recipe_src = select_recipe(GLOB.cooking_recipes[recipe_type], src, ignored_items = list(/obj/item/mixing_bowl)) - if(recipe_src) + var/datum/recipe/recipe_src = select_recipe(GLOB.cooking_recipes[recipe_type], src, ignored_items = list(/obj/item/mixing_bowl)) //check the machine's directly-inserted ingredients for possible recipes as well, ignoring the mixing bowls when selecting recipe + if(recipe_src) //if we found a valid recipe for directly-inserted ingredients, add that to our list recipes_to_make.Add(list(list(src, recipe_src))) - else - if(!recipes_to_make.len) - recipes_to_make.Add(list(list(src, null))) + else if(!recipes_to_make.len) //if the machine has no mixing bowls to make recipes from AND also doesn't have a valid recipe of directly-inserted ingredients, return a failure so we can make a burned mess + recipes_to_make.Add(list(list(src, RECIPE_FAIL))) return recipes_to_make -/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make) - if(!recipes_to_make) +/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make) //cycles through the supplied list of recipes and creates each recipe associated with the "source" + if(!recipes_to_make) //if we aren't supplied a list of recipes, we're done here. return var/datum/reagents/temp_reagents = new(500) - for(var/i=1 to recipes_to_make.len) + for(var/i=1 to recipes_to_make.len) //cycle through each entry on the recipes_to_make list for processing var/list/L = recipes_to_make[i] - var/obj/source = L[1] - var/datum/recipe/recipe = L[2] - if(!recipe) + var/obj/source = L[1] //this is the source of the recipe entry (mixing bowl or the machine) + var/datum/recipe/recipe = L[2] //this is the recipe associated with the source (a valid recipe or null) + if(!recipe) //if no recipe (null), we have a failure and create a burned mess //failed recipe fail() - else - for(var/obj/O in source.contents) - if(istype(O, /obj/item/mixing_bowl)) + else //we have a valid recipe to begin making + for(var/obj/O in source.contents) //begin processing the ingredients supplied + if(istype(O, /obj/item/mixing_bowl)) //ignore mixing bowls present among the ingredients in our source (only really applies to machine sourced recipes) continue if(O.reagents) O.reagents.del_reagent("nutriment") @@ -322,15 +318,15 @@ O.reagents.trans_to(temp_reagents, O.reagents.total_volume) qdel(O) source.reagents.clear_reagents() - for(var/e=1 to efficiency) + for(var/e=1 to efficiency) //upgraded machine? make additional servings and split the ingredient reagents among each serving equally. var/obj/cooked = new recipe.result() temp_reagents.trans_to(cooked, temp_reagents.total_volume/efficiency) cooked.forceMove(loc) temp_reagents.clear_reagents() - var/obj/byproduct = recipe.get_byproduct() + var/obj/byproduct = recipe.get_byproduct() //if the recipe has a byproduct, handle returning that (such as re-usable candy moulds) if(byproduct) new byproduct(loc) - if(istype(source, /obj/item/mixing_bowl)) + if(istype(source, /obj/item/mixing_bowl)) //if the recipe's source was a mixing bowl, make it a little dirtier and return that for re-use. var/obj/item/mixing_bowl/mb = source mb.make_dirty(5 * efficiency) mb.forceMove(loc) @@ -403,19 +399,17 @@ /obj/machinery/kitchen_machine/proc/fail() var/amount = 0 + for(var/obj/item/mixing_bowl/mb in contents) //fail and remove any mixing bowls present before making the burned mess from the machine itself (to avoid them being destroyed as part of the failure) + mb.fail(src) + mb.forceMove(get_turf(src)) for(var/obj/O in contents) - if(istype(O, /obj/item/mixing_bowl)) - var/obj/item/mixing_bowl/mb = O - mb.fail(src) - mb.forceMove(get_turf(src)) - continue amount++ - if(O.reagents) + if(O.reagents) //this is reagents in inserted objects (like chems in produce) var/id = O.reagents.get_master_reagent_id() if(id) amount+=O.reagents.get_reagent_amount(id) qdel(O) - if(reagents && reagents.total_volume) + if(reagents && reagents.total_volume) //this is directly-added reagents (like water added directly into the machine) var/id = reagents.get_master_reagent_id() if(id) amount += reagents.get_reagent_amount(id) From b55c6270e3948393192657a3ce6fb929e5cf4b66 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 1 Jul 2018 03:55:15 -0400 Subject: [PATCH 09/11] Missed one Also made the mixing bowl failed recipes account "loose" reagents (ones added to the bowl directly) in the scaling reagents like the failed recipes for kitchen machines do (consistency). --- code/game/objects/items/mixing_bowl.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/mixing_bowl.dm b/code/game/objects/items/mixing_bowl.dm index da02182216b..1edfdac9561 100644 --- a/code/game/objects/items/mixing_bowl.dm +++ b/code/game/objects/items/mixing_bowl.dm @@ -151,17 +151,20 @@ /obj/item/mixing_bowl/proc/fail(obj/source) if(!source) source = src - var/obj/item/reagent_containers/food/snacks/badrecipe/ffuu = new(src) var/amount = 0 - for(var/obj/O in contents-ffuu) + for(var/obj/O in contents) amount++ if(O.reagents) var/id = O.reagents.get_master_reagent_id() if(id) amount+=O.reagents.get_reagent_amount(id) qdel(O) + if(reagents && reagents.total_volume) + var/id = reagents.get_master_reagent_id() + if(id) + amount += reagents.get_reagent_amount(id) reagents.clear_reagents() + var/obj/item/reagent_containers/food/snacks/badrecipe/ffuu = new(get_turf(source)) ffuu.reagents.add_reagent("carbon", amount) ffuu.reagents.add_reagent("????", amount/10) - ffuu.forceMove(get_turf(source)) make_dirty(75) \ No newline at end of file From e39ce0730580e7c4752c4fba398eb3489f5512bf Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 1 Jul 2018 04:24:06 -0400 Subject: [PATCH 10/11] last requested change --- code/datums/recipe.dm | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index d399568366d..99d97e45626 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -54,31 +54,17 @@ return . /datum/recipe/proc/check_items(obj/container, list/ignored_items = null) //1=precisely, 0=insufficiently, -1=superfluous - if(!items) - if(locate(/obj/) in container) - if(ignored_items) //are we supposed to be ignoring anything? - var/unignored = FALSE - for(var/obj/O in container) - if(!is_type_in_list(O, ignored_items)) - unignored = TRUE //found something we aren't ignoring, quit looking - break - if(unignored) - return -1 - else //anything we found is something we are ignoring - return 1 - else //not ignoring anything, and we found something - return -1 - else //didn't find anything - return 1 . = 1 - var/list/checklist = items.Copy() + var/list/checklist = items ? items.Copy() : list() for(var/obj/O in container) if(ignored_items && is_type_in_list(O, ignored_items)) //skip if this is something we are ignoring continue + if(!items) + return -1 var/found = 0 for(var/type in checklist) if(istype(O,type)) - checklist-=type + checklist -= type found = 1 break if(!found) From 229c7245aa0945a462ee7e15c695c1e6c8367d3f Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 1 Jul 2018 04:29:24 -0400 Subject: [PATCH 11/11] for real this time --- .../kitchen_machinery/kitchen_machine.dm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 49f53767c5f..93b6fdbe8c4 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -246,7 +246,9 @@ var/list/recipes_to_make = choose_recipes() - if(recipes_to_make.len == 1 && recipes_to_make[1][2] == RECIPE_FAIL) //this only runs if there is a single recipe source to be made and it is a failure (the machine was loaded with only 1 mixing bowl that results in failure OR was directly loaded with ingredients that results in failure). If there are multiple sources, this bit gets skipped. + if(recipes_to_make.len == 1 && recipes_to_make[1][2] == RECIPE_FAIL) + //This only runs if there is a single recipe source to be made and it is a failure (the machine was loaded with only 1 mixing bowl that results in failure OR was directly loaded with ingredients that results in failure). + //If there are multiple sources, this bit gets skipped. dirty += 1 if(prob(max(10,dirty*5))) //chance to get so dirty we require cleaning before next use if(!wzhzhzh(4)) @@ -281,7 +283,9 @@ return make_recipes(recipes_to_make) -/obj/machinery/kitchen_machine/proc/choose_recipes() //picks out recipes for the machine and any mixing bowls it may contain, and builds a list of the selected recipes to be made in a later proc by associating the "source" of the ingredients (mixing bowl, machine) with the recipe for that source +//choose_recipes(): picks out recipes for the machine and any mixing bowls it may contain. + //builds a list of the selected recipes to be made in a later proc by associating the "source" of the ingredients (mixing bowl, machine) with the recipe for that source +/obj/machinery/kitchen_machine/proc/choose_recipes() var/list/recipes_to_make = list() for(var/obj/item/mixing_bowl/mb in contents) //if we have mixing bowls present, check each one for possible recipes from its respective contents. Mixing bowls act like a wrapper for recipes and ingredients, isolating them from other ingredients and mixing bowls within a machine. var/datum/recipe/recipe = select_recipe(GLOB.cooking_recipes[recipe_type], mb) @@ -297,15 +301,16 @@ recipes_to_make.Add(list(list(src, RECIPE_FAIL))) return recipes_to_make -/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make) //cycles through the supplied list of recipes and creates each recipe associated with the "source" - if(!recipes_to_make) //if we aren't supplied a list of recipes, we're done here. +//make_recipes(recipes_to_make): cycles through the supplied list of recipes and creates each recipe associated with the "source" for that entry +/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make) + if(!recipes_to_make) return var/datum/reagents/temp_reagents = new(500) for(var/i=1 to recipes_to_make.len) //cycle through each entry on the recipes_to_make list for processing var/list/L = recipes_to_make[i] var/obj/source = L[1] //this is the source of the recipe entry (mixing bowl or the machine) var/datum/recipe/recipe = L[2] //this is the recipe associated with the source (a valid recipe or null) - if(!recipe) //if no recipe (null), we have a failure and create a burned mess + if(recipe == RECIPE_FAIL) //we have a failure and create a burned mess //failed recipe fail() else //we have a valid recipe to begin making