From e441324abc0b6d752cf07e6b82aef0adab512ca0 Mon Sep 17 00:00:00 2001 From: hazelrat <83198434+hazelrat@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:08:20 +0100 Subject: [PATCH] Hydroponics fixes and additions (#20792) Adds a few new recipes to the biogenerator in the interest of making the hydroponicist more useful, including synthetic blood which I didn't notice had been removed until now. Fixes broken handheld icons for horticultural magazines, and introduces a simple set of handhelds for them. Fixes dyn cartons being invisible out of the Condimaster. Adds sounds for watering, weeding, and sampling hydroponics trays, in addition to a one second timer for weeding and sampling specifically. Intended to add more feedback to hydroponics work - right now it's very mute and lacking in visible messages. Adds a new functionality to hatchets! They can now uproot plants, killing them instantly, on a two second timer. This is to avoid the tedious and arthritis inducing process of clicking on a single tray several times to kill one plant. Transitioned some tray documentation to DMDocs. --- code/game/machinery/biogenerator.dm | 30 ++++ code/game/objects/items/toys.dm | 8 +- code/modules/hydroponics/trays/tray.dm | 148 ++++++++++++------ .../food_drink_species_skrell.dm | 2 +- html/changelogs/hazelmouse-bloodreturn.yml | 64 ++++++++ icons/obj/library.dmi | Bin 68342 -> 68948 bytes 6 files changed, 195 insertions(+), 57 deletions(-) create mode 100644 html/changelogs/hazelmouse-bloodreturn.yml diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index a66b185eb0b..6232ed66147 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -120,6 +120,10 @@ FOODSTUFFS name = "Universal Enzyme (50u)" object = /obj/item/reagent_containers/food/condiment/enzyme +/singleton/biorecipe/food/blood + name = "Synthetic Blood (50u)" + object = /obj/item/reagent_containers/food/condiment/blood + /singleton/biorecipe/food/pepper name = "Pepper Grinder" object = /obj/item/reagent_containers/food/condiment/shaker/peppermill @@ -245,6 +249,28 @@ ITEMS object = /obj/item/storage/bag/plants cost = 250 +// Like soap, but better! +/singleton/biorecipe/item/mop + name = "Mop" + object = /obj/item/mop + cost = 400 + +/singleton/biorecipe/item/filterbox + name = "Cigarette Filters" + object = /obj/item/storage/cigfilters + cost = 200 + +/singleton/biorecipe/item/cigarettepaper + name = "Cigarette Paper" + object = /obj/item/storage/box/fancy/cigpaper + cost = 200 + +// Intended to accomodate hydroponicists preparing their own first-aid kits for themselves or the crew. +/singleton/biorecipe/item/emptyfirstaid + name = "Empty First Aid Kit" + object = /obj/item/storage/firstaid/empty + cost = 200 + /* FLAGS */ @@ -355,6 +381,10 @@ CONSTRUCTION object = /obj/item/stack/material/plastic cost = 75 +/singleton/biorecipe/construction/wood + name = "Wood" + object = /obj/item/stack/material/wood + /* CLOTHING */ diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 394272822d8..f93beca1e55 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -413,37 +413,31 @@ itself in every unconnected station, frontier colony, and doctors office across the spur. The magazine's fame largely comes from its writing, maintaining a perfect blend \ of entertaining commentary and nuanced summaries of recent discoveries." icon_state = "horticulture1" - item_state = "horticulture1" + item_state = "horticulture" /obj/item/toy/comic/magazine/horticulturetoday/issue1 desc = "A staple publication of all things horticulture. This issue is about sunflowers." icon_state = "horticulture1" - item_state = "horticulture1" /obj/item/toy/comic/magazine/horticulturetoday/issue2 desc = "A staple publication of all things horticulture. This issue is about root systems." icon_state = "horticulture2" - item_state = "horticulture2" /obj/item/toy/comic/magazine/horticulturetoday/issue3 desc = "A staple publication of all things horticulture. This issue is about garden flowers." icon_state = "horticulture3" - item_state = "horticulture3" /obj/item/toy/comic/magazine/horticulturetoday/issue4 desc = "A staple publication of all things horticulture. This issue is about wild flowers." icon_state = "horticulture4" - item_state = "horticulture4" /obj/item/toy/comic/magazine/horticulturetoday/issue5 desc = "A staple publication of all things horticulture. This issue is about tomatoes of all kinds." icon_state = "horticulture5" - item_state = "horticulture5" /obj/item/toy/comic/magazine/horticulturetoday/issue6 desc = "A staple publication of all things horticulture. This issue is about the genus Allium. Everything from Onions to Leeks." icon_state = "horticulture6" - item_state = "horticulture6" // // Toy Crossbows diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 395fdfd025e..4a5933f71e7 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -8,49 +8,74 @@ atom_flags = ATOM_FLAG_OPEN_CONTAINER volume = 100 - var/mechanical = 1 // Set to 0 to stop it from drawing the alert lights. + /// Set to 0 to stop it from drawing the alert lights. + var/mechanical = 1 var/base_name = "tray" - // Plant maintenance vars. - var/waterlevel = 100 // Water (max 100) - var/nutrilevel = 10 // Nutrient (max 10) - var/pestlevel = 0 // Pests (max 10) - var/weedlevel = 0 // Weeds (max 10) + // --- Plant maintenance vars. --- + /// Water (max 100) + var/waterlevel = 100 + /// Nutrient (max 10) + var/nutrilevel = 10 + /// Pests (max 10) + var/pestlevel = 0 + // Weeds (max 10) + var/weedlevel = 0 var/maxWaterLevel = 100 var/maxNutriLevel = 10 var/maxPestLevel = 10 - var/maxWeedLevel = 0 // Hydroponics systems don't grow weeds irl. Pests are still an issue. + /// Hydroponics systems don't grow weeds irl. Pests are still an issue. + var/maxWeedLevel = 0 - // Tray state vars. - var/dead = 0 // Is it dead? - var/harvest = 0 // Is it ready to harvest? - var/age = 0 // Current plant age - var/sampled = 0 // Have we taken a sample? - var/last_biolum // What was the bioluminescence last tick? + // --- Tray state vars. --- + /// Is it dead? + var/dead = 0 + /// Is it ready to harvest? + var/harvest = 0 + /// Current plant age + var/age = 0 + /// Have we taken a sample? + var/sampled = 0 + /// What was the bioluminescence last tick? + var/last_biolum - // Harvest/mutation mods. - var/yield_mod = 0 // Modifier to yield - var/mutation_mod = 0 // Modifier to mutation chance - var/toxins = 0 // Toxicity in the tray? - var/mutation_level = 0 // When it hits 100, the plant mutates. - var/tray_light = 5 // Supplied lighting. + // --- Harvest/mutation mods. --- + /// Modifier to yield + var/yield_mod = 0 + /// Modifier to mutation chance + var/mutation_mod = 0 + /// Toxicity in the tray? + var/toxins = 0 + /// When it hits 100, the plant mutates. + var/mutation_level = 0 + /// Supplied lighting. + var/tray_light = 5 // Mechanical concerns. - var/health = 0 // Plant health. - var/lastproduce = 0 // Last time tray was harvested - var/lastcycle = 0 // Cycle timing/tracking var. - var/cycledelay = 150 // Delay per cycle. - var/closed_system // If set, the tray will attempt to take atmos from a pipe. - var/force_update // Set this to bypass the cycle time check. - var/obj/temp_chem_holder // Something to hold reagents during process_reagents() + /// Plant health. + var/health = 0 + /// Last time tray was harvested + var/lastproduce = 0 + /// Cycle timing/tracking var. + var/lastcycle = 0 + /// Delay per cycle. + var/cycledelay = 150 + /// If set, the tray will attempt to take atmos from a pipe. + var/closed_system + /// Set this to bypass the cycle time check. + var/force_update + /// Something to hold reagents during process_reagents() + var/obj/temp_chem_holder var/labelled - // Seed details/line data. + /// Seed details/line data. var/datum/seed/seed = null // The currently planted seed - // Reagent information for process(), consider moving this to a controller along - // with cycle information under 'mechanical concerns' at some point. + /** + Reagent information for process(), consider moving this to a controller along + with cycle information under 'mechanical concerns' at some point. + */ var/global/list/toxic_reagents = list( /singleton/reagent/dylovene = -2, /singleton/reagent/toxin = 2, @@ -106,7 +131,7 @@ /singleton/reagent/drink/sodawater = 1 ) - // Beneficial reagents also have values for modifying yield_mod and mut_mod (in that order). + /// Beneficial reagents also have values for modifying yield_mod and mut_mod (in that order). var/global/list/beneficial_reagents = list( /singleton/reagent/alcohol/beer=list( -0.05, 0, 0 ), /singleton/reagent/hydrazine = list( -2, 0, 0 ), @@ -127,8 +152,10 @@ /singleton/reagent/toxin/fertilizer/left4zed = list( 0, 0, 0.2) ) - // Mutagen list specifies minimum value for the mutation to take place, rather - // than a bound as the lists above specify. + /** + Mutagen list specifies minimum value for the mutation to take place, rather + than a bound as the lists above specify. + */ var/global/list/mutagenic_reagents = list( /singleton/reagent/radium = 8, /singleton/reagent/mutagen = 15 @@ -258,7 +285,7 @@ seed.create_spores(get_turf(src)) visible_message(SPAN_DANGER("\The [src] releases its spores!")) -//Process reagents being input into the tray. +/// Process reagents being input into the tray. /obj/machinery/portable_atmospherics/hydroponics/proc/process_reagents() if(!reagents) return @@ -309,7 +336,7 @@ temp_chem_holder.reagents.clear_reagents() check_health() -//Harvests the product of a plant. +/// Harvests the product of a plant. /obj/machinery/portable_atmospherics/hydroponics/proc/harvest(var/mob/user) //Harvest the product of the plant, @@ -342,7 +369,7 @@ check_health() return -//Clears out a dead plant. +/// Clears out a dead plant. /obj/machinery/portable_atmospherics/hydroponics/proc/remove_dead(var/mob/user) if(!user || !dead || !seed) return @@ -363,7 +390,7 @@ check_health() return -// If a weed growth is sufficient, this proc is called. +/// If a weed growth is sufficient, this proc is called. /obj/machinery/portable_atmospherics/hydroponics/proc/weed_invasion() //Remove the seed if something is already planted. @@ -477,6 +504,7 @@ RC.reagents.remove_reagent(/singleton/reagent/water, amountToRemove, 1) waterlevel += amountToRemove user.visible_message("[user] transfers some water to the tray.", "You transfer about [amountToRemove] units of water to the tray.") + playsound(src, /singleton/sound_category/generic_pour_sound, 25, 1) else to_chat(user, SPAN_WARNING("This tray is full of water already.")) return TRUE @@ -498,17 +526,20 @@ to_chat(user, "The plant is dead.") return - // Create a sample. - seed.harvest(user,yield_mod,1) - health -= (rand(3,5)*10) + // Create a sample. Takes a moment. + user.visible_message(SPAN_WARNING("\The [user] begins to sample \the [src]."), SPAN_NOTICE("You begin sampling \the [src].")) + if(do_after(user, 1 SECOND)) + playsound(src, 'sound/items/Wirecutter.ogg', 25, 1) + seed.harvest(user,yield_mod,1) + health -= (rand(3,5)*10) - if(prob(30)) - sampled = 1 + if(prob(30)) + sampled = 1 - // Bookkeeping. - check_health() - force_update = 1 - process() + // Bookkeeping. + check_health() + force_update = 1 + process() return @@ -565,14 +596,33 @@ else if (istype(attacking_item, /obj/item/material/minihoe)) // The minihoe if(weedlevel > 0) - user.visible_message(SPAN_DANGER("[user] starts uprooting the weeds."), - SPAN_DANGER("You remove the weeds from the [src].")) + user.visible_message(SPAN_DANGER("[user] starts uprooting the weeds from \the [src]."), + SPAN_DANGER("You begin to remove the weeds from \the [src].")) - weedlevel = 0 - update_icon() + if(do_after(user, 1 SECOND)) + playsound(src, /singleton/sound_category/shovel_sound, 25, 1) + user.visible_message(SPAN_DANGER("[user] uproots the weeds from \the [src]."), + SPAN_DANGER("You successfully remove the weeds from \the [src].")) + weedlevel = 0 + update_icon() else to_chat(user, SPAN_DANGER("This plot is completely devoid of weeds. It doesn't need uprooting.")) + // Hatchets can uproot the contents of trays to kill the plant with one click. + else if (istype(attacking_item, /obj/item/material/hatchet)) + if(health > 0) + user.visible_message(SPAN_DANGER("[user] begins uprooting the contents of \the [src]."), + SPAN_DANGER("You begin to uproot the contents of \the [src].")) + + if(do_after(user, 2 SECOND)) + playsound(src, /singleton/sound_category/shovel_sound, 25, 1) + user.visible_message(SPAN_DANGER("[user] uproots the contents of \the [src]!"), + SPAN_DANGER("You successfully uproot the contents of \the [src].")) + health = 0 + check_health() + else + to_chat(user, SPAN_DANGER("There is nothing in this plot for you to uproot!")) + else if (istype(attacking_item, /obj/item/storage/bag/plants)) attack_hand(user) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drink/food_drink_species_skrell.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drink/food_drink_species_skrell.dm index a54e7935aac..0cdf2891484 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drink/food_drink_species_skrell.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drink/food_drink_species_skrell.dm @@ -126,7 +126,7 @@ condiment_name = "dyn juice" condiment_desc = "Juice from a Skrell medicinal herb. It's supposed to be diluted." condiment_icon = 'icons/obj/item/reagent_containers/food/drinks/carton.dmi' - condiment_icon_state = "dynjuice" + condiment_icon_state = "dyncarton" /singleton/reagent/drink/dynjuice/hot name = "Dyn Tea" diff --git a/html/changelogs/hazelmouse-bloodreturn.yml b/html/changelogs/hazelmouse-bloodreturn.yml new file mode 100644 index 00000000000..92ae610610c --- /dev/null +++ b/html/changelogs/hazelmouse-bloodreturn.yml @@ -0,0 +1,64 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: hazelmouse + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a few new items to the biogenerator, including synthetic blood, wooden planks, a mop, an empty first-aid kit, cigarette filters, and cigarette papers." + - rscadd: "Hydroponics trays now produce sounds when watered, sampled, and weeded. Sampling and weeding both now have a one second timer for completion." + - rscadd: "Hatchets can now uproot plants growing in soil or in hydroponics trays with a single click." + - bugfix: "Dyn cartons are no longer invisible after being produced from a Condimaster." + - bugfix: "Horticultural magazines no longer have broken sprites." + - imageadd: "Introduced in-hand sprites for horticultural magazines." + - code_imp: "Transitioned some documentation in hydroponics tray code to DMDocs." diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index 6aebf935f2cfb9577fe8255747901750f13f8797..46db7314468950517583761a017cf9e4eebba84f 100644 GIT binary patch delta 8340 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 delta 7730 zcmYjW1yoc~x4tw;gETsWw3L7n(p^e}qQD>_rGS8l)Ez=f8UzU$LMagt5Re!^T8C~V zMH=avA?98E|MlKm>#n=*I%nU#&fRD4@7w3QBN@a;Z-^6EXaI6j005?^iL3#D_#%;4 zhLFuD5y1y~tgEX%v%<{X)pCqCwlJ||S*aSdXfu|sIUizUV;S$rl+LfxHNI!bvb4G> zYV_mh918hn-OqVi)1cGhwlN1se|Wi5aRGvX74g~F%I@*$a!W5_o}u$if=kr*)S@k_ zp?A6UlBUO;Lke2Y`;BH~-^*z|Un$xm9J0!(r!+kV35S}LpNkpJ94Bn~n;t8a_*1M| z=hdf0mg!*<8TT*>m;Ag)UV6QP?)UNq&EpC@6f(XI+3>dOaamI8m9nOK+!9{!yl;D0 z5k_fCaj%_0D2msTQLj!Q^}d<#LgoE$&p)?cvZJ`y$sigFQxyr8)hTl49ce1$srmXr zu7=tk9C-?p{bJuK_@lvp+<3Lev1i1ev|OoJk=i=0@A^@-VA<=BYrazGw{eb(`_Myn ztYcSDK)(GidHe#WzrKCOvEzsO3*7mUBykW=ZK|Q#CN+m#a>Ut{LFedQ>!x*&+vuPpKV<7K- zeI;Ub+erERGdNVN4IH0tQF?F-uaY4=oGY)=-pRdmJcXSjI(ZgG*e+mG zyAS{5h^bd+U5z-HbbM=&ODMG$7j%)G4)bPS?C=%0<`mIQZYJUZ?fK$9@@hPHX3RWW z_|Yi{P?rvyPaCVUOmbCaI?CS^18a!WJ6(m`CesUQNFEf~an`OmlejQAQ9J=kJ~q9) z^u`-|`f1pl^V~&{g6?ZZiT2pR1h5pPDKFpBt&!^2#h1YJriOu-gZj_?_F0AKX~{6T zqxsEXxp230IfjH|u<6HKb-;FxQ0n#-@7lelMF-Q`@TkT+#_t9;37pH8S zmgct=G0_y?3*P43DKVV9H1bJ#p`z2fjXjClRr|}92@3Wj^6Rp`YKPz|QK;I)Ihbm{ z2Ae8W4q9vUQSPd4t0Ftvo#`^^?m7~W;vxbEhH^R+uaA7ba)m~TdEeO}AN>cboj5FX z7va-)9?IMDL^Qo__8}_yf|!{l8PpDZ7;xfeG97@uiQ_QCGq2rqxfNX{Nn)`H_9@6j zOIR%$AeMD)sVE2-$SLT^$0Lg(9P&dfb*T*Fo$tN6)=esTO{ zD5C11emG~g)IO*1qAYY5HFem*baz~K&+oLpv%T;hrSdpNy*f;Ss~nBHzPGnm-@7t& zNT+zZS>@YI8UiQ(dktXs1CKS#jJ=Kv?wANa!xbm9mh-V)pI6yvE{$~f7 z4x3=e2Bb9H4J2RyFPvC~?%(y6{Qo_ZveEt5FZ@m@75RTn=n4j(vRvc&=O;2%Cz-F~ zl$WmEfLZr{UEiRV_&2FE~M!lZY_b-!IAUtdhExxx!3a;0iIHSlp{ z-v^svhA(KI4bC+NU1#`1pc9@q)c5*;JU3^ z;roT8j|A~d;AJ8}$}}b4%{|!}CpOc}?qVmjSvvz5d?16KvL~CSZ=PG=(d^GxkY`cm zra>zzGqUrqk6+&%1{dF`T0Z^MnlqhVcmI&OtY*w+FiBzg9p3BX;Ofz@nlS641HXaQ zBisJ(4)klo!uN^kl~maiN=t=n9Q&^dL=yryn`~NeRl~^jinFtGFx&~;@M*B}S5-ll zlo*;Z#fYE#12$9D&P639>j!OIvp999q~v%>i`3S)O2FI*hXLZF)Kbs zOq@yEhc1_2oulo+`Xb*P1`c9b@Aj3dzwz$cTw>8{e-aZar#a_3d+*< z_ykfOe*TESv)!)lo}RUX_>=k8P~og#aIV;-aN=NXxJ?)S>r+3Q%+7TpK!uJ=$A>(G z-0V;}>4~8ktaOaS<5!qoci)jjr>S-l(bay3i9doK4S15*9Z}26UKRHlcG_qu=s|d4 zfw{O&B>|AtS6y^yHu@Te3of9FtE_rBkuFK2Mn#VFDQJU9z{8A$t-r()I62-1&#;25 z2~fIhuGn4!h~NGT2XI4}!otwB-8iVg3h7sx!y1oysoUH_?8MjJ&10`(MDNc9^8Pd4 zxDWzt?lV;86h+=W>2LvpmqV+zg=m4rq`y9&wEbWtfVTvAl*DfXK-<5u&A6qHz~8YW z>03m~6QB+`RM3$yE`McKJ43TurTjbioo%XYr?CC3-I0}|5|+x%FnA=L1_cs8^^-(! zGbth{0~DX$5RPUBkR89m-~bej?ngq$gs%jTYQmJ(r1(* z@Ej12uJc}Fc<>-Y++*I*3Xe&*TOAdm5CKK*dVJM~OTUoU&z2`g^@n0G1oW<2ug5nC z<|DED%S%ho{V<0Z9pR!+pB!{_bm{`I5~?%&JnC)|QCqJhWx3s^n*E%~^z{D3;=*5( zKga*##)hNuk6A9SD!?SKW|07OFHc?rNO%2GASXR3dM~z)-}MQ`b z5RsCt(q74ksIK<@{X3=$qAdWJoRnpi-J1i{eP*qKQ4RF(--GYHPh@-%rE8b~Q*-lg z3m#$H;Zbg{uFE~ryAv!TPExYj&M#EEir5d-97@MJ$=nNN$~#H$QbuC6_3o-Z za7l7g2YSOGth4h}okLng*O$zJy7L-YicQIeGB0_gnof0F@WBWs=Ect;wg;#rI+OD+ z!{Y!@s#eMhzBs-g)8H>GAt8~Fn3&5!uPn(00pFNDg3;t$?y7+MJ)aL!HH1JCeru3g z=R#d*y^r99yx~=o^WKd@Lgk3%P)UIoe1E}jA6G0sioyj50^UxFH0G%bHV$lVdaJKA zYgr)3k4;xpq5I5lPk4=7wcT08(N{jZ0wp<%135cQBlC#k3n`N9BY2#Nf^t}T*B_|u1nApv`4(Jj(Oj2k#Qwva*mQ=C@ zedurIp(7Wjys4&?eR9ls#j=@trJqP_?pW^Z@k%+h!7PyTV*B?7AE)c=?UwaEY1TZ2 zh8*Nf@-3;HmC($1=~;}X*&mWpOPc8z7LX_@!RjGC+TZxp2djIq83MJL=u%|37f`X> z-;xs0QsvG9%pVmG?<{3E6FBLq&ic5;MnO%PXVXe32dz(leBX9MO!Wwl{qGB+I=LGZ zyQY4&Nnw^^SYYZ->P13Q0H5SClHP7J`^wJD%2Z6$?s?LX61CI6)r<4j5a zK$!WyFmu&!+dTKrGF;KjP>tjXs3mRs*)<4!AOBtnpvp;NoR@59v|!zp)Rmh^VY&H3 zsnE}>n3O!<8*Y}0l~rC~!aD`hB>S!$mA1r0anAJge8Pj%<9-4=D!VRyXv=PRul9EL zUZE|oWm81Bn&JlM_pwwjt!m3xtQac5|`pk0bN`ZJaPvc zBW;s`CWBgwmfb}yBMXbD_4VYUGQ~$3LGpk3wrv5~w$K8GEzvGs+)G_w<{k+nS0Kp_ zAePSZDsd5m3*{TM)Fes#(LIbIb9^pKvCyMcft}x+sbd2w)@JTixNm3s=yad4(fSDf zo%3ju1xBQumh;gIo-IcX4tfMmIy(1~6E=8Z)4tQz2f}V*e&!&CO`>i?hulC>H6vaz z@StlN3=mGo@&LUtjW3-LX~}fi0bvp_`Q069SXLt!FRSfmV+K_^C0kW?I(&M8EeVQ7 zdfINWxPLIC|0$iu#+S)2jR_77io?uZw$DPuHBiMr{-CKktJCXB$JEI~E|0o06I1XT zThjxaLuVlXqqhY9~Qy7z+p)~zn016P+gFt=>$=K8w+;>m7#>)U8a$GDubGUm$7 z7+t0M@h6y9d|=gryUbZFN7Tm@E?>pz_t3UmcYGB1E~l=8-%&G!#-k z{)8Zh7aq{iMt_Pf^leL~%?WJ7>LDDVkVu$|x_?vCa5S9rurN?UN--K6HnR4Opy$D* zhl%U)jbfAlA%<-G96$=bW+50bPPn^`W~k&8noN(L-}~fosJHTli2R9+(oPST{8u;j zfJxK_-}{;x^MAfG_z zIgIn>01*mjW5r81uGR7$s7Ch^TB9}S+T+QF84|W4`^O1221!#x;3{TK1K-OA`rx}a z34tdyJlaVlm78@wA8zA5E>2Ebuu49@CLyV1+k)f*h~F2kSPC_RE_U-R^x6jfDt>-6 zo?iUQNy4lWzaQH>#z##78liCZ!XWN8<5&?F;`1wh1A7bODKYQ-?vXBKno{4~zH^M|Y z=?M@Id)&(Es%8QWG)lJ-K1=SmfnE>aqd!B8bjo^ab@U4$<4dpV6<^z_OX{i~lV$>A z=qkFveFL@bbFG%6p`_=)O~#>m{H2jjbAcBcJac86-(j;JeJ_2!u?1k4^?(6UlF8#Y zHHzIcwd$!M5!V}jRZE1A(Xs5G{iu`~?Rqiq;z})At^OEPzJ0yndZQriC?e=}VOQyJ z?JYqV0Wv%6q^h}?E!ItJtFp7^eI`7zjByCrUHL?tkY03m4C;%Haz6;T6_wC3>!~6K z=LMqq=l!R*gbd9{VqUhsE$L5X!n&G!9IPrW97^Ta<8BD25@*RBU+K$Mcvafwn-|LR+Bdp?7KU~o|4>`8G4v2Xvh`5z^hPn&V+90-I$U8c z!xgDe&{1VCrlJeKWf;#OP-#|6)&ry{HpvxIkkhUgl?$FPEwG=9H_shx33X>ClK@cM zqazQ`f0QjVv8krUBrS+(W=~&<=WV>Si|+8 zq8q=TL2Wt$jZJb>Y`@%)9RoZy*_#d2b8W|6INXztMZqfYzZ^dO7EYnqjWFo(2Xh@< z{!O*6C~c(;S9Co$H&A7G?|(4Dtx~V06bG54nMG+srz$V<$uKul1+O}y555~-P;x^J z`X5{NjUC-8o-bC33>p;XuGbo^S?niCQRT8WAT%FF&#kFKr%uHw!x@tE0d{4ruyAF5 zbJC>Z0pnn;J0E0O4%S*2Jd0fYJo#ii5K%wl*2Fa<;Hv{i`Zxq5cNNGRc?MR7XAJ}e z*PxxXu*knVi2r=!5w;D;;fE_wp!>*BF0~aW6oDB(BT$)uvgFlV0U?XAGPDeewRZw@9tSn zY@HSI*SZu04w}Yu#pxr@2|TAQ`ZRiNIU{3{fPy^2osk$MaO@9?7%rsEDOnFIrig?ajy%2G$diyZ zLXt+3q2g0x&cJHPtbITwKkoPO!W?`65tGPAG!0gvJg`n}8~Zohl}Qdo0&|h{l#X_u zVWCQ8pr3maI+ladO;O@;p9X4Hr_N*7^OV1?Gd$W8!~Xe(%ekY{$tO2OnJe$`;0DZX z%wJJgZ!EXk{tDFR4`Q@ZaNzl{`(dke;YqG)Z-BCEB^v5rq&Y8o$e=9BKYbVX0H0e} zv#}hyhzdLLX(ojb%lFzh$2P+112svQQ8vD0U}d|%4xz8M{U~tijXl8woOmhvwk@PL zVA`tr4zwd{6}6H!{}L#e{(gGL&&u$!w0ySEyP)#1PhvQJhF!5;sgUK z&%?9Q9x6QB#vr=}Gib{YwY3z$PIp!fIuWA9wc$T|r%+E%SmTv<3ucK=pZP)H9dyw+ zy*}vALLwhG7T|F%HY-M>hiZ!@m*)QKpxLP>o8~a|E_w54^LP!-o$BS#jctpsrD}n0 zsx_d$p@ACctHT_DAye_DRgK$Y(undMM0=3e5?_ass`eBCoxOQ_E?Ly5n9bP4w7NBm z3yVBudM>!`?7`F#3nf&?-@XEYS1=uoU0=7W^W9Z#APzf5?r_*qt@Mx2H*D*-yua!I ztQxlkYC*@FO1bSu#&Oyn$XSW^vJ?2X-bHmGEJ>906#KH|2YL7DOOVv5k8pec+ zbFYNdR0^ZZiK(f<3vKRDnIjr|1mtHY%4H?&yAvud(!=~MZ-z-yj=g&^>zo3mQpALmc3%A;?|38>dm6QK1)23lbv?Cep8m)~4h ze@DA$CM|eg-*i_SYw;6L2(^EcwR-rBw8tIa0!}uRs{CcGyAe?@zSnO2487ZpV=CVW zghAlBS&7{l$NxIFy#vW0O~-8rB~v>;VN68xMINtz#lljQ-*!ZEkN_hC<^Do>v*VJ) z^ydJxi4_BIITT*c!j(CoVMJ_4r4@hGp;A~aiKn}gO2Y^qorgAl>FO#}YAysJ*!L{` zLNpACHV-c;fpo&8_Z6`kjfb+qALaCb0HDm;e{=MhQ_kmBJ6Seazz1)5J>LN&j*%$1 zSL2r7*u4AHG?+k(@9fm9hEC)s(=-un1Bt#e;0BU)CammJfN1NA7vkaB&@+)-N~|NN z7eqn^^1`X=O`I4iPtQ`^_QZ;7u&|uB7s8^L{q`zU!Hs3DkuPwMh_}s5$*U+Yv3{2( zbZVGr)3dwu8r5>NH-3;EukF}y=^jY*efPeKIE00xceOh)U%PkYeAF~vwpUrb`q&II zyYA>?k9<~?%IoO1Q{2b>6;m4MjM`q-;gn^ON4O4JruESMK*Y) zczI^>`l6f%#NO)ED+}w3SmTuDXXpEKb0ej_J{o_6O8w0d6*%U$2!4g48YyYLy>(9hQ2n0-dU-hcg z3>Ie|;IK^%nwjN$QY0XKSNi^6B>oJ2Ln|xgDz&&C9+HQ5p${O~2zgr!A@J1zXzj@7 zDwvVEDo?iMW^~5^MB~?v3<)7+9aIT>1u_t-qrbl_J$R{;%C@E@5NMs`poyc`MWxxN zCkBNLt?*hreh