From 8d3feebf3b3c0e9bc24309ba03c070e72019663b Mon Sep 17 00:00:00 2001 From: Geeves Date: Fri, 2 Oct 2020 07:53:46 +0200 Subject: [PATCH] Electro-tethers (#10117) Added a box of eight electro-tethers to the RD's secure locker. --- aurorastation.dme | 1 + code/datums/beam.dm | 81 ++++++++++++----- .../objects/items/weapons/storage/boxes.dm | 9 ++ code/game/objects/items/weapons/tether.dm | 86 ++++++++++++++++++ .../closets/secure/scientist.dm | 1 + html/changelogs/geeves-tethers.yml | 6 ++ icons/effects/beam.dmi | Bin 8077 -> 8292 bytes 7 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 code/game/objects/items/weapons/tether.dm create mode 100644 html/changelogs/geeves-tethers.yml diff --git a/aurorastation.dme b/aurorastation.dme index e4956a6e02d..f13e009a9b7 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -901,6 +901,7 @@ #include "code\game\objects\items\weapons\syndie.dm" #include "code\game\objects\items\weapons\tape.dm" #include "code\game\objects\items\weapons\teleportation.dm" +#include "code\game\objects\items\weapons\tether.dm" #include "code\game\objects\items\weapons\tools.dm" #include "code\game\objects\items\weapons\towel.dm" #include "code\game\objects\items\weapons\traps.dm" diff --git a/code/datums/beam.dm b/code/datums/beam.dm index b96cfe6c0b8..5e02d924655 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -7,10 +7,11 @@ var/icon var/icon_state = "" //icon state of the main segments of the beam var/max_distance = 0 + var/curr_distance = 0 var/sleep_time = 3 var/finished = 0 - var/target_oldloc = null - var/origin_oldloc = null + var/turf/target_oldloc = null + var/turf/origin_oldloc = null var/static_beam = 0 var/beam_type = /obj/effect/ebeam //must be subtype var/timing_id = null @@ -18,18 +19,20 @@ /datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3) origin = beam_origin - origin_oldloc = get_turf(origin) + origin_oldloc = get_turf(origin) target = beam_target target_oldloc = get_turf(target) sleep_time = beam_sleep_time if(origin_oldloc == origin && target_oldloc == target) - static_beam = 1 + static_beam = TRUE max_distance = maxdistance + curr_distance = get_dist(origin_oldloc, target_oldloc) base_icon = new(beam_icon,beam_icon_state) icon = beam_icon icon_state = beam_icon_state beam_type = btype - addtimer(CALLBACK(src,.proc/End), time) + if(time != -1) + addtimer(CALLBACK(src,.proc/End), time) /datum/beam/proc/Start() Draw() @@ -41,9 +44,10 @@ return recalculating = TRUE timing_id = null - if(origin && target && get_dist(origin,target)length) + if(N+world.icon_size>length) var/icon/II = new(icon, icon_state) - II.DrawBox(null,1,(length-N),32,32) + II.DrawBox(null,1,(length-N),world.icon_size,world.icon_size) X.icon = II else X.icon = base_icon @@ -115,28 +119,61 @@ if(DX == 0) Pixel_x = 0 else - Pixel_x = round(sin(Angle)+32*sin(Angle)*(N+16)/32) + Pixel_x = round(sin(Angle)+world.icon_size*sin(Angle)*(N+16)/world.icon_size) if(DY == 0) Pixel_y = 0 else - Pixel_y = round(cos(Angle)+32*cos(Angle)*(N+16)/32) + Pixel_y = round(cos(Angle)+world.icon_size*cos(Angle)*(N+16)/world.icon_size) //Position the effect so the beam is one continous line var/a - if(abs(Pixel_x)>32) - a = Pixel_x > 0 ? round(Pixel_x/32) : Ceiling(Pixel_x/32) + if(abs(Pixel_x)>world.icon_size) + a = Pixel_x > 0 ? round(Pixel_x/world.icon_size) : Ceiling(Pixel_x/world.icon_size) X.x += a - Pixel_x %= 32 - if(abs(Pixel_y)>32) - a = Pixel_y > 0 ? round(Pixel_y/32) : Ceiling(Pixel_y/32) + Pixel_x %= world.icon_size + if(abs(Pixel_y)>world.icon_size) + a = Pixel_y > 0 ? round(Pixel_y/world.icon_size) : Ceiling(Pixel_y/world.icon_size) X.y += a - Pixel_y %= 32 + Pixel_y %= world.icon_size X.pixel_x = Pixel_x X.pixel_y = Pixel_y CHECK_TICK afterDraw() +/datum/beam/proc/get_x_translation_vector() + return (world.icon_size*target.x+target.pixel_x)-(world.icon_size*origin.x+origin.pixel_x) + +/datum/beam/proc/get_y_translation_vector() + return (world.icon_size*target.y+target.pixel_y)-(world.icon_size*origin.y+origin.pixel_y) + +/datum/beam/exploration + var/obj/item/tethering_device/owner + +/datum/beam/exploration/End() + owner.active_beams -= target + owner.untether(target, FALSE) + return ..() + +/datum/beam/exploration/get_x_translation_vector() + return (world.icon_size * target_oldloc.x) - (world.icon_size * origin_oldloc.x) + +/datum/beam/exploration/get_y_translation_vector() + return (world.icon_size * target_oldloc.y) - (world.icon_size * origin_oldloc.y) + +/datum/beam/exploration/afterDraw() + var/distance = curr_distance / max_distance + var/set_color = COLOR_GREEN + if(distance >= 0.8) + set_color = COLOR_MAROON + else if(distance >= 0.3) + set_color = COLOR_BLUE + else + set_color = COLOR_GREEN + for(var/beam in elements) + var/obj/effect/ebeam/B = beam + B.color = set_color + /obj/effect/ebeam mouse_opacity = 0 anchored = 1 diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index bbc3026ade5..ba143d0cc8e 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -316,6 +316,15 @@ desc = "A box of varied assortment of firing pins. Appears to have R&D stickers on all sides of the box. Also seems to have a smiley face sticker on the top of it." starts_with = list(/obj/item/device/firing_pin = 2, /obj/item/device/firing_pin/access = 2, /obj/item/device/firing_pin/implant/loyalty = 2, /obj/item/device/firing_pin/clown = 1, /obj/item/device/firing_pin/dna = 1) +/obj/item/storage/box/tethers + name = "box of tethering devices" + desc = "A box containing eight electro-tethers, used primarily to keep track of partners during expeditions." + starts_with = list(/obj/item/tethering_device = 8) + +/obj/item/storage/box/tethers/fill() + ..() + make_exact_fit() + /obj/item/storage/box/teargas name = "box of pepperspray grenades" desc = "A box containing 7 tear gas grenades. A gas mask is printed on the label.
WARNING: Exposure carries risk of serious injury or death. Keep away from persons with lung conditions." diff --git a/code/game/objects/items/weapons/tether.dm b/code/game/objects/items/weapons/tether.dm new file mode 100644 index 00000000000..67c1cf1a999 --- /dev/null +++ b/code/game/objects/items/weapons/tether.dm @@ -0,0 +1,86 @@ +var/list/global/all_tethers = list() + +/obj/item/tethering_device + name = "tethering device" + desc = "A device used by explorers to keep track of partners by way of electro-tether." + desc_info = "Use in-hand to activate, must be on the same level and within fifteen tiles of another device to latch. Tethers are colour coded by distance." + icon = 'icons/obj/device.dmi' + icon_state = "locator" + w_class = ITEMSIZE_SMALL + slot_flags = SLOT_BELT + force = 1 + var/active = FALSE + var/list/linked_tethers = list() + var/tether_range = 15 + var/list/active_beams = list() + +/obj/item/tethering_device/Initialize(mapload, ...) + . = ..() + all_tethers += src + +/obj/item/tethering_device/Destroy() + STOP_PROCESSING(SSprocessing, src) + deactivate() + all_tethers -= src + return ..() + +/obj/item/tethering_device/attack_self(mob/user) + active = !active + var/msg = "You [active ? "activate" : "deactivate"] \the [src]." + to_chat(user, SPAN_NOTICE(msg)) + if(active) + activate() + else + deactivate() + +/obj/item/tethering_device/process() + var/turf/our_turf = get_turf(src) + for(var/tether in all_tethers) + var/obj/item/tethering_device/TD = tether + if(TD == src) + continue + if(!TD.active) + continue + var/turf/target_turf = get_turf(TD) + if(our_turf == target_turf) + continue + if(target_turf.z != our_turf.z) + continue + if(get_dist(target_turf, our_turf) > tether_range) + continue + if(TD in linked_tethers) + continue + if(src in TD.linked_tethers) + continue + tether(TD) + +/obj/item/tethering_device/emp_act() + deactivate() + +/obj/item/tethering_device/proc/activate() + START_PROCESSING(SSprocessing, src) + +/obj/item/tethering_device/proc/deactivate() + STOP_PROCESSING(SSprocessing, src) + for(var/beam in active_beams) + var/datum/beam/exploration/B = active_beams[beam] + B.End() + for(var/tether in all_tethers) + var/obj/item/tethering_device/TD = tether + TD.untether(src) + +/obj/item/tethering_device/proc/tether(var/obj/item/tethering_device/TD) + linked_tethers |= TD + var/datum/beam/exploration/B = new /datum/beam/exploration(src, TD, beam_icon_state = "explore_beam", time = -1, maxdistance = tether_range) + B.owner = src + B.Start() + active_beams[TD] = B + +// untethering logic is primarily dictated by the beam itself, who will end if the max distance is reached, and call this proc +/obj/item/tethering_device/proc/untether(var/obj/item/tethering_device/TD, var/destroy_beam = TRUE) + linked_tethers -= TD + if(!destroy_beam) + return + var/datum/beam/exploration/B = active_beams[TD] + if(B) + B.End() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index 4cdb8bb7281..a3d76b6ebcf 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -47,6 +47,7 @@ new /obj/item/storage/box/firingpinsRD(src) new /obj/item/device/pin_extractor(src) new /obj/item/storage/box/fancy/keypouch/sci(src) + new /obj/item/storage/box/tethers(src) /obj/structure/closet/secure_closet/RD2 name = "research director's attire" diff --git a/html/changelogs/geeves-tethers.yml b/html/changelogs/geeves-tethers.yml new file mode 100644 index 00000000000..d371ec1d484 --- /dev/null +++ b/html/changelogs/geeves-tethers.yml @@ -0,0 +1,6 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Added a box of eight electro-tethers to the RD's secure locker." \ No newline at end of file diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 924bc156104f25a3d2e2d79f2439c84fd3165987..3ab304ae67e685f9b2fdec3439ff6a8096cd9fe7 100644 GIT binary patch literal 8292 zcmYLOXIN9q7M%n_ReBZa2q+?O6;WCcsVdC|f^-W?l`1s>5orP{pch2C4Iv;+YN7~; zr~ws24@G(jp(TNkyaU|tdq0w#GiUFaJ!fXEz4j!*+R}6{*FG))z+Q7Rqw@g3(9p+) zgAHnVf3Hjr`soV0XcuU7J;2@nmS5m4UmpPOJ}*u^%k@c}&w$WzFfO>n?R>Y-`$r-( z1x+zUH#VZHGLA8PNS}>s8C!0}dj)3xqFW`aLNbi6{7UJ;y6UgTWn{+E zkM;g}7^!EXq8funtCl4FfgO0ODbEpq@J;f(A1ll&QS-d5RPQZyy)29jrPCjKnDX5u zs_%=M1nowrd&2twv1}KeGeWm%0OqA3elr_8zoFJ}S`$;bkj&Kgac7Pq$@BVC<6H08 z?_sYB8`>+R{S}Xddm8r67dN&G10Zc>ZglG6-RBEK#3Thm5RQD|XwyBrvrZD@l3vOG zUUExgOK!67l-M6*((C_8;Q8NE)Kh6E6sBdD&&IFR50zq1eLZa^!%6)(Et_I~{3EjK zu&j%#xu?4wC$sCv>BC1oli%5ibb8@0O5I*O7vyalvh{)TB780iDPymvr}OIN%gyJT zB|g__*W_}N+XeZ>lfGPh`6~rk#J)g1tsyn_cubn$-z{l${coh1x8R>Z?MGz0A~VAUW|Q|D z1(bZ%O743;e^Wdbi5LkyJABc?o|$C**!p${kzUZ5+1nLM6^e2qs>dbXh{C*CP7u$*3#EyIPx?D-b)tj? zTc)GoXhy^V*@eF)l2{&NAZY_!9?b2!U<~;U*o8pv_#w_)O3n*Z3meuh=(Pp+SsL!R zI|#w53}EQUn#XCu%RMPXVPmk@28@^xcikz*{01yS;KMJ?UH2Mm)^a!k_*7f$xHo$X z!498-p~Een?6{M-jDe;ySaQE4@YAxnpX^x3;R53V^fzaB&DDfp7t6)>)8G2IT$Z72 zeq!@i&SwYAuc|g%Q0zo3Z6!4p+Cv4Adv0lahb9(fq5*5P6gqCXoW=b;NLObc87R=W z*>(-4oX0+LVJKF<luD9B8I>r90s_pS-}Y-So!z$;eR006l>t+UtJ*vnL?9xxJo)?&JSF~ z5jZwy2d)dOz|IIZ-ARdBhD&`MJL1vB8VoDZZm(8$-MXD?Vow z*8{UcA9ClZOIiI6!Sv{}eW!}JQLwVfCj4d#$D_cA0rMmvy8l!_f$~p36v{Dj2FvWg zbG{Vr@5pM#04^Cr*YnB}L5DPWSBa8DFYG*58obJJql6=k4#SCu*up8QaLC{9>%wI| z$E0o3=K)wz>wz6pHM$oYp=!re0@V;*c4*sl=_@I?E65oAmlq7L5%-iO`F}z(61Tfk z$&vWlJCROm@|jWJ#0E{kWt!G(jW6dQQ5RMFOu^X zuf*?Gs|mWinGo26<%rFqKZIb#ngmCGvVLMc-9Z$arI~gqgAwc;Qa(B%S? zdk=87Wt?|)ncqckh20bD`3_?I8eRU75cr*>%DMLdO`;+PW%K}! zo^UfaJbjj7a(GJGrU1B9cRlH{euCxSpqW;g^t0z3S>rwb%SbcF@|v#5NsB6l(}E)wRxqVhJ*BUvvj3n5Pr;U&4lG%F>>`$E*2EDj zy8*S1u>8s)?c&bXhBa{Sh;HQ`p)IO?!Ru}C6I>IN!}35Ll3;G8L%ZGXd|wWoq72Gg z{=-^!0Y@GS7nrYrhJ1nvrq?LLJrdxc!RtR_P)P*#c>vekyz5R%l0(NS1HVGgU8s8J zbL2r#9lVvj;~p`f47ZDhgW4>`9bO>{CxT4Kz3I}fd&omM^gba#wRyU0?hKiu;Q%Fa zKz0Ypxvf*uoP_{~3IC572u)B!=W>V9rWjo%Wb@UpbDB}IIjpQQVl!)CQF5gx1^?_Y z5WXdhHWrN9ApiS}B~LB~p4Zf0ctn32<>rL|+9`Vz0YJ2?s z@mR1&k0!AV?lm=#wX@9DtbF^n@K~t@sz^${GfXTsp!!tK zAV=0#(q7lzuVNr(l$qi}5rF}8OmIW=i$yw(pT7>X`c;yj=6t6~@O3a<_K?qPfT_{2 zz$4<9H2mny=9He?vMfLUzm`XPsP~WUVn2!b0#`n&e^B6O__fyoN0XkAaty|JnLE&? zH?A^U&Ka($l4{}cNcu{uiw#(k5cd~&Yt@W=Iu-&^%KT22Ub-ZHTfjaiVrckh`4#%; z3lwWAqym0jy3%sS(Bd&B7s1^*&I{q13!)1Q$LGfo1wgRAw@nw1t)V3s`?`~{PY8z# zBtj{=0!q;k=0htK^LrtX&(TcNmB9yFFLMuNh#wZ{^7irzEY?pq*xww{uy`dXo@$)< zc|G8yg_pE;6eB&keT_N%bX#s@{y%x6CC!zpF|jXV;~=i;!Xpj8NIubLK7(6(9lo!f zub2<*M)}_>ypLdic_u;P!w=^fzSUiAMHkE&CLUALaqBm0`=&xT!+?ikdZx#2_OFy& zfy7ML^I(B9P|W>P&JN^oi}X}CYccpCd$og1LdqY%*zJt$tG-`IU;*z#+Pu=mqFi6* z(Gqg@;x_&!i=C66IXAsUn8e;1;l4)j_X{FfTo|dw~*{&nEoVn*D493Bu z2b@KenEooydc;9v0iaqFmr-Z!3fK)e5xDA}xo=lq?KMCkaK(zE;&&=|zyT=xXF0ik z70w3fkS6eGXo4_>hI6649Vwal5N{;IT`mwGwnBi?Edaf4p0?%?WUQ3I@!sL{&mgv8 z;WBV8TYvJ31NbGwyB^GCCqVR|{hgA#9`3BueBV6}1WwFZo)?0}T1;()Y|wt?OENEF zR(xN9EPmgtRKxc_M28S9g@iy0*&Mh+Qu76r>c^*_yd-c zdbJ@ANx zCu-b5pBWj4rdymlK5*#*K5#<=q_dyLv~RsAy$>tlkkaOJ&S|x~^wA>jpQJ0Wk2Z{)bO%W98Ptu_1~kz)xKmnA@<_p zi8w6e=Nzid=70@Pr?B$K(q5HiEtMcXde6^g^rnU;Zy6p~e=_X$KrZ%gZvE{~7?IeQ z_M&J$djnasx;0)s*(%2AH2*o`OXY9?&(~uxSfRUmk0fM?C2lIreNsbeb3mT zeS@Q7^%Y}&wNkNq-NN89xGx`T$bq$k3GqnWSFeWyP+oWe)-@0J4Bm?7^RQ&Kb)ff1 z!Nv@EWene>G9`|&<+&=4Gv$OpVEP6XDfqD~ef2V5)_JQ4S=UnrVTN|FV+uk5m|dKL zr_CCviy~!N-&nE^^t0|oK&%8@$bqzGcaJlnImX$vLH|6yuFY1s(x!LZZ!MyLRIaHX34a`G;@cd0)EN zpyc5w8&Od7pn$jcG?b}~f)0VeXzr{P0LA`Fo9vvqLB-~uaqGDA;8A3-uknIMjQijNY<%&PkZRuSo?n ziMMdBm16!|Vk;%pu|ApQwUGS2bG*|3jSw?q=nCT}sy{buQEgr}+cwU{y9lqk|~pYq$+uuLgymVVw=rU2cdkNVm%^!Z&m zURU$kGj}$XWJ5^OpPS9Y~sO0`|MoVct~g@KNkS+CW{cmJ&Z^DGo>2} zK$VfGSXanDlgNO9S%fKHgd`R8m^u)+9UNk=Br8Db`*j1xUFt&DPgbmK`QA3z8GH z^)5C8Jg2_e(t@adH8>^RdT@nLj*HKPmzQ=k3Q z-_Xo9(tA&34B5NRZZg2)A}5x0UYbdmMqunm$8RILI`GaFpW1r3@&vD}x3${TG))&L z6?!?m|3=ym96r5NTKg<2Ai_$`hzzA$=Mqi}dGi7g;m{AK1nrsYyMG-&0KqYR2PCJG z!nk$uPg5%}VMA_oQ~Z}3va^z6x8>pQoohWrzmtK#{%^r>_M zbH7mngg`v0w3B7RRQhu1vDx-g;hX@%78bpU~z z4T5Hs1oFlpaf*tnyWjMpBaBwDQD5n9hd-hlW^%lfEUhP>?TA6d*FcA68~MQKaO-!R zQJ_-Hzs#=6+ojk!PuMq2&{LfI60x{pkG_P&o{iu#Fzt7A@m4UDiLwy^5D^@-WHZdY zF@E!=Lh8k*QTjEqsnjg)6VP;Lf8s0u9VE@!g8{OGD8zQKFy)Q%gI}cp$ix0Ypc~K{ z3}25QEJfP<&u2d)xx!8TH`o4cyuj$6I~sbEWabk>3ta_rt=0hD3`v;eq=K}41FB2M z*Hf=y@N-EI?-W>QI0_>)mg$I!b91KFPMHN`LKqjFzt(ucm~qSmuYs5+id$Va~(NyUFXz|Sw< z*}du*+8RV3*YnY@)Dh(Gkm?oh2>*VT!236P=t@*>e1wTVEhGL!!^zFfqmNQAuM_Fh z^-r{d1~0o;-<4_u%}{Sia=ORH&` z_@1eQA5I*qfgMlPf43pAd6)Nag8(6DUiS7S;FK-gQ>;CF{Y5sxF%)8}xwg7*z{`i{S6Nhb1pi?J$NU=lW0np z8EZezTJ<()suWSSkZ)5Vn;sfyv6XVp0G#7)q*v>!E?us;N&9*7#U+f|&zr(sQM7K+ zUq8#*D0*y8DHshlhL6+LWH+hE&7n2A7p?n&KR4ZMxnC?(3*1>MMXqse8#$*{fnUO{f5%+_<(Kgp8PaAICKPnmxZhIOTb!R(+<=2Du9IrkEUfz#9l8s&N(WO-L z&;ulv$;$-&T3KmI9Zy91cM|eKq-8|y?Dh!GK3CL|NbY;+R~4r^RsD!lC{J%jrBmc$ zmxRh#c;Ca`NfNP+yP-%nF0eQ;)Oi<{`hmFa=LcfBlM zb$3*U79ml#7GjsxJIJdoRaKqjPG?H-KH`%n8jLLJ;uPrR-G7kFTR5>!BXo^zf~9@S z;4tZPS0gx<;~K0fXi0w}%yBkEK2QwXE%xEn3X}Mtm2q?u5-46BFY5Z|wbSE>1f{4U zNm|5bXHB-naY`*YQgR$K`0zvx5xc_I6?SoX8mFgFqB*E>chT@xpcYk!A)XDCBPvc}vuh*Ps&7{5E5vQrLuh zdj${H;wUQ-GZ{ZhoTLRDRF_1u)_v^PV)~sqpKs^W%I$pWsk-#XJ~+RA^>%>8@yJrd z)a{i&|dd|r>w!13k5-blP#b!UE?Gc?@fY9Hgu?9S% zRSFT7+`2-iZ$;NuS1V3Q@B5DbsDJG7W`h%VR~_hrV^E6%s!NL)UQSiN-maHWi>(Rw zbCJ8sP$#p$;DpSHC+3yD5tFkSIeY8mof&KwtctBt_e^lWA_CqCUr9zrsIIn*+~+s>z@jONzXOs0(D*VpZ(TfPjB;%dCNEZhDFJ`B4&2(`LMJlM?t7326`HHxn$Y>_Bq%;=4LI$Pjj37 zXC_`@($Im=uvqaVN{5ilh1l~p-elWwR*zSAcx6zGKF_|RwzkcE5$C`?DZXh~KGx#_ z`Yy|C0XS6&iogA#V$D+Fep?1n^+z9XD~eZ+C==%@^iN}0OkBQ&VaOrSP)RS&u?eoD z4-U(=-h-zf;o^&vdD(=v{-|)R{=8Fc-bsGlD)Z?-dgyvjScEf+j3Kv~gkE0Y{VoYuXKBW?<2v-|0a?WTsmJcH-ZgqsAKUbvmkq{yJL2#qnxlYk>%ocadED`AZr*L;Na1-(7m06QBBE!0D zs}M4*r~3p%46?Rul%Wz<;m}uj8dTYT)CFjL=+NY`FH}T9J-%m0!;Lu%q)WMhL^%wn z-o*kP3D^K_muUo!57PY4VvktIf>mKh7y!N9Zvb>ka+Gr~2>#Db?lTn$B$R>bqX^g@ z1Ofnoo;mmYZzf(6_7K^ahB+Huj+V%R^Q5PcuKCt4vh(1wJ zrI*rzlrw3;h~`YPjGRSsbo;>q){5?Neb`-shMtUqSK660L4mUwt-g}pT)y?ro{kT9 za*i~+3s9}Iv*!>;j@Y{m_VzlkDf7$xHJr(ti`aHU_ zA6+MxA5(pRIc`OcP3XyBg{-dpH3R!nj}w6c$?cz*_~&GZ-BIZ~KR-+9N%Tq+alBtE z#_1^9E46n?VP+DTZJkT0#)zvGCJXy*DV}m@{wpO$~^v; z8Q>j5Ni>-qby)&eBvq`4zO>?{d_RJoT+X#FQnrML2{?r>wo>*oR`9LjJ}^jh<-eHX zi+O?s4W-Nrt69BE*wq|r&Ddh+8^@64ED1<-F8pJS1jPg(@kXK9Z)XlD-UJeNoBy#&f?_O? zXc+THd}s!b$^a7G-2PuY29LT8B*rikf3HhQK(6e7h#wvJ6KW8&rT~fhr~j<$rW8+Z z@G=N0p%AQN7s3-nqTidr#5u)zIXH07k%7Si^D|jp7Y7Cb36;G36Mhik>v0Gj%U;q@ z+7=-{8K_N1rKWAOFl2ieP4$Z2Xk&k{i3sG;t(q!cJbFY9@+dC6=mM&qU@sgr`>r!| zZ#?7@d?bg>%Y-P2>zD#9e$y)N;hr=-A)RA|M($Q{s3VG2p-HX*%}(Y(OC!DhP&^tV z0+ACNEWv_tf`x;`T@SuG0f!#*z45q9lqX6@bib&09N_0aEtHk!yZWHuFm&*9SJ(qF zr4b`|Nh;Q#&x`#TR=C1FYNtPoaH^70^Y5C<{rV30=fSA|W!ZX<%skQvAhex-Qm0QP z5$*vb#w*a2S!Ov4A{aY4$N?|o_${EaNs6Yt@>^-@3M!2@m069_H08hvxKDo^ro50OQxu`7s&=pEm}3R<+)RjacPWG4FB@$OXSs! z?I!~S=b!gOpei_3OQfsqm|i4D;e9o;s9N9;$2?~_pWG{)MGpN!%T(1%^l( z?Y}4SCRayY{_z!XEC6Ugv}CMP18IDnuYh?CvdfN7QnjS;n_fowpThnN*{ap&tLG+Q z3~r4AkvJrPqG)f+$dJ~H{(|R$N|~oX<)A=RTxCqi14%vFZk7_sYHPEZn(&(j+d7=; z|Bx5Ob;4r}J;`Hwe^hS5O6^)&82EYn=f7R<(u!W9Xf(UO_}!utzXd}R{)^x3m*G-0 zg6d!VZpUnjC;#GiyVIt4+ii*xfAPEZ#HM)gFMfBJY>KD<;0tRY?nZ9c z;a;xD;|4oZm^g`LeBHl~<7bV$qC^<&tczR0blh57PHmCGjLUCP&(D)2w3#G`#L^AX&g0 zAVM;ejUdyS$z-8u=sh(H2T}Fq$v|^ZMPgtIGI6i>oPV%8Rw=eP3Ul z^K;Aod5>x=x<#L0=+tFzak03!=xgo;`19X^5)v^Av>LknY zu!+Yc%klGGQG2!LxSId%VB=jZaB9l<|K)H-KP^w~R$ekfp}<^qaKmVTjTH($pXt;k zaX^eQMtgQ49}xYra&bcNLws~%ROM_Kub90BqZj~AHh-(TF??^VqJ*wOh<#(IR*@JK zwQ5x22F^GeaY$`n8PZ)Pdgu|_-FZ_Z?E;5wr6{+@0g78~;jnEKWnnbo?6i`c)9NiG z4JbB~7zG;6#{;5v(ih;cT@+hVR|Q++cj}15q2m z=adP{ZHCF@-U_N}j*6BXrTvZ|Pag(|YrE=E@x#n;i;duil2*? zl}i6N+Oqvo{MVhC#{FCL-Z1kQnDOwjaVz+7aAW3)imej4T?#*W`icAH$E^#$p11Ut zu%F`&tSkKdET5iyAlfo9jHYtjB49x51ha>8Nsz>vYZNe#l}M$dLEGc_uaD!#8niFd z`*5?ttM^w#gEFxLGKandyuzY*!-O(Hpk>bxA*dkE936=$1GJ?&4j) zC7uX}h-3DDReE&d_tjXVx7Tk;*i_Q)JyCk}=f13GWb3yi{#L#zQ+jk63@sr+kYL)J zQTul%MHx)wRp%lpx;P`wFGfg)U^u7rdMD-SW^OQjGf156gn!?t+5nhJU}Z?5e&W>C ziKh#@MoZj{+m;Qoy)JDydPCzv4q*i42i#AO1gJXpdNDqDbf`SK&Qnv>ANe}Q+* zga7R+Z(o94OLA9KlF@+%|8mxIFh!rTRpr6jq%cwvt`P!;p_XNgTd z{_D@pwCDA@bPnB@qt{i6V4VaHf{fnp_S8MmbGoSZZM44YoI%l7u%T`DBkx;Y+jBgF z>=S7?=s?7m#vo%4)RE>iy675xyUtAjE4Qh zS&Ap_iC(IK34ZQR1il*z9FNF9Xh2y4?_5rhxm=ZK7&FottB|-y5rp0=tfQ-;fbQa8 z-4)GG{((L0xsr}Bbx#x1(;v-8QOd8bI^5YQ zmAKEP%eY<|kyCrXP)YoBVLm=yLrxQH4C2vYxmeII=%Xu;imdNG@@wt*YQ1I^#f zbm$E?VRUz_VfCv-U12m5dC_FG zp)ocY5C!&vGw)2Myv4S-%qOFE2+5e(dF>Q{c!m@lHo7${)}a=4*~7u2j-oM`iBz~~ z(ijiO+e|H;Qpx`O`H7oAIGbcv4j&o)?(yT=;;xIVD}5f%LvDXKXWN*2AzoBO=(-L` zdRG92@LYC)J>QbxK6>wyXHM{X2FBEo06w=XJgkPaU z%|!B5h9E?_Q(Q;}zU_PqTmif=uw(;vW&m{e3nRYE7dcq^goPYLTsV1=p#z4%j?Tz5 zpukZ7{_YV@EY4*}{s<&ptV#%YYw%E)k(f82ZN05#)TKIL^?kkehE;$p|HEhP%SI6$ zRI+3jZ+1C#FcWX(Df{?kK*Md^V0Q_W?v|3W7l?r~dU~NG`H$MYf?@X5&C_gJDJy?`HlL|%&#cZI?hjxM;NTsFK&*B>hr6$vWNwumk3X~A2` zr8P)jg|(;XTs{@Eku4Q`QT!iFR-={e%!eORHXjo;z9D1)v*Q5g-b{*)Q8b{?7^18` z4P2Cy*(H;xibfc?&I1=Wq<7^&&R{l22R4?vmC;xtMchY4X zkL@8qn^JU4GG0jqlZA2?8A5>{3St)-X5wHjYM}ogreF=d=NlkO=tj{XR^ggEI;4Wr z@Xvg_u@TP3o7OurA?j@TK{s|PZBhV6JSXh>B4Lmz)bPo`ha{V)P;i0p$(L=VN zCEGt>^&khIHcJNcTKzDfJ9@TonE$J|REwV#a|0V3a!Otbm76wE@e{ffIT5o=8uy4q zjPFI=$*WsB%kN!NYi1hr+V5sJhurZ0ckpg-L^zjV;QmVRHSgv|0@=JjX3gZGdgvSL_xhN|9$d_KJJHb8s#PInqg)sUHkgUd!5yLoP^MJ z#GU+F(-p*oJ6l`C#d)PUb3OYf-ZCw|&SUyptxH&K%)G+P1hm$HFX*_r;m)qXQRlcZ ztfLNij@`BMR1e(TQ~vOiS@k;NEI)wGsC`H>5I8cZ;=9r1@_KeL0qgWnl%pxYvCQSAqmH_P>*Mmul0U2x z^=uk{UfBf=_w1Eyw!-c>EQRo{+%7v#G~pE|?L6y8Y# zi6#p?SG86LyV?-;wnwY4XGN}OkMxBZmwA(Uxr=pfl)w^PH8lK;@%qxQv0}XmPFudq z`Ao>{O%RnwY#OUOg36CT$5uI{N24|2qI{<;a)j?AH}{CX`@s>;mF?GHxL@nC`gX_J zQH;QHzDmnl|4aabJ48&rbA4geBJ_0fw(9VsZgu&Yz4~^8^dZs{p2RdE7U39CP*$V# zRI{6s6;Y6NKh=~?#^+y1xh3}uh5Q<7c(|41);qrx$BeZ7%zMIa9xB^=lBN)k4Tg&(5F9)J)Wjz zP~jYZ?S{V#xhh)mZshL=ly%2Pw%4WaWndwW2uxbYo#kZ9TK3rwzw4%ZzMC;&HmEBY z?sZY^Y(y))MaW!97Zhj2mPI8F(Q~iQ90z{^u#$HoMM@VLXLVW3kPXs+=QW?oGvrc6 zV1R78UbkP&ZA4iAk0M;8FdBIMbCSHl&j0S_8n>(x={rA3#;H|`?4*IUM@B&R{&Dw& z+r3c2!)B9!u7rSfUXLUZHxKMf2HswL2c3Hw&@pA?ZwBj!m}gI}&ifq5=q-9|SfQFx zyGzXI?x%ikPZjLYjiQp;x37Ma0qI!kyh+Wm%4)-q!=l&T8A0T7wp}uzDS&vZ!zq0^ zj~LHTFH61j3_8c0G{q6IgVJCvn4`NfNnan(ZVEYt%IWk<1*^J?Kvkwq#0vH70>Iwe z4D$jy=Ra@9atK`CwT%|NAM)x6^kCzc*pZsE{mA9)tFDjGQQX|r z?B=DNs5^z+Y)k&)1az&egX^-Ve;A}Vf%kH51|EA@zYIS|Tq3e|x0a=Hs}_Hac3qoP zpd9Mdz9v7;nN(=QRfc9#F}3{P{CWsGiC6hCI}^;qx6b1(8LvCP;FoUrd)(*@i}|!H z7L^ooZOX(Z)ko5%d8urvOm=-~q|+3Koww^esZNzb`AfHa2Z@wn)ZTgPW5Wbz1>qaW z>E;{sfOJDuk-CAOYaq@ukZbc%O+1a%>XO4AFX_}n>W+{)a6iNC(lZ`N{dGY-{X|V0 zPrxavO0u*tBIgElGX7hkc5sgqU!AuY&$qPb#It0Lhk0LEp~}h`)YYE58l7Fd@O*}> zEA0J|3$C{*bL-kyGj>cF(5W`2Y?0~Wi-U}BO`(Kd8s=;fFkJgkaP1?{oE%-wogR*$ ze&V`3^FpOB(M@?`{zf?ezNRn3f=EQwkP^qy^?k(X*3PA-vmg zcVX{s+tJC=c1Jx~3Ejse_JT~JQF#pJS4*kLe}=PT_Ze3BPY9P=lJ!SYe|VXK2hnD$ zDFgD|t`f78rj(F0>Ks331KhH)JXC%u3JY6sxuLm}{62h6LwgBUOj19m-)*kCuOOSm zUI!cHGq4M#L`~6mvy1lm+_LZAvIVb({r0yI6u8|*SV4L<^zDH2@F!_wwmoma685f` zA~wL5^vi$$3V%8#>e_IdhhUVl@svweV6|zuMiiXxGCse1I?wf*V5C5YvwZXBYz=ct z&}quAFD9CQse|&zb&Ore;UBWA7Vg@o9yZ!n^ZFu3-P}K^INkIIv(!6D};KIjnLZ5 zUcA;9O7Q-oOE@21&|LG+LRz4Aft9|UaFIR0(7hK5u6v6ca?JteSI6(fwOvp=$dSyN zYRNz3IuPr~BDqofc!@JdBMJ~RM{kER3_b?-m*pGs+FNx=0i1`=k4oyeY-~Hn2tp~kk6JTboyD~&JN9IC)zZS}P-j^gSMOi&(cRhBrkF)4yO*Cpr1z~J z*r;rouY~f5QBD5^fiGOrr)ihs#GmHH|D5>R)!RO8P3&){e2bh*J$Mu~HaA@^V-f5p zDz_FSf0TN-6gyKYdY?^r(m<+Om`G4%O215VbxHd99NIhHfE_UkGM0QBA{sH_XI;}7 zU#0_fsl@K9S&0%XyI1f{Zh+V-^szOr8uknF=YP-SveT=$)pOhc?*essYDzxSnL1Y+ zt~Ay{rJvN!KCEOtJp>8#X?k(J)unISj7HeeOaJ1_e*^S=jMHnO^TY3I4F978s)4(8 zhe;Cbyzqik8G^T8U-w1ESUvy?mf9EV<|Wolz)L-ma@$Lzf%4nhM(&eToqJ;kvR0i} z>4=_Bj@L2$M^N@p4@thgf*5(nk?hfdRX8#(NS`aEMmo9v@5Ott0M_C1*OMMR@^cn@ zK7oU>6=XvMcAM?)W-~^`f8BoNDV|^5&JH(}b_$nA@7_$}i|?_liM3W+ZuO9YR01Mw zh-H);3E3C6W#or$GW(SVSOr3kNLOq^!Jl0^02Ty|fCCYx+1fsXmb}sfQ9rz8`zL(a z#x-}`hFcHSmBgleEaukurzX4ZzSNi1O9cy1?Mtd*Yp2KVwr8n>|7N_4=2ySxKk6a6 z-yihlebTABkdIwyER0s{sim3Pn6Jmo{R0OZj#gPZIe?3^o;I=Vjx`IHU#QgV{#G5H zqYjou=Y|K;rx~PCw`yCXO=<=kHixQ!Ld#R3u?~IELTIlk3>$~orV00h$06<^dZb@P z6b$asjS7Chy11O`eWR$^bwnl%fzj*cb6VmN+f?myVb-uyuo*GEZmF;WJ?nO8=TiUc zK4SwxZQ#arj#XV(%C<{Tk4O3I%fl|8t8i;H{POaA87bAStF0Ygj=l6hPJtLuSokG>C~b48Y`Ik`#3S0u(Tlz6$vN0DulCFxIV4 z_z8ps13>-Jm(a&(c`~i#whPqh*b&`bw|6p==Bb>=>?!AWz01tb?oE-!h)ux3^@n@62-9aIH(C2RZ-LwR<4ZzelCsvHtS$O zxAILlaPh<~5uh6YdWC%u-Soo9qZ7U4g9^Z9M!n_H*iirwm;Qwm2DcInn25(AFadJF zmx%_*ra6cPx_NH8frk>8ng!heaKF=W5}RH$1B`f+!HCJ`894$GOQ{#hzrxVq|Led> MOB;(aGfdq70dVKELjV8(