From db87175163cd8ccbef2554d498985ba7f05146a3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 20 Mar 2020 13:50:44 -0400 Subject: [PATCH] Earlyport Fixes --- code/modules/ai/_defines.dm | 5 +++++ code/modules/ai/ai_holder_combat.dm | 19 +++++++++--------- code/modules/ai/ai_holder_movement.dm | 10 +++++++-- code/modules/ai/interfaces.dm | 4 ++-- code/modules/mob/_modifiers/fire.dm | 5 ++++- .../mob/living/carbon/human/human_resist.dm | 4 ++-- code/modules/mob/living/living_defense.dm | 3 +++ code/modules/mob/living/simple_mob/combat.dm | 8 +++----- .../projectiles/guns/magnetic/gasthrower.dm | 1 + .../modules/projectiles/projectile/bullets.dm | 7 ++++--- .../Chemistry-Reagents-Core.dm | 4 ++-- icons/obj/pda_holo.dmi | Bin 6918 -> 7164 bytes 12 files changed, 43 insertions(+), 27 deletions(-) diff --git a/code/modules/ai/_defines.dm b/code/modules/ai/_defines.dm index e94d26b3c3a..7b49f18ddb2 100644 --- a/code/modules/ai/_defines.dm +++ b/code/modules/ai/_defines.dm @@ -20,6 +20,11 @@ #define MOVEMENT_FAILED 0 // Move() returned false for whatever reason and the mob didn't move. #define MOVEMENT_SUCCESSFUL 1 // Move() returned true and the mob hopefully moved. +// Results of pre-attack checks +#define ATTACK_ON_COOLDOWN -1 // Recently attacked and needs to try again soon. +#define ATTACK_FAILED 0 // Something else went wrong! Maybe they moved away! +#define ATTACK_SUCCESSFUL 1 // We attacked (or tried to, misses count too) + // Reasons for targets to not be valid. Based on why, the AI responds differently. #define AI_TARGET_VALID 0 // We can fight them. #define AI_TARGET_INVIS 1 // They were in field of view but became invisible. Switch to STANCE_BLINDFIGHT if no other viable targets exist. diff --git a/code/modules/ai/ai_holder_combat.dm b/code/modules/ai/ai_holder_combat.dm index 65fd1785b13..a56f03777da 100644 --- a/code/modules/ai/ai_holder_combat.dm +++ b/code/modules/ai/ai_holder_combat.dm @@ -70,21 +70,21 @@ /datum/ai_holder/proc/melee_attack(atom/A) pre_melee_attack(A) . = holder.IAttack(A) - if(.) + if(. == ATTACK_SUCCESSFUL) post_melee_attack(A) // Ditto. /datum/ai_holder/proc/ranged_attack(atom/A) pre_ranged_attack(A) . = holder.IRangedAttack(A) - if(.) + if(. == ATTACK_SUCCESSFUL) post_ranged_attack(A) // Most mobs probably won't have this defined but we don't care. /datum/ai_holder/proc/special_attack(atom/movable/AM) pre_special_attack(AM) . = holder.ISpecialAttack(AM) - if(.) + if(. == ATTACK_SUCCESSFUL) post_special_attack(AM) // Called when within striking/shooting distance, however cooldown is not considered. @@ -218,7 +218,6 @@ var/dir_to_target = get_dir(holder, target_atom) holder.face_atom(target_atom) - ai_log("breakthrough() : Exiting", AI_LOG_DEBUG) // Sometimes the mob will try to hit something diagonally, and generally this fails. // So instead we will try two more times with some adjustments if the attack fails. @@ -274,31 +273,31 @@ for(var/obj/structure/window/W in problem_turf) if(W.dir == reverse_dir[holder.dir]) // So that windows get smashed in the right order ai_log("destroy_surroundings() : Attacking side window.", AI_LOG_INFO) - return holder.IAttack(W) + return melee_attack(W) else if(W.is_fulltile()) ai_log("destroy_surroundings() : Attacking full tile window.", AI_LOG_INFO) - return holder.IAttack(W) + return melee_attack(W) // Kill hull shields in the way. for(var/obj/effect/energy_field/shield in problem_turf) if(shield.density) // Don't attack shields that are already down. ai_log("destroy_surroundings() : Attacking hull shield.", AI_LOG_INFO) - return holder.IAttack(shield) + return melee_attack(shield) // Kill common obstacle in the way like tables. var/obj/structure/obstacle = locate(/obj/structure, problem_turf) if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille)) ai_log("destroy_surroundings() : Attacking generic structure.", AI_LOG_INFO) - return holder.IAttack(obstacle) + return melee_attack(obstacle) for(var/obj/machinery/door/D in problem_turf) // Required since firelocks take up the same turf. if(D.density) ai_log("destroy_surroundings() : Attacking closed door.", AI_LOG_INFO) - return holder.IAttack(D) + return melee_attack(D) ai_log("destroy_surroundings() : Exiting due to nothing to attack.", AI_LOG_INFO) - return FALSE // Nothing to attack. + return ATTACK_FAILED // Nothing to attack. // Override for special behaviour. /datum/ai_holder/proc/can_violently_breakthrough() diff --git a/code/modules/ai/ai_holder_movement.dm b/code/modules/ai/ai_holder_movement.dm index 58b8c9d5eeb..4ba8003ade6 100644 --- a/code/modules/ai/ai_holder_movement.dm +++ b/code/modules/ai/ai_holder_movement.dm @@ -16,6 +16,8 @@ var/base_wander_delay = 2 // What the above var gets set to when it wanders. Note that a tick happens every half a second. var/wander_when_pulled = FALSE // If the mob will refrain from wandering if someone is pulling it. + // Breakthrough + var/failed_breakthroughs = 0 // How many times we've failed to breakthrough something lately /datum/ai_holder/proc/walk_to_destination() ai_log("walk_to_destination() : Entering.",AI_LOG_TRACE) @@ -90,7 +92,9 @@ // step_to(holder, A) if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED) ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO) - breakthrough(A) // We failed to move, time to smash things. + if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things. + give_up_movement() + failed_breakthroughs = 0 return if(move_once() == FALSE) // Start walking the path. @@ -106,7 +110,9 @@ ai_log("walk_path() : Going to IMove().", AI_LOG_TRACE) if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED ) ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO) - breakthrough(A) // We failed to move, time to smash things. + if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things. + give_up_movement() + failed_breakthroughs = 0 ai_log("walk_path() : Exited.", AI_LOG_TRACE) diff --git a/code/modules/ai/interfaces.dm b/code/modules/ai/interfaces.dm index 59ffbeea722..b4323782d35 100644 --- a/code/modules/ai/interfaces.dm +++ b/code/modules/ai/interfaces.dm @@ -8,7 +8,7 @@ /mob/living/simple_mob/IAttack(atom/A) if(!canClick()) // Still on cooldown from a "click". - return FALSE + return ATTACK_ON_COOLDOWN return attack_target(A) // This will set click cooldown. /mob/living/proc/IRangedAttack(atom/A) @@ -16,7 +16,7 @@ /mob/living/simple_mob/IRangedAttack(atom/A) if(!canClick()) // Still on cooldown from a "click". - return FALSE + return ATTACK_ON_COOLDOWN return shoot_target(A) // Test if the AI is allowed to attempt a ranged attack. diff --git a/code/modules/mob/_modifiers/fire.dm b/code/modules/mob/_modifiers/fire.dm index 7f0cb81c4c2..3a3c53a9dcd 100644 --- a/code/modules/mob/_modifiers/fire.dm +++ b/code/modules/mob/_modifiers/fire.dm @@ -32,8 +32,11 @@ expire() else if(holder.fire_stacks > 0) - holder.fire_stacks -= 1 + holder.fire_stacks -= 0.5 /datum/modifier/fire/stack_managed/intense mob_overlay_state = "on_fire_intense" damage_per_tick = 10 + +/datum/modifier/fire/stack_managed/weak + damage_per_tick = 1 diff --git a/code/modules/mob/living/carbon/human/human_resist.dm b/code/modules/mob/living/carbon/human/human_resist.dm index 37e20d0d21a..56d42c1a15a 100644 --- a/code/modules/mob/living/carbon/human/human_resist.dm +++ b/code/modules/mob/living/carbon/human/human_resist.dm @@ -1,6 +1,6 @@ /mob/living/carbon/human/process_resist() //drop && roll - if(on_fire && !buckled) + if((on_fire || has_modifier_of_type(/datum/modifier/fire)) && !buckled) adjust_fire_stacks(-1.2) Weaken(3) spin(32,2) @@ -9,7 +9,7 @@ "You stop, drop, and roll!" ) sleep(30) - if(fire_stacks <= 0) + if(fire_stacks <= 0 && !(has_modifier_of_type(/datum/modifier/fire))) visible_message( "[src] has successfully extinguished themselves!", "You extinguish yourself." diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d53d307e76e..0184a54d594 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -363,6 +363,9 @@ handle_light() update_fire() + if(has_modifier_of_type(/datum/modifier/fire)) + remove_modifiers_of_type(/datum/modifier/fire) + /mob/living/proc/update_fire() return diff --git a/code/modules/mob/living/simple_mob/combat.dm b/code/modules/mob/living/simple_mob/combat.dm index 0f3205fb8c2..046a4ef9880 100644 --- a/code/modules/mob/living/simple_mob/combat.dm +++ b/code/modules/mob/living/simple_mob/combat.dm @@ -3,26 +3,24 @@ set waitfor = FALSE // For attack animations. Don't want the AI processor to get held up. if(!A.Adjacent(src)) - return FALSE + return ATTACK_FAILED var/turf/their_T = get_turf(A) face_atom(A) if(melee_attack_delay) - // their_T.color = "#FF0000" melee_pre_animation(A) + . = ATTACK_SUCCESSFUL //Shoving this in here as a 'best guess' since this proc is about to sleep and return and we won't be able to know the real value handle_attack_delay(A, melee_attack_delay) // This will sleep this proc for a bit, which is why waitfor is false. // Cooldown testing is done at click code (for players) and interface code (for AI). setClickCooldown(get_attack_speed()) + // Returns a value, but will be lost if . = do_attack(A, their_T) if(melee_attack_delay) melee_post_animation(A) - // their_T.color = "#FFFFFF" - - // This does the actual attack. // This is a seperate proc for the purposes of attack animations. diff --git a/code/modules/projectiles/guns/magnetic/gasthrower.dm b/code/modules/projectiles/guns/magnetic/gasthrower.dm index f42ae950617..742b5bd6c5c 100644 --- a/code/modules/projectiles/guns/magnetic/gasthrower.dm +++ b/code/modules/projectiles/guns/magnetic/gasthrower.dm @@ -9,6 +9,7 @@ one_handed_penalty = 20 origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 4, TECH_ILLEGAL = 2, TECH_PHORON = 4) w_class = ITEMSIZE_LARGE + slowdown = 1 burst = 3 burst_delay = 1 diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 06144e01f8c..e05739d194b 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -271,10 +271,11 @@ /obj/item/projectile/bullet/incendiary/flamethrower/tiny damage = 2 incendiary = 0 - modifier_type_to_apply = /datum/modifier/fire/weak + flammability = 2 + modifier_type_to_apply = /datum/modifier/fire/stack_managed/weak modifier_duration = 20 SECONDS - range = 7 - agony = 3 + range = 6 + agony = 0 /* Practice rounds and blanks */ diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index ed68723d154..c2ff36ea103 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -175,10 +175,10 @@ S.visible_message("[S]'s flesh sizzles where the water touches it!", "Your flesh burns in the water!") // Then extinguish people on fire. - var/needed = L.fire_stacks * 5 + var/needed = max(0,L.fire_stacks) * 5 if(amount > needed) L.ExtinguishMob() - L.adjust_fire_stacks(-(amount / 5)) + L.water_act(amount / 25) // Div by 25, as water_act multiplies it by 5 in order to calculate firestack modification. remove_self(needed) /* //VOREStation Edit Start. Stops slimes from dying from water. Fixes fuel affect_ingest, too. /datum/reagent/water/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) diff --git a/icons/obj/pda_holo.dmi b/icons/obj/pda_holo.dmi index add15b941fb8f8f727c8a984a75fed863a47c3aa..4e92a6d6d96dab3ab963da504f35804825fb4962 100644 GIT binary patch literal 7164 zcma)BdpuO%yWSH~aw|l{=!R5O6om#QN|J8mHl-xwl1nbb%&3sWl!_wc5+RggT*@dy zxnBok47rWV%oxTDGxp5c`kr&X=XcKeo%8!+f7aT2ueJ7C?|R;6J@30?&Yd-v5K|Nb z06^lD#fkF(0E4P9V4Vn5IQqT23EjAaUbG81;p%_g&)qk`-NzdMf?vla9`LT+FK*^G zBYUFcuvto3R?>Epr`sxotag7CBc0y8J>HvQa=c2IpCWGfEc4j%+e6`Wf~5L@vJ`!@ zZiB9kC8JHd=v5Xz%|4V=nIpyQbO0OcH@|z^)3fmF&@qpkL}w@e%PPm61a60w_tc$& zw@T~R72U6?4z`kBj{9MG9QJKb-N(2-{+he@RO>^(b;jQjdl`(dGkjQ?LAw`OHL>03 zWXZfjnCxw#H+K{1(z$t-B2PK{-)gz^_Z+v2diSa)dcA3QjmMNsqT&VV3*N&O*znX1 zmy5*R>l+Wm_q|M>e|`X-x7Mo@8w0*!6?%p#l%KPNTf;Ggbu%T2-#t>sH<;K-oXc}* zn!I?VZoTIEyo)whDN#EN-*sdp{h z8L2TQF9`q&2X8z~>2ad?zMB3sL=*QBk7SQuA06cj)Q#R5k@!F?_4(|2=#Vm}IeGlZ z#=y#{TqK?VzAL9Vb4sd@Z!(!1yuit3RVBlq=C`+of}3*})pj_G0Uz!5G6gG{T~-LN z5~P`r-U54t%?0f(iGseTcE1I0k1weX4~8tvn`TIBVlGDgg1-RC1QNzUzX%Szx!swa z{T3cj8MvI((;d)-Cx!Qgw8W z_nl-c1f`uEPnD^3^5NZ+0)U{l*RNiREt};!L=L;hauJg<)LTvnFm#si`Kj`$hQr@_sc-tZg+P~>b;Izve2B-a$BY(zaxDaUmb3@ zId0XI7+?s4uO{(s0FQm5W75x!zyLlxd*`{mfA>4ZRB!H7+X;e^ko1pBKz9)m7e^d? zT|Rgyq|zn#YWVT{pJlsO*E0R^WLAA#I^X{y!7jFUw`)8aCE}a;)rv2!Dl0ZJ;L9mC z0Ht`gqqbQYoL&a+rgJ82` zr%Go}@7;XdP^AId%IvVc=W`8iVRRME7W1tWib&baE=C(>)~!Ov(S%$GkC zPj`-fXS&)FvMglwzgof{Q#j(Pa?f(l*rZ`iD(|ynn}Lhms{8!exi-{|lJ-xC;Sne7 zn+w_(22FTXs22Cmr75X;2G7elGpZ=vuq!ZnM+I&Mw^BLCx4;LN7RLUYEGi5A;|g7uuRj(~DMTJR%SYrXA7j&ETox|mfhk6G zjIE%cI^)~36Cy{+M^`4(&zW-iUC&g3IxU#YuM#|VBgW5PS!ugo-OG+FBd;@RRjZC6 zI8n8*wJIpx)Ry=vH&d}0U6v4HpMBf6%bMU#2v;%gxNvXxdcf4;ZcW!c8JGRyfT?&C z%=qEA{lK~d3jf5*R~wyl2Ml@5I`)KbIVA1QwxUhsQ6h~9O8g4+B;Ndjq>`}dKBNf` z)frFEw`r26@JLrg)w;@tViKdw!vOMw#U_1uplHRjx9G>`sjg4owO0a%6B0H}zBqaX z=`h1R`)mq*37pNOst~*}#IzF|2cx27e*E}R)EmTm(=#qFh9$SOe0M>S6A}{Yl&{T} z->L3A_g_Ae<3e&KNHv0wL&T5iDXoo6@&({A!+oTWhCC{zEiP-q1Z4@S0AW-Gi_!;zFn-ledg<48?D6fDOWMt`gR4~@+ zQDoti`WXPQQhHvdi-|(+Ai|+XNjosD%)e!zv~!K|TckeV4et@c*A8HP!J6l}`Nw#z z1_0K4&mNgB<1JJ+f!p;Fi=}uWsx-`!X!Tuv62Q{(h>yrIh~6Cp%bNxtA&ziqcb)sm zVbR66YwqnSq+rUXA9d$?P)audbB(o9>Nz8?W;uacQ*`c6IQ>igVri+u$b6%#))JZh zsfj%UZ83q|suXwfZP~&jE>cr@T}^1cR^r?MvXo*A1Q0K}AcTZX)VP1QHWF$d$EQbp z`k}oQC`f5dLrFaB25+!+jIUqM>UIOje4g`?<0)vysQ9?{qtHY-e2(m4Xa7%Glr&hk zo~}hIY>c58Cpt?Uc3)xZ%=H#Jyln+8E=LNzG2D6*XQ_3^(YnXeSe-z|RdX?K>WcHz zon#xBdhdmR_ueI1qT#&J>z;S+5|TlRldX&GEK_^X-6=6#d^jgY#wKKZ=(*sSa4)|> zYX+vlQ^0Bx3K(n3r__CJ->#!i+{}Z=G^-JAA*wV9bmk1Z!R5d>t$S*vrKN?9n%hDP zk^?IGaAy&q8ZW#BIBzph?HI~+dxl}M2o@N2&?p5&5_(qG#OKXqBY0Iz3Ss=pR2x5k zrTQjdavTA&nidxxs6J45T!34X6kQt+&dz{dI5&Z9(opBJL*XVuJ_MDm4H(x+rK?sR z^^9_X;G_Rn@H7je@pao4X#^7{O)!#U73}-FPM0I#6)xWO`lU&jD^y$9r>sq7|EF)5 zZMWlHg&AL5TRjBCWNmg5IvZ!qEsYH(R<@rZ_i`ZFiu>wdh zJRp{O{&eLA;wS-xd{A2!s2IehNuc%QM%k4~i^>V*I}AD9Mpul`U7#k1Fek2R%j@{` zgM!wL@Aa|rWl52@YOj5wvFnciJ8}#kdB^NZu;n zv*#?9C?~e z@CEc2pOL^hY%Y)$MFpxCZ=aL*e(mbrXCr&iF6sfYtRw7`B!9O2qek-||uvcT9TV~)=`B(zSE3!Q>R>FUDU>aISZto5B$ zhu zEhipD={qOck!IeuSrEfMJWG=4nINv>BA-nt$c0q3d7Ikmi-y2Z&hCqUz0zb8SfO*b zXUy9UL8q<$t6X9K`>QAksuH{v1-9)(4Ojhxfc`%~{zqloC<33{+Ik0Y-j&E~cp5s8 zIwaVR&hQb^S{2w&{u0=lv?l2s-X(Tz7vnJ<6x7LBm(N2qbB!=ZjEENB$WRv@q}*cV znqNW~f-cYiwNa9R&Uw%5_Nr}FG=)jyVr|cmW(M^7N|KY~Q8!!WUqt;q8fJd!&a9W0 zoU{CgHMNrW)YHQ{F-LAea;rXrXi)a-Y*df6O6-qK0&5Yd&th$tb`%|4?bD4JMaAECWB1W{LCaI>On=;B!}e)>{6@HI56 zp^;hBDh1eyn%*D-EC=<-_mI$@^@#_JGvUW91S_ezGUR}xD-(7v^UrBKn0pfo%Z5W7BM8%fT(@MM zqar}T`7mJrh!REmsQ2)UV<#E%p!EuICvDD2hatXBq4D4x#O57^9wSePN8|D zflFdodh+R6VevIwkOLW*Sd0>obO4(NLaMKWq?L**j@&tN3GpfwyC@-XUZy<&b7ukh zf>j%P9&{u4OWRVDvBP|<6@Vh2B8go3&J^xP$T`}N zO78;?J$Xi9vsEbFw}8x?FA4{f>ol(`;RdqB#Xph%#D1bnHSIu72T z(`J;^%P3IRm*;j&B&j z$P?r#`N)Q{MZ;Qwdr@faRMO1kdJ{;x+QQdLZVN;#i#Tey#Ts%`Q5Sl+Qg7;IebLG*u&AIAeS8&nA$n>jkfUQr{S(m;O}x;bS_e>l0$GHumIHu zH>ASk|078L|9t#UBz;|lA-oSIRqsN4bOcpUM5D4xJ} zeYgRz<)hr%61lFAMe&Bbyp%=WEcJ^0;{EiAGYF%fPIUxH!lCza&;@{=+K0eb!&|sE-8s^V;jws<+n0!TOZ%PZaSxD zIrOlHxBEtC{PZg~ppoWgo~-jN`%2J;qxXk@bXE|TpU%*8)qfiDmq6u9mk4dB6(-LB zc#}WPi5RLrxGJ{G@((*M)-=Vp-4jHo+eu*qC;90G{l~?U9qi|7CT>Qc?`llBiJlvn zm!Cv)M+8swuX|2~SR$$PTv2SE4`zDlJeACFp4>BguwTkfs=COM$9ZFFT!y5oUcH`u zpm_gzjX@kgwgL0xGs|*SL|a)|4RHIBds9n^erB4pP|dxAySTon^?dZid0U>iohbpC>!DA`*3q6Kr2 zcs|uBPuaibN^x^qNLa|+&LV~OCgLhH3c(g6pxc6JI?;tTOY|;+0?ha@3 zICDWg%J(-ArOqg=8R13*2R%O+Ue8Qt$f>mme^K2E=%~DkC{O{9|MtsAA4G|$@)V3| z+(lDxHa{M=mz%$N-##erf7<})vb%&Vnh#fQh^V8;wE^cNv0%`Jn}8)hI3(#UCn@wh z?3}{x6XTJs;N0O7987=l6NxXk=d#8T5n%WQl&r{p-Am$|A+ID|+A7rEZ|&3Nv`)W8 z{6^=W!Y|ItDE7{+I?kpf4w@+<@||R24Cw)P(rMzAbl9!Ox*`KOXB(Rccw2I$L+%-q zD_35Xq3_yB@jF}b(n6d9YA)W%31<)xwAFMM`@WGQ;sdG4WMiH~>Syufu3}2cXV#XLNqm z$}LUM@#j>EYRYw5(u$ji;;Os4#t^(%?jB9exhD0rC;VCMX~vBWJ69!p!E`PHaqG2K z)5MBF{fPqz`rF&)@*&}3x>yC6VCcxwzqE{F zxa?A1V_Y821BuEiRe7!C_;tSr#Jak-?K}h@uKfx4&i@wOKUs*-4l}!IvWtlfMB_egSMA*d@po<3Y@v@{1ff^{BFI}Q70KW`( zy;KU|bUm9j4F#l4OGK+T{0n)7f0BH7oC{FxZMNRnqY1L0BagwIsmXg_!pZ8gMu2=U z?IsY52{%gA-fg*(P1-NFRpIU)Ek4sTCjAXq(JjS@{OGSXOlrgEF=aj@SHpUERXGq_ zRDP5>+MqqIQ1cs!)E@OP^uO9yXb;{OTRePznvF}%n$#UXyqdBQ^!*qzPz{l87d4`n zALpnkG|{p`ccLE#DF7-T;Va^>@L6|*2R&A9fj%cM*DkRvyc#N!9FHIJj{Yet$3AYe zt-bFZ%Cbb>8a6kE*=l;~)V1G!*Rxg>rvn}vbUjWW`=lD^i(9nl+K_hFgghMu3fugn&RT(j2#BM0z<^G_2iIS;7mr{I6Et(kum<0 zv7XF_;m1caKTbLuNh}${d1goN`w5frg0i$9`ntbSF-<5!u#nJ3N0VGSvx$W|CgMBt z%IZ|pn+_Ufu8*`@AzK&o*a(pOb@j#weFbf;gH70|ye?AHce;DGqu;5unH?JJf;{17 z3&FQT(KZm`^YGRghK>=` zLY}D_-8?w-Nj-;rC$`M1{U>74%X;PIFE3HNhd=JN_Ky}LMolC8ycbDTsO?WD=KN38 z=g68!hWBavO$#rp!tsYWANXc{Jfe|8FTsLzxUq&PKCJ#V@#lafG0Z5?rL$9)KW?BL z1K(r_e;p!P%atFwufw1Y$s&WNMTD`tFkikjy?yz>>P|yt5TC^T;j9?dO2W{Xg?%x_ zo061pdLq;Kk5bsF?IidLwgGqU?3@_uMI`szf+d!L5v*dT|1Su|bQhkr7qMD)s)ERIM?w0~9$eV6S?9r9D*32` z?pt(A=$N!M!!3G4#v$cvV&(UlLWNH?Gpabwx9Q&zW$Po57#|Va>gcb34gvf{v-7Oq zXbmab;i+At@5g_mBe<3)1KvQe`>AI~vN^cDZ&cc6VloSQ@Zx%dJ%_NeVhnoXe9WN1 zo0wZ5ezrpyE(PtlK^7Q(6>fZs4&YAd^)t9xH4mN)Mo>g{{`Wr_{|KZ1OoSR@l4T z{;&U4(u9mJBaUo40sp&lRxG~?o+`avln6U_X_03rr)0Wry^4zPzq%4W{CM-75{)~3 S!O&kl;FQ_f6Gf(1@BJH4dxX>g literal 6918 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