From f6b9858f4f6d878e931f124700c8ec36e96f2243 Mon Sep 17 00:00:00 2001
From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com>
Date: Thu, 24 Feb 2022 05:01:13 +0000
Subject: [PATCH] adds snake coiling (#15514)
* new signals for resting and stop pulling
these are to be used as signals that will cancel the coiling
* Create coiling.dm
* Update coiling.dm
* adds sprite accessory for coiled naga
* main changes that apply the actual visuals to the coiling mechanics
* adds message to coiling, fixes offset, adds action icon
* coil offset was using old direction
* reordering
* fixes coil sprite not disappearing
* fixes offsets, solves loadout issue
* follows lin's suggestion and adds support for slimes by making it entirely handled in handle mutant
---
code/__DEFINES/dcs/signals.dm | 3 +
code/modules/client/preferences.dm | 1 +
.../sprite_accessories/_sprite_accessories.dm | 8 +-
.../sprite_accessories/legs_and_taurs.dm | 5 +
.../carbon/human/innate_abilities/coiling.dm | 89 ++++++++++++++++++
.../mob/living/carbon/human/species.dm | 20 +++-
code/modules/mob/living/living.dm | 1 +
code/modules/mob/living/living_mobility.dm | 2 +
icons/mob/actions/actions_snake.dmi | Bin 0 -> 494 bytes
modular_citadel/icons/mob/mam_taur.dmi | Bin 59290 -> 62367 bytes
tgstation.dme | 1 +
11 files changed, 124 insertions(+), 6 deletions(-)
create mode 100644 code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
create mode 100644 icons/mob/actions/actions_snake.dmi
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index fdded58308..dad0f49832 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -359,6 +359,9 @@
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
#define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items)
+#define COMSIG_LIVING_RESTING "living_on_resting" //from mob/living/set_resting
+#define COMSIG_LIVING_STOPPED_PULLING "living_on_stop_pulling" //from mob/living/stop_pulling
+
#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items)
#define COMPONENT_PREVENT_BLOCK_START 1
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 3272060835..8d6646b8d0 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -3066,6 +3066,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
save_character()
character.dna.features = features.Copy()
+
character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
character.dna.species.eye_type = eye_type
if(chosen_limb_id && (chosen_limb_id in character.dna.species.allowed_limb_ids))
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
index 1dc50bfe73..f5e1c2e113 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
@@ -28,10 +28,9 @@
for(var/path in typesof(prototype))
if(path == prototype && skip_prototype)
continue
- if(roundstart)
- var/datum/sprite_accessory/P = path
- if(initial(P.locked))
- continue
+ var/datum/sprite_accessory/P = path
+ if((roundstart && initial(P.locked)) || initial(P.ignore))
+ continue
var/datum/sprite_accessory/D = new path()
if(D.icon_state)
@@ -64,6 +63,7 @@
var/mutant_part_string //Also used in species.handle_mutant_bodyparts() to generate the overlay icon state.
var/alpha_mask_state
var/matrixed_sections = MATRIX_NONE //if color_src is MATRIXED, how many sections does it have? 1-3
+ var/ignore = FALSE //NEVER include in customization if set to TRUE
//Special / holdover traits for Citadel specific sprites.
var/extra = FALSE
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
index c525a13ef8..11fde50a37 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
@@ -126,6 +126,11 @@
hide_legs = USE_SNEK_CLIP_MASK
matrixed_sections = MATRIX_RED_GREEN
+/datum/sprite_accessory/taur/naga/coiled
+ name = "Naga (coiled)"
+ icon_state = "naga_coiled"
+ ignore = TRUE
+
/datum/sprite_accessory/taur/otie
name = "Otie"
icon_state = "otie"
diff --git a/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
new file mode 100644
index 0000000000..52e2a87a7d
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
@@ -0,0 +1,89 @@
+
+/datum/action/innate/ability/coiling
+ name = "Coil Grabbed Mob"
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "coil_icon"
+ icon_icon = 'icons/mob/actions/actions_snake.dmi'
+ background_icon_state = "bg_alien"
+ required_mobility_flags = MOBILITY_STAND
+ var/currently_coiling = FALSE
+ var/mob/living/carbon/human/currently_coiled
+ var/mutable_appearance/tracked_overlay
+
+/datum/action/innate/ability/coiling/Activate()
+ // make sure they meet the mobility/check flags
+ if(IsAvailable())
+ // check that the user has grabbed someone and they are not currently coiling someone
+ if(ishuman(owner.pulling) && !currently_coiling)
+ coil_mob(owner.pulling)
+
+/datum/action/innate/ability/coiling/proc/update_coil_offset(atom/source, old_dir, new_dir)
+ // update the coiling offset on the coiled user depending on the way the owner is facing
+ switch(new_dir)
+ if(NORTH)
+ currently_coiled.pixel_x = -12
+ if(EAST)
+ currently_coiled.pixel_x = -12
+ if(SOUTH)
+ currently_coiled.pixel_x = 12
+ if(WEST)
+ currently_coiled.pixel_x = 12
+
+/datum/action/innate/ability/coiling/proc/coil_mob(var/mob/living/carbon/human/H)
+ // begin the coiling action
+ H.visible_message("[owner] coils [H] with their tail!", \
+ "[owner] coils you with their tail!")
+ currently_coiling = TRUE
+ currently_coiled = H
+
+ H.layer -= 0.1 // LISTEN I HATE TOUCHING MOB LAYERS TOO BUT THIS IS JUST SO THEY RENDER UNDER THE OTHER PLAYER SDFHSDFHDSFHDSH
+
+ // move user to same tile
+ H.forceMove(get_turf(owner))
+
+ // cancel the coiling action if certain things are done
+ RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/cancel_coil)
+ RegisterSignal(owner, COMSIG_LIVING_RESTING, .proc/cancel_coil)
+ RegisterSignal(owner, COMSIG_LIVING_STOPPED_PULLING, .proc/cancel_coil)
+
+ // update the coil offset, update again if owner changes direction
+ RegisterSignal(owner, COMSIG_ATOM_DIR_CHANGE, .proc/update_coil_offset)
+ update_coil_offset(null, null, owner.dir)
+
+ // set our overlay to new image
+ var/mob/living/carbon/human/user = owner
+ user.dna.species.mutant_bodyparts["taur"] = "Naga (coiled)"
+ user.dna.features["taur"] = "Naga (coiled)"
+ user.update_mutant_bodyparts()
+
+/datum/action/innate/ability/coiling/proc/cancel_coil()
+ var/mob/living/carbon/human/H = owner
+
+ // cancel the coiling action by removing the overlay
+ currently_coiled.pixel_x = 0
+
+ currently_coiling = FALSE
+ currently_coiled = null
+
+ // unregister signals
+ UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
+ UnregisterSignal(owner, COMSIG_LIVING_RESTING)
+ UnregisterSignal(owner, COMSIG_LIVING_STOPPED_PULLING)
+ UnregisterSignal(owner, COMSIG_ATOM_DIR_CHANGE)
+
+ // change overlay back to original image
+ H.dna.species.mutant_bodyparts["taur"] = "Naga"
+ H.dna.features["taur"] = "Naga"
+ H.update_mutant_bodyparts()
+
+ H.update_body()
+
+ H.layer += 0.1
+
+ // remove the added overlay
+ owner.cut_overlay(tracked_overlay)
+ tracked_overlay = null
+
+/datum/action/innate/ability/coiling/Remove(mob/M)
+ cancel_coil()
+ ..(M)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index bbe2781403..e6ac8ae881 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -612,7 +612,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(Q.type in blacklisted_quirks)
removed_quirks += Q.type
. += 1
- qdel(Q)
+ qdel(Q)
else
var/point_overhead = 0
for(var/datum/quirk/Q as anything in C.roundstart_quirks)
@@ -906,6 +906,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/tauric = mutant_bodyparts["taur"] && H.dna.features["taur"] && H.dna.features["taur"] != "None"
+ // stuff for adding/removing the coiling ability if you have a taur part
+ // if another action is ever based on mutant parts we should probably make a system for it so it's all done in one proc with less overhead
+ var/datum/action/found_action
+
+ for(var/datum/action/A in H.actions)
+ if(A.type == /datum/action/innate/ability/coiling)
+ found_action = A
+
+ if(found_action && (!tauric || (H.dna.features["taur"] != "Naga" && H.dna.features["taur"] != "Naga (coiled)")))
+ found_action.Remove(H)
+
+ if(!found_action && tauric && H.dna.features["taur"] == "Naga")
+ found_action = new /datum/action/innate/ability/coiling()
+ found_action.Grant(H)
+
+
for(var/mutant_part in mutant_bodyparts)
var/reference_list = GLOB.mutant_reference_list[mutant_part]
if(reference_list)
@@ -1220,7 +1236,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!HAS_TRAIT(H, TRAIT_ROBOTIC_ORGANISM))
H.adjustBruteLoss(1)
else
- H.adjustFireLoss(1) //Robots melt instead of taking brute.
+ H.adjustFireLoss(1) //Robots melt instead of taking brute.
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 2070d07e14..bf3094cb08 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -395,6 +395,7 @@
..()
update_pull_movespeed()
update_pull_hud_icon()
+ SEND_SIGNAL(src, COMSIG_LIVING_STOPPED_PULLING)
/mob/living/verb/stop_pulling1()
set name = "Stop Pulling"
diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm
index af34fb54cf..6aed30ab83 100644
--- a/code/modules/mob/living/living_mobility.dm
+++ b/code/modules/mob/living/living_mobility.dm
@@ -9,6 +9,8 @@
resting = new_resting
if(!silent)
to_chat(src, "You are now [resting? "resting" : "getting up"].")
+ if(resting == 1)
+ SEND_SIGNAL(src, COMSIG_LIVING_RESTING)
update_resting(updating)
/mob/living/proc/update_resting(update_mobility = TRUE)
diff --git a/icons/mob/actions/actions_snake.dmi b/icons/mob/actions/actions_snake.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..6856171b0d69d1b5fafdc9bb76eb4ed131ed8ed3
GIT binary patch
literal 494
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
delta 5835
zcmV;+7BuOf=L4G01CSSgzz7Ba005mY#P0wA0c?6ySad{Xb7OL8aCB*JZU6vyoSoK9
zPQx$|hT(O5icz~qv{dY}0HvTJwIBrR%Bm-cMQT^JNr2O{pg-;c#5V_c^=Ky1BxAar
z-!E2FEf=ci5UqDq((K|=6@xXYrIM~^s%Y6ZZK9H{rYa_#m`WOdZP!V^hjr^iMU
z@cJ}Tg|Q)0Ni$W{L2o%yNt0iayXVK%%YPG}EQt7IL1W_wjM(@A7vj#R#0HlRAtq{P
z9k{uD13CPWf);6KC1g6?Xv}iD(U@U^egg;kNd(&ySa~Rz%Xi>=c*;P{8V)FB4F}mC
zaqX)dNFEUFK`7vidiT0WMdvvTTI+3!>)FgH$VwN$b
z7;6>dW>c)CX}6Ja>>#UH7Hl2X(pm=WG7*TG6dRdn8&hP+-9NtfmtROlur2TR$nSh+
ze)IC)yDxL!Iq$uD?z!iln<#%)W8t+L7=JfBau0L41EI!0T+Z<1oAD$6
zukYaPIMca3SQrD$Y6f~Be8u07Twq5nupcOb>e&i2ZAYW+%UWP-nY<~tzJqRUtA&;&
zvFt-S7AjqjgUL8Rnktpmp=>LJC4VZTA7Y^&SkeMbWhy%r^$lzHp*VktnGhzqe3QnG
zTA&x`h2}Z1A9>~{>JU!>^JCc~K>0?X5O$X7*dCPmCh27Wf2mJvuodObW(Gpbcu<
z;5lF^O8LYzCSqu6s261AkdezSBrAF(%giq$(?dws
zOq1-FB3;zB0d2rYH-2+QH_!?6$+)dQ0KY=tub%?d-3lWr?uYVj)LA(O#p`u>A?o1d
zqU!mI#{eh9ZwLKRh|&m+1>T5%AF0t$@6nvp&T*1qG+H%mun~WJ1JHAZ@>TV^D9rFi
zJ=cT&SK
z3X&C<4v}G$=@m%UO>>p;;ZmfF%*A0re#kJ5gsUWb+irn=pcATgX-f%kA5?V%ThL_Q
zScU>9-V84-m$!fT0W7R=PjDi*0h}Pe1^5swXoZ$iJ?w?R1YlD9y#h2~VYR;i&M@Lz
zSeOXRZH67?Y7Yv?wgDwAu(=E##=@5dJ^NvezXxd|ln1*P3!fi!>A|!`8J~19(XTbe6#=
z-~eZyJ?(#_iw>l}cI41nftKS1HRdCT#vE$*$0K7eb8am#qYjR)Q>e?CMgfKsJ?LI9
z0~XZ5%j@LHJ&9y9p6ntDFChoX$wB)okR#;)vYQIx|8mktxHcNXn=G&cDZewGoQe#B
zQ^*EDx_pEDcn{Ko8^8(i1%lc07TV{+)c*kHp$C6|5^xCqWh3x5Jb$N#5#PX#U}t#n
zX8esrArQOQ!n}HDUIXRzuzR)6|6x#BC%ueAtL(`
zPpup1|8oU!dA$B$yzWbR@U6RzU=L#Y<9p|sY5%h>>Quy{lc15?5+V6>F-eAbkuai28fFA*K
ztMv&xft*>r$g>N`BAXry&jTjQu)Doc9i4yUz%hVA8FQ5tiQYm^sjSdFQz#i6M>4s+
zF&e*tXHV@AA)_zbc*vEkUf+0>49FyZ0gQ@2`;8TJC5(E1IDun$;M
zjf|-t2ut%rb{8VnXn{`xKS$4fW34%p#hB}
zkLAj_qqz$
z1k|+X_{FizqQqra;h*!owB=Rk^8J-r|$s62Mw5{Ck;3u6~U^c<+zr-jCAS
zbO04VO<9Z;M)8mb@X2t_g^fLKVG^*gS#d8JF`^J&1|>t!7be7eE|d(q-o5l`ScL@^N11=mmkwS*I&sp8J*a%Z
zg&P#%GSta`0%b#+wgKpg<()+E5Qqe@8Vf8!v0wYpgogKPsKeG<;EyN-Vg{NR@wCo0
zAj6>$&6)dOJQTvYu&~V*n2m-rZa^*dRNx?l)xoU60#_i{Zwc@dG$gVQ!g7Ds)5tO`
z)B#0p=zCUzR%n0t7_c?#2|g2dV__!pU~)CE2e<}!0Ydfg*16SM7<$jG)ry3;>nz`P
ztFXWl;1?)s&<p9p`FK5@<)estj*=h^x8x#q&XbsZq
zG+?_z#Bx~myuc0M^UOeu@0dXc-_~Zp0EU5N*g!TGvPOSKa3*D7U);J8>|7{VqXi}*
zm)C4$=*CG=12Mo8;_>NmI|DfCvA}8O-MqbLGk~qm0w>6h1A|;+BhDT^aiL>%7Bcrb
zK$OMV?)@*3xsw~LHtMWD{!SqWSV7hRrXSe{1)Me}KioTmX}}F&$8j9TaqyfV8{8hu<$w-_F&;LU!){)9*eSn9SgYp9mjE;_lT!KbDa0U-U=IEL1Bn6U*o
z0!)VfrC^?;`MeUaP%ud5FE7>F856Y2CtUuHU&
zp95|M=0HIO*irXJo-gdEg@OuT4wCujq=V5&Czq>~%inPv$2lu*0H+k&XTiEGyp4tb
z@YM?^8=tjDEU8PFT_>?#7IY572tha#CwZLbAX5f0XzIzvhrLLDGu`L!T
zLStClfpXw+=&gpo87SpCNsa7-M9gq-*^Z_iV5q2u@~rt7e5PE1Hbnn
z#hmaK@NFBN8RxL021s1jujo&h0mK%S+
zj^m^oH-OX5)xaXSsu9|O-dxuw57`5>0t>2vtw0|zUB+)tE9OWC(~(ZLN=L0oXHIf_
z3@8DZ2|NY7nA7Swj^msaH-OX5Wk3(mr#59rj;oW8T!W$==m)+6{0s$}I_Y2v(#cnV
ze(CC(oK`6R=m36~*|`x|l)Jh(j^lrv3vK|Xo$bIbc(Dq;2wa)#`s67m0X~g}+K)n*
z=icA65atErDALWRqpqAp>5e}@9^hTMtBd0}&be?=t}Ec2g<{|oTs0cHR>}$KB+Ee1
z^Is|0v7XVr1ui4x!ipisL3e0ocQ90&G;+`v}@Q^BTM2xWiTQM9Kl@EU(`6nXD2
zg>a*HC>_U17WV+Boo9e&_2+g54Kq54VFcR+>|KR=AVr?*H%(YY%m~ph9qqzb!2Mt{XMZJ3rt1%>aGQ5>t|d1eR3QpSv(C|f>?t-@?rHmcty@|&URa1
z3^dPDDDaoPVb2L2SlAB~0keOrQJ`r%a1vUULD^QI07B`X>gNYoSkj`h4=vNNFS#C1
zGja)+
zpd{wKC^TYzEPMnumdjyZwlf~v6Eoj9PC|GZwEV_Bz)A8ZFe_{9X0U$-3(Sh=hw?md
z7(RiFFDEx#MzE1U8_-q@JO?ZV%3vBmDR2m^&B70`U~So753%ensBF{kVJtlCDeVU2
zkdX_!fTil}4VGa>rW^uFqs+@xmgl6CHee)f{N{>opc5tJ*jNq+>VaRO1!8^*-POQe
z=r4xua&=aY0qcw7KPZ2U9URAToCNR~;G`K1+yFM%__+bK`0qe{l`ff1u<1$E&p9L4
z5v(Jlx5+3xr5olpq4a2<0j9?|?VGaKT?%jt#XCklSGL8IH)o%NeDMkoHv9+Vka_;6
z0H>nN2FY+hrdI%4qs)JZ3Qo>mdR?B#FpYdH%Km9A^dn<2)pB3Pq^u+sJDIL`US4d8^ZjTRUU&2yoA2Wk-t7-$7rN}y~r*h3aVW%lEL
zr#I-S;x>ZWdJBAh(7`u=vB0;0K1D`wBzyWGXqM1y;KyiUV-K(sDxX2_%nw85HVfhA
z;jM3Lv(cWb{s4af1(iueK~%sZ;8oxd(1PRvuoGAe9FH;^B*S)qUn0-@m&wXJa&rfS
zwZmI>7Yd&u*r$O1L8Bk9qQR{ND3xO;atfaS=AsCeR^q|2zy}krvg0^;h=)KVfVIRW
zjZ2`s6V{gi2eQA05-95gZUJV-@=p5cKt|e&z;A&SXf}Tks4?#xwErS79vOR?b8De)
zK|KFFXB-6>R`j5ICEoj5vKCP>l2K+6g_j1M%j~Z}vVIZCz9WG;JAW2`Pq2T8p+h^6
z%AQ1_4`X7PQ^3WU3kp!jCLi7d$8mCwdw`SR&G;J$jE1$lp?)5$X@>f8SiL)*|HGiN
zPI?)K*4uyWjQd^jSUYf7d1yBktC8Ey9MVxvZ@aFC~yKAZjl-@
zsw+f;05da%+i?TfahybO12_qephh|~wAU+J7~+4n7kNM4hddxhhW-O5RTKd~g6cA;
zjoBRrRsk5H%{Ua<@EQtH-A~rATe$^UbjM=a+AgT5O!5YDOGPC-+8pow7?Q;wpz(G+
z{*#eGbObqs55*#kK<`Q~8b3cYNC!ScG_^dwPDXD(N(eC?rPQ8c;o8=3jy#V+)un+ix
z>(fa9PlJ}i)4iqISgcEYNqdRHz2>KcK?@Z>~=d4J7y=_G_3!1;|EzzOj{
zO#L*5Y>3+(1iL>TA4fLy*A3uwV|5m|1L%O3nKIBOp$7dng586KLS(EB4QEuIT6s4|
zA|tpR8GiZV#e574uc1MY{mAg0hKzsO6GO_5LvlTijNJc>-s7XlI4;|d1bV+OqL60p
z#lqSRz(Ul^-v;4+-LJf+GYzZ07gM=5mfJm+BtvczuIZx
z5ZQaKj^PYE17Z2u4WHWxwhRl8wnA+wS{wW$4CDfKQp_^cTkPiaNf6yAJZv#gm7A(L
zj+1|Q8nguXJ{Fh+%?p7(XeuUV_Sd$lSjU?e0yE$dUm+~r>;PU-rib}JU8&mcW$#6A
zUBKZu5$t7{a2~3eRwe+v9PfYqFxkN9b6^=379*L@M>^mYq!TBVd?)4u-cX2wzK6Q`
zPXMQ2!!(VUe8<0kj^iYN8^Gt8N3bvr*m%8`Gj5zMXK%wAoo`s9{l?ikzwvry$#Nq&
z<&09;!*j?G+Yc<^9F5>kpbKi}YCz!YOXa}4I}dbzHx?$Nd!B}5Ko@`6lydLFGAt}X
zvYwA*KMArqwVc#(KNhY7u0^rhbOPP5x-@DSKK}kZco!VU$t@lOe4cp#
z3zLACkzw18;u?>UjRBqzk57-=87RilV}aAlyBWGoXVKd|SU5p;6d2?f8^Q3O%ykbI
zGWVJxBa5@$`(Gk+CpR}_I(7Z=cZzJ*$NLEO)wpc(n0RckN9HcqsdJw37~uTo{{c*x
VBdbs;W@`Wd002ovPDHLkV1lD*