From d8bf59bca068842e1046ee3960f8662ab72bc4a8 Mon Sep 17 00:00:00 2001 From: Voyager Date: Mon, 31 Aug 2026 16:03:55 -0400 Subject: [PATCH] Add starter RV progression and fishing feedback --- fishing/fishing_spot.gd | 4 + homes/assets/starter_motorcoach.glb | Bin 189284 -> 156012 bytes homes/assets/starter_rv_interior.glb | Bin 0 -> 15564 bytes homes/assets/starter_rv_interior.glb.import | 45 ++ homes/assets/tent_interior.glb | Bin 0 -> 9880 bytes homes/assets/tent_interior.glb.import | 45 ++ homes/home_decor_controller.gd | 15 +- homes/home_world_service.gd | 503 ++++++++++++++---- homes/player_home_state.gd | 81 ++- main/main.gd | 411 ++++++++++++-- network/network_home_service.gd | 80 ++- network/network_protocol.gd | 3 + network/network_session.gd | 3 + network/network_shop_protocol.gd | 3 +- network/network_shop_service.gd | 145 +++-- player/player.gd | 83 ++- progression/player_cooler_capacity.gd | 75 ++- save/player_save_manager.gd | 28 +- tests/economy_regression_validation.gd | 58 +- tests/home_spawn_multiplayer_validation.gd | 23 + tests/logbook_runtime_validation.gd | 8 +- ui/fishing_danger_vignette.gdshader | 10 + ui/fishing_danger_vignette.gdshader.uid | 1 + ui/fishing_shop.gd | 76 --- ui/fishing_shop.tscn | 29 - ui/game_ui.gd | 153 +++++- ui/game_ui.tscn | 27 +- ui/home_decor_toolbar.gd | 142 +++-- ui/player_menu.gd | 5 +- ui/player_storage.gd | 6 +- ui/rv_upgrade_shop.gd | 330 ++++++++++++ ui/rv_upgrade_shop.gd.uid | 1 + ui/rv_upgrade_shop.tscn | 14 + world/decor_shop_interaction.gd | 8 + world/fishing_shop_interaction.gd | 8 + world/generation/generated_world_region.gd | 156 +++++- world/generation/generated_world_region.tscn | 6 +- world/generation/terrain_chunk_generator.gd | 13 + world/interactables/decor_shop_world.tscn | 14 +- world/interactables/fishing_shop_world.tscn | 2 +- .../interactables/rv_upgrade_shop_world.tscn | 36 ++ world/regions/starter_island_region.gd | 20 +- world/regions/starter_island_region.tscn | 5 + world/regions/world_region.gd | 18 + world/rv_upgrade_interaction.gd | 15 + world/rv_upgrade_interaction.gd.uid | 1 + world/test_world.gd | 26 + 47 files changed, 2268 insertions(+), 467 deletions(-) create mode 100644 homes/assets/starter_rv_interior.glb create mode 100644 homes/assets/starter_rv_interior.glb.import create mode 100644 homes/assets/tent_interior.glb create mode 100644 homes/assets/tent_interior.glb.import create mode 100644 ui/fishing_danger_vignette.gdshader create mode 100644 ui/fishing_danger_vignette.gdshader.uid create mode 100644 ui/rv_upgrade_shop.gd create mode 100644 ui/rv_upgrade_shop.gd.uid create mode 100644 ui/rv_upgrade_shop.tscn create mode 100644 world/interactables/rv_upgrade_shop_world.tscn create mode 100644 world/rv_upgrade_interaction.gd create mode 100644 world/rv_upgrade_interaction.gd.uid diff --git a/fishing/fishing_spot.gd b/fishing/fishing_spot.gd index 8160eec..fdfad53 100644 --- a/fishing/fishing_spot.gd +++ b/fishing/fishing_spot.gd @@ -684,6 +684,10 @@ func _is_reel_input_pressed() -> bool: ) +func is_reel_input_active() -> bool: + return state == FishingState.FIGHTING and _is_reel_input_pressed() + + func _begin_aiming(player: PlayerType) -> void: if state != FishingState.READY or _active_player != null: return diff --git a/homes/assets/starter_motorcoach.glb b/homes/assets/starter_motorcoach.glb index 5b0d0225da3af0dc3978f6b0bb19562b571ae8e3..becd54edcc889a1754cfb1e1d6fdffb43e5bf8b0 100644 GIT binary patch literal 156012 zcmeFa2Ut``_dkB`T{YOSmsk;vK}B447g%8L%-T`0_l^_=#frT_tXN`i!A2B&BgPKw zU28N^qlp?dMzI@PP>EuR`Jc1w!0gK6`h5TI^FH6-^Ywl9oX?*9%$YMYch1Zn^ST3~ zJ2jI8L5S`r37ORdp=HOmZ6>()i;0OC=^ik_eL%#Jh!Oop4jthh;NB{7#Lyu_W84Nn z6Sqdu5ktZwM!2+kOAK00DVOw`aJK-PGv-6wgvM~odAF$7I9ons=x z-2-~Mw+iaecW}Rv5hJ4dMaT4w85R*XD!ShY_uiiFF=5b|dw|-CVt_rteMrB-U~}(i z`OMRO$k6Zz{6O7%60~6NCb$odh>5f`W&Dx-MnE5}heGIKL;HnAx+6cQUyJMTp`${h zBRWQfV_+jkjEdmH#lbrW6+U5MH|rN>nH%*a7^}7G5u^K#>^B4^V_4{j))6E7MMp=4 zbr?EoK;)2!7zllWduYFyh{i*shmK&ad#b&BeSLKP8h;;ey|2H&ug=#~?d7A@`0Dlk z-adX{*J%8}r1SBEHyR(cx4*_$r_p$Nr z=ciTs`or_&uYm`U?I=HuMyJ-p2z_CQ|CIqnM-7M^8S{w?=I8GZ`^5)F;-}X6dEXd>O9?=(#pg)}xx z|V~P-z3Y8u3s2DXE8%Z;2jTc zN~8Msj~LM=Am(mKeazPjGfItnhXJ?r~;sWpDM z1${OCTCLUxwkm8?y`Ng^@8<()7xrp>jhC;VR_mwLXf#?MZ?zvbA8857y-U-^TDbYz z1`k91Xz=;9hX?f&+G{@OA0CPi+gps5$%Cu|512K8j*S}zH|+3%3wT&Qbdfv%{{EI{ z#5(_4ouAs@U#r$ZeuLu|rqtgLCfg5gJurjtu)zfS`upnD-rjm2U$vjV>*1>gTs&b-;4-Sw>$Q5V4un6y1+@4*L#Kxw zr1!%ep!M^ICmxO~o!Zx18Jh=gwgsn+TrKPx0{K zD&X1hp@-aM(0Hq1Li67TcxZg+BX=EOnsS#xi`N-njm}38k2*ZbS}&d2Pp^fG06gA$ zZ%kTwrIMUXWVZ}B>G0(bQ#`bRdtWxTl#@|g5I_g?O# zduuRte`L}v^Xqv3X*CdK&a?kP_JL&Y4`0FH@(-6xHGUQIhw1az=`=oY3xf^e$3Oe< zoel14Z~~|`K6*dAndOmwG;saY_`r?=j#iE7D|Zg^cy#mJ|G5v1CH{OJd}R0AImlxb z^4xy8tKjSR(FBB-ko+DcZBG8Fuk(TjUZ>Z@^)g5Xrv>##GOAAEr8 znBO$w-RWaP$hZARHa|{5Zu<{c0dHp?_Mf{7@Wqt1cW?~jgZ`n1+$RaXHdr?TTx8&z zhL7IY7fKHB<=5LE=Fk_Pc3(9re>kDNVG-aPhrgfBM+5W!!6Inkn~5*%5ICXXri1q; zc+h|cIUiOPc86zuZ!bNZ3GhFEEoeO5Keh&W<^$Ui_%M1>};g<@`F_G5A%8O zTg>kvv~B<465!SU!}hsL;Fr6EYz1IMx!(r(ZwHod2BG6dMg&I;888xxz)<(WZHT6} z{rg+$*m$|^H(~&mv|-+T;R_SHo;%ap>d;vazL4N-yVpP^3bw7Y4&eI;1kA?|dDI7| zgd2n9J81Tdd^iSgC?VT<@YmzTh4+x}EPUtzPES90LY(#B2M4Zg2tM#&e!@a%ee50h zdi&v*Yd(T}XF&(w?rcNwg?qrK%)*Br{QTiQXB$I)^XLyJn{5dGTFA%FJJ4aR$mUt_ zhVsy-OatU@yAa^}s#b$Jj(eQ)8$=!+;M+7@qn!5O1Lug{DBy~v|Acwa=rAYnd%_!z zF#BDV-{S!HZM$s=HAJWnJ3orNJiz_$6XrqVgO8uhDBvjgq>ZVyf1tc!W7@Ap{_|kJ z6j%WHgr)d!E#U&E`=nX0e;{>QxMMiK5KyYOokShfyzK(WZwmY{TANkS!A}2#DagwK z9OllC01hGh2%s|Z2~(iK6kt09U++)Z4j*J!tT}(m9OUJ|A0JL<(@GxCksth>r}GY= z^k6>+P)M?iK#PCxn|)4NZw>ra0dkP98Y+)&ZoL{wLZcRKga_YuGf()ky)ov7%FN?K z+q#>T3ayPLE4!FOqk5X(oN8)pv{N)68Q#PE{&EZBv)gYJ9wXlj{9hior|4%Q_zZb( zw86;#7ut>v`jYY({l5kOYy9=J^u;0O?W-S9*PeyVJnnLCsJTzSbXvu$pm|UEA?Co} zpVGB${!v<19&CPI@fBV8t7PUe@`|>d5r#L@PDbQ zC%rIbAB~@~f<$*3PWv>HjSQbEcGhBdX_iRiCV3kd00(iMX-6#f@EZf^isKh8c+|pG zv{6$(3&-{5KpK}+-{Pm`qE&QJ&#va)KAns`hDXuxjq&C+-*mBHwD$qKYv)CT*%34T ze)^??_SL{geDp@5c`U@RXJ`qtS4N*4{7-6v1<$Qm&wO1PWR3$4;xE>&w%9{@DcD{f}vLd@pj&4r(G#*4T|md1G1eE=mF zqA8C(+SM~&n%a@JUz$Lj!K2fv8mlj!N-J(ipw8e$rQMCal*M$__tBKc+vgTFMl7C7 z-zO$eXYi4}MU5|Ct)V5qi>5s8U-1Q<>oJ8MNJ^m2;3L2MN&kAYkQ(=Z9}W+buFzvk z+R!n}6R0zINtaWU{2fA@osXtGURL}(9aeV>>6no~9pNI?6uKaNGpRTzn(~-D(;MTj zZzjVcqA8DcuNoK=^;^hqFB7OE+-;MOv1FYny0uRf<#AbUE#t_T<@7?2D9U4FdR1f3 zlGErP4-%*|xYxLP#+{iRY0BdS>I~jDr?9a>>m*tzGK%uJ1FZYrnqSj*PZOv!ctf@1I@_2{oXS!M0L^i?m;|PZY8;s}f?;=$+gD8(DZc!UUc5fn=p{*l~d-gKy z--j1m%{<0E)dTj|;nS{W9>>8xtpfYB|8qC9GZ^>&ImiQ39=e&G!KYzAX2O1~2L1AQ zAFOW}?Cb6sZf0ljCD?<1!hU=Ret69GvMLv8upmEe0T&>lg%2O-f5nk|{ z-dv()E2C!hSjuDM-x-i?x5r}#pCRudhG~8s&6~rISa8DJOl8r+Q*=hRanxD-s7iBV zlRaZC{Ey+XKECG1z;6e9N4S5dHs)4Q7wMvQI`IUHyVqt4)# z!G9`|zz+w$BaHKw2=mq-I5@Y%U_KF__&QVhdBG|A+|xO%hq1f{eg^QJ!5Gh>{;iCO z!$U2xF^v5luH4+XJ3iDB!^d#OCB1onjaJ5u;D^T}b-v~$;O7|lafFjQwlNotyhz{G z3Zstjz@B<@-0Y^t{%88oDz3ifLLGuEcB@ zPf{!MySXPU*fjl>!m!Vy=Sra}r!Dq%)W@vN%Jx%n>nmmU(QItE)Y81s_>+Zm#Qn9h z)r#HEy;PRFp0(J=b^Tje(5s0hp0O8On;Vb1YO!ZV`kDh5X4?;?O6C%scheum=F}dy z=&&xw&hWDM8ae#@Fwf5m5A0UJjP}vPT2p(B@i05X*cbBMZ*-*jVdOJTUKn%NE68>6 zRSTOj*D;K_t_t%M_1mIGCPBDA7O4pz9WqJ%@uN; z#}B2AlD(r{8k+DLvTpJ4{&qHEzHg^<{8G%5A*!IFy=S3XT2?Cw#Vq7*%`*ZkiTxZ zi#b1xe8$NWmmtPD*F%lE1+D1w9~&9}{bqns19<$<#2ovHQfqST%YgslQr#T>SCwm9 zFmf2iwu}=J)5O^Bn=p&dyzs&9U(p%zYGWJV@EBuYcEs4$yGnMyX!o(=nnTwZ!(u%x zF(9tu+s}dg^{Slw7)Q~?Vg z@$ybxEI4gXDJod)h*w$deo`yb_1-V&9`8n!$L}vMP2=r`6MJ(w3?ql(A>A*fUGMxC z-QBRI#gBXXU(~aH3mc4_z_SN)IIkKX%;7McS!Iz@eAi&3TGN$om_J9^vwpY*|9L2i zF#CvhK7`qkAAQQ5>a6_BFH2i6au~+8jB~&7EXA|c5R1=`;gO}r&?(Q|NnPOc7-M60 zdyGB{ba$g;p)FzoFvjKxqaPP5CqG=w>hoZ@OjdOAu=q#31Tgx~4>t*pwu~1!`C%NR z*P^+~G^@}2aJ)4JvbI)isqo{+-$pMqUa4X2E6 zk6FKH&kv_{C~IV#yfFGtwQ@d&alDL^AI5mFFE&3P!$td!HO&4kJI?%Y+0M-^V?j=S z82e?Mk74YWaXyB>+CEq*4>2I$SsZWmk9=n^`p5NR{`11UeT8?dQT(NF6 zP4`BXz-0M*#nZ=VAMxV@XkC`8|JHi-G zq0Oap#>Fs>YtGPeIrCtT(I?~BW9Ad>jxff|eDWCMWHIE0*;tTckC`8|JHihJMk;Ub zHn+50>aI?GW5sB{CYH;w|6#@N20stH5Lw=0M=ZuRv*7n71}o>ScEkm&c05C`!Fk%; zvw)e$cvkZE060$>hhgL}jA!LFI8U3Y3t9ZQ!Fl?{qk=XVIsR~-GS1&{o-z)@cs>?` z^E5KLuo=(O@8LW}jAtUV<5|h<>^vP{<>MKOn4PDH*?Ec>&$W7RKBCW$VgK+_W_E7! z7~3+tJw~7Jy17w3v}I=~>le>fd(6&IwC9KMj7Fb$CN6-pjA1-au`N4K^TK$BVw~(e zb%b$@>L-4-!&7{<1Y!@k2J z2fv55hVQM2(XNK?q|C0fV*E}T3g1J~j<_;>4@HdMNqbxEh-+Bw9V0dw$9qmN`lMzm zyL6k3-%XA)wk!Lm1@8u&zF9?)GZ8p%vMSN(7q=M2ShcY&aCrP@(iY>NZGDY8@Pqgv z;CEKO1pHgz2l))2>AlHVsPshRk@t5L#03Dadh?PD+`h#aGSJ6(80_|V0N4|)9ENW! z-eUZ^yWV)q_!;dydK3IN8{>@WfYCk!>|droRM4Idb`QW`C46hVTzVCeZcL|+uvYth z4#yG3wzXc>p`z7KUKralyCaN#s(_y!^UIr^!RUwaox$kyB#f8&{}@J}jN=Uc{lEsx zTm=;wLLK3&Wq0Lp^20b+&A<yWdBg_5@Rl>ISA{)H=(!T<3lE*8L zkh!5}N%d--ZT#>Y-v5~+cjS=h`$RL})=z59BBm3A9+4B@g($W9#hO09(TkS#yh(UJ zyuGxWXu4VBF**L5EkE3R+BB`mNs?&nq&%$ig|dUX(W1fWgm25+e;-nw^t^ce&^7%e zW#jFerXN3_PcF3WVbk__?Fgm95AWq3-oF#REpNZ`m7ihhh3kh-zl~L5dNm@GXO5>a z!n!n`0-ADbnB?aX}rC6g9WK$>a|Ll^>?hobKGB6QhvE#Rr&I?puDTs zO{w*&g314wN;z4xqv`9m-IT^#-kEq#LDeO>Zu|S>@Xw*ji`8Z_Deffc@T!YL{tpW$ zli@I*#=D_PYNv*24?5mXn^t48!u#a=jT$_bxYX#Nbn92Z#^;=Ux8znCcS*UdP=)7s z%0*1+YaWpS>qBh#JZI?ns?@)1WhLaOVAGbj>pO}juOW}g&BGx|bh#f*eFhvM2JbEk z&pEfHJFU8*wCU0|Q3?2-%5OuDrahTE*&%13`vTLgOQ%T8-+gV?l=tIk-FXhbUi@4+ zT2r3G?Hv>MJeatBVd6O@&Rmp_ytqfYJ_w~eXVRV{TYA_`%(yBubo3=ck+nX|P=hl}x;_!3D zt+mYC_w=5hIv@7$#=m1J&*AnF<<^}h?3hf>S3F7F(?e<1$HuelcjiQDp%Bm@4tcPIjL@cCqa%cfZpTt*G3n!O^shbruE@86-t>Vt6KqHS8N_AkA^eZZT4V`&iB>cs62 z$N>EB_z@{(S2hW31elA#g1zJX0^WiB*S-;f-|ageFb(kdeeDlk3tAm$1U#_*f|Tc@$)iAfXX=!efEnAK4|ARZbAAZs`~!|P z4y!$T4jaOnrayUf=nn7`!t18o+1LKi5ldU!Ib?H=KJto)!2Y|K5ZItNNfGS)%m+^0 z@U1D8z}~k>x4@Pu=^Q}TiV;&?fcEEtv$!mw>9qn zIp%Vm!sR-J%XJEu>$o|{j?22o6)x8)T&`2NTxV%(&2pt*_qhj-G-FN<6u2Z;N z2W_+CfZPT7Iw#j1;&PqBnt4Pp^L&^-acRC*e!F(*4jE5R+Yn1vJD^ju-LiW#dsE|TK_;uOxVEcVwK#&n-y@PA=@*9A_BwJmZ|8Hck|pMPFj=6Nf8=gp2K+kaWDd#X!K zf5WP*ScT)*tR0LoCr+NjVSAqj&Zp(R1pT6ahB2NT%*VseC&#hG!{#lUpS`v`zpd&N zc{6-aPV5f&Ib#97DG$DNEZP2@t^xMENHcV`KkFpvHgb^Fw`J}b z=OE))`}%J|Kfyh2YqxJ}Y0u`};@_5^>%U;_rqrcPb__gb{j(mkb)4c1$I7+z zYs``ywnpTl{a9Z_~X zTw9jgDSvLV=y5EZopR@?%^3M}lRHnbZO%E%|^I?e&-|OQ0_d%{Eznm>wMVw%sI!o^VH@{=hx2GPwqa=gJYem zTn;~<9G}JZ0pHQ{<|qb!efj4B_}rZ5?sM)uwR!ez=RcRv`Na9p(t;;1d}sJn{13Dp+`;*_|9|m6)ek=|_O#_bV{A_{oy*9B!{rRd zV{4S7t$UY!jymTvYkT(IhQsze*9YU}8C!mQ&Ijv*`C!@-7xQ7&jO*w#)|SPUAKxiX ze*IdK8Y|MP{@iELa-zr~zPW;nO1k*<6FA=7nhPI}? z-u_0~wGO5e`~6Nv_ijZqS6#``fBxk`uNJ&a9*wF)J)U05(N~_LGWG=`UJcmR;RE$_sMGFw!JdZ`K%%5merJ#&uu2hUX~@BUAK^mJ1WWR zA`*$mZ*}G1?VCtsLorpXY`1JG|Eo|ZpV zr_dj9C5 z)GfV`Y_IR^EJn=_ipxw#wflplcPTD2oq78vNiU<4?RAZp4@g|rKm*guzkW`PflUld z|DF!>HR7qkk;ZwB8~NNa-+AfGe(=m*HyD_9IsTTIU7i{o=^!G}xRizlriGtHYF?aS zaHOByD@5ZiL>rjiI=>)wTl&i2NSDtlM&l}F8kl}PxF`+TSxC0m3CY)pQ2K8J(}mJ+ z61R<#Y_B6{{v{iuQw&U(tWcO33x985+PtC&iF2tWJJMs0OT)J0}~MuJW)BNxxlDcBEYn8Ax2ey#}UBUe%Mt`sHOudTiq^ zMBT|nX1dpnV3K~bq-?L_j~xO+gp#E zJKj%bdcjSYud)?nNBV(Gh;c(#nd!|HTa%F9rDS`ZA$KJqQ?uaVQ+_tH2s^Rax&=TRb}LLU{6daDz9>#OcU$9GOPogzFZ}5 z2D`BPRiIHHO&saSj3oJ5Ks2$}LdU|gu}Uez^yQaHav<|R?8lLmmy3u`^mSRN#vNFa@^69 za`KBZgz09B=8XkM_Dla(ybKdlU7D`j*d21}q@P9d+c^YBwtE7)F?8_Kp1(kSyQRay9tev$h{$ zn%OItaiwl>jxl{XqX&sgsUw%a=t|FlKc<8%;v$b*Sn7^Xy zd6Xn3H6exSpCI9?VDjGm9=W`;1&RFpJ{j9Dh-~V6nw)In#iKkyV+K=$kt&$vk+jFD|%8K0h{r-hub0 zlP1#Gg3pNz_L2>K2|oAieO0iVl?n8X(U;r=9(x}YKZ=fDA5IgJM$>6i!fANfF*JNs z80``=nyy+BN`DF-MLYZyN}H#Tq{B{x(Mp9z)4EAvbpE9{VvK1*9O*fi<4ESRnZ#Zv zF04%|7VArxUJ_QDgnl!VFx@9(At?s!jDr>tp?@%`-K7mpG@U0$E)OB+5~k;9X776@ zkXC}vI}NHsHm{nVqnSObP$2E%d5DycszW>D5DDn>*4v>=|DMd`_@t;pnq&&ahZt;m=Q zMW}w4NSc+(AR+5YlU2ValIFdGDARX-N`(JTz6E8vNx@~L$mk$yudml!Mxr0Kp!T|z zIgu1-)RLAzSdwgn{gA07k}4&GXcu@N3Hv5Ecq!@8wI%IUH%rF-!rt#`y_6g;6hyCq z9rqV|f2l_s`gGNLax=IsoxS~A65OW^4fp6nDvW7M+XeL_zFiv9T20rJRR$wXI`}O~ z?Qf)sF8xTSo(<`Py1hxYwQcB{D~UP!!Oy|;+||{@?|3ks+bfa;A8$jmOrbgY`4c1E zngubJh4wo_$&teisrh_ga^Oj8`glzUS#qKw&G>8`>G`5Hz0+bHajV#yj(zqA@x0TU z>SAsXx2I$1=BIyC!`?Kj|2{IR-WY0JxQ{%1J%+w3c7QC{ z)|+06OebX47}{-mI{9f`Z#rYjUed1L80x!hFDcM>EbTRTKWPOztN(T4`(rN}vT{Fp zm)wi4`T9E1{4j!Utlgh7-ReaQJpupjY{I7TG_-sF9G$U$93Aq_04gl6YZxCHL5=2D zfwSg?(|gJYI`$5{Pw+9UYB|tyj*tImAU&~fJnht?KRw!7rtMV8^1OovnjXDXesHEf zT~RDqe%H^7x{TT?mxa$=s)dn~@Oh^{BglXVFFF=<&-3+ZB-l4iH_-UnyJUNv+S=x1)&2fFz;UNjl(_ByiTIO_3JTjIWE z9My-mAz!!gqUkk5KhU*XLBHZ|*$?xMVOsz-$J~|89tY%(C2Laq_rh>BO`LRB7TN^J!-~V-5!$_243OplcJ$}cO`r_u1au7`@S_a22B%YRj= zPxp-iB6VJqO7v+7E>0%&rBdot4%wW)Hq@S2qAcQ*s*fwc03>EIcua+PWIDbqcQ45kZq zndIc!`()#*nw05zU=MmHktILulLuyb(j0v!fi#;~lPs(}BxZki=!~ z)Lu`noj{6RtU>K{vb=|o0?@BjFKWG){4=#CWxD@>{p8mqcWSRkKiW&y{8oe7YnQz% zNs(08i&i~1DS>nh^rB4HnzMpDuGE0q>y3pHNZ$tysJ(tzY%h7x*o!i4thI-Xyx>Kd zZh2}iS@5UN`$>j69NnYoIx=ru1nm-*OjeKY zpQBxO?PW0ab1L(_Io#@sZ1L(aQYsujy{pq?QooS_7p)}%)PIS|dezaHr zWRfzyKYd7osIkUex#F)ubj9o$@=;S)no)bMyuEH$8aIE2yv!Ixvpn0AH5Y=YKC2^X z=FycNc-fJ(P3=lo)oV`*eAa>*o6M2zb$`ff`stm>0myU4uR4+4FS}5e7IS2KT@Lb8 zFFBb^acMy#SGNB^hh}!6S>LoL_F4ydu^F`c3i8m&_+6wD?Mf?pxBEcHH|$E&E6hkksd%gB%OX{}pupIn#Z_?r0 z&eZ<>waT4o;)=ua{aMpVY53g!y&L4I2b+eH+H0qg5u>|Mrh7r&yS#lUk^1)~eTH?R zOqYM!hiu%|m&QXLn_Xx&VejL@rjfMo`qD<=??i#wguOr4b~-s77XrV3(V51379>nF z`?89?$qV?r(5;qKUAG`%n%P4jFI>Agi){aC8c9g#OPOv2_R9r_k(a`BV*aKJW!l`K zGc|TPA~XF>%nTA-vI}L}6Fy&cwg6$eN!uBuOZ^ba^s%iisnGg}%yjs?p5%09XUequ zww5&fbOFNjvZg)B#8M%YX(Qy_14V|B-Antx|2MM>WqJ_g=~chYBG2pgAz3r~Ql`@( zUwn137fpuzQL%F`Diz&JN}cINv)uL&Zv)sN?e>sX&yjtUHqOb+d6=HZQ4VQv>8Az4ctQ-mh4R{ zPG3n(?FY~ftyYrcGQDa43Aagni5{fcmYd|{cfH8i8&DUEOC(<7Zj+FT>&P`ppz6!L z$c^atBywYSQa9>7DS7={5?WQDMZQiXtndwOXFtT}Xikt{{8+CL`65c10csyvDqw)Jz#ZJfM zbCI=4yQa;^v7H0SxgN)4rZaX7B<&_PBTUEd4kPd81(W0o^~r)Y!Q{^0VI*DG6=>?yI%LXVsAGQdD(C&F>TVW$fhDdMJA04(CgWW!{ISoLTKM=LKSzyx zw6phnCuUl{&x-RN6SOa?Gmf71=}+fHl(6t87I|m+eA=N(mUeMJPO^M{f1-!wb8K&F zKAvKGj1SwVFX?A#k8xvr{2bfk=hz-U$M*cV*!Y-c`6lYc?MH@v--8 zJoe+`-($S?@w4}Ay!PW~?ge4%C2y=wpLYj~QGDX-YqzXrc!ypd}hlC@-N#PjC zV}c@_63z-gf&580F8nN95Pkvqi*Q=FBz!OI2f1IkA{-PJ2#Y{267~otVTCXco{a8alzR1vCztSVFzDht(xY9Ol#p9?hwcfk#$n@~geLZ}7rzJOOvp|;>5)B{;h zs4LVFz7#w`dJ6RgFF`G6L23n!;4L%|bRcztkKix(3BDkG1wDB1w@5ws`(3yyqzl(T zrwf08P8Y6&P8V)~PKVEKfGi-oh@XiC;3bHn=qeTgSwt)-77~k!N-U;`GM?xmZOyMu#q3}R> z1@e{fLikg-BfJIqR>%_G2)BiQg{MMcvAFnDC@%gZ{4JChi-~^=#l&aAOW|{|jQCP0 zBR&`23nj&B;(MW*_*!rmJ;X0XcX+vpwZuANU66IfFT~nnJ<$`Sr&vR*E_#XeLDm;* z0_#h7=LWCp@QEk1t^qH1_@q9xt_iPN(7G1k zjo4Z20dxY%g{Y`-$No!^PHOm>4Mr zi(SS3;%Jbg#Svm3v4=Pc?`&ZCxV2p zPh1RgvA9T_FU}U1f?O&t5#z#I+#TiV5OMF;UzIa-+CT{8n5eZUebZ+$^pZzY&u_CW%|b zz2ZS}Kgj*!K5>_LK->dzkGMnpPCO*0fJ_m0i{Fc>Vj9Raai_RlR74XN*X6rYG0ATz{U;%)J7F$-jtcwM|Eiqbof@5FRq-GO(1!0Q@(k_D}=!|Mio@(x<3 z!|Nur&Vbgp;B{NPD?Sumq`UAcAUzQ8izPsokcvr<#TR0EkmaQ^(lha?SQTVd>2oPl zd@I%jSyOV8-iWWndLZjbUrO&qmDB)a14%0h(!ZiVNPo#!lB9cLA&`Y6FX@r^TC5GS zwp2v=OZ-RFfYeCUq?h7zu@cBiQeCNuM5JaQn@Me?c2YN~FUY=9FR7;#CIy2GmRd+% zq>hpdQkEJ?28l{dK{k~dO3kGpsTIgpQd_CL)IsVDva{4(>LK-(LO_N{p;BupLJ9{N zE;W|AO8un)AO}c&q<&JQ6a_L$YAG3|LDE2w1Eo&D3Ws-%;bnwRqM&t4c(sO4214sj z@ahV!2SDpS@aiYUNF$_CAV*1~rD$oWG#un`X^1pT8Z3CUg zN-L!`(vQ+Qkn5x=(oAWibOhuPX{j_vIwYM1c~<&HS|pv2_JQ0d&69qYu1M)1)1{lz zAJTQ{Hptu3E$N1IRk{oEu5?GbEM1fCfxIW(2li!)ybmp|Lc5zFZvyKYw7UiJ7O<{E zyE`E7fTusD4CxujXVOFIFX@H!9OQH9vGhp#Tgn8PDLs{*NH3*VAYVxj;D4{6#RGW# z2`!!h>mj@zL5t_WdJL~8&>|B&J%!g_(rZalsZ_5)ypcrJXR3lK5nlgDZ>7R27u8$I zMfI=rUMiw0s(LRKRb@$8ASKWew0Q%q3PZcXzDi4*n z$_u2Is-8-xGO7$94Jy5=zDlhM1R1EJs>Uiml@_E{RaaF^RYFw`WI0u7RYg@5RV|RU zRBozLsxMX5K~`5)P}Nkqs>*^atE#LjuBxN*1nH?NsVc8(pwfWUsLH4+seDxdAOlp@ zRJBz^)d*xGl{>IJRWe9f^@Xac${$)(g;#l14OK(%R0Cecp|wWk1JXzJxhm-_{Kh01 zLW6VP*e`B%pm{gB9?_ayoV&`$+zDsiWJXUvIo#UU!_#2s)-|vKed5pi8 ziFS;K#}#`IGY@IqnMOR@Nu9y98%;J}>^t4UcLoog7;hf9cAkar3_fdGXfF0>s)g?i zt~_{!xmcri7QQnWe=8K{0mthI<8O%KZ=E8?5iTD-$UN6Sj8-W-jXHyq22C&*sIh?l zU3eOG2G=eeXHH6(L=V;5MxDX4*TtB9!`slCKHI1>xW=4#bM@cgcRW9vMxDVfG4WB}{rk5x%WDf7=`N52i+tfr?C z^Tub*5~(v-PpTO)Zy?_pJZ)xCBjyd{JA-Ewd`>ZMAm16>Dfl;vc?0>*VE(s|dCdPV zGLKtU@it<9n0$U9bp{_QTf>O?L7g^`I)lp&sba+Z&?{~gbp~Jh!^4RAVe0Hv)EQiD zU{NFHhr|N|sWZ4;LQx~;hcc5_QD^X(=Z`4nho>-JXYkW|e^bm42VuO<;L4w$p_m_h zVg8-L^yMEE^Ftq)A7?QC8`wPNe-E3-{BL9PnE#z@9`AcR)V#XsRoV&8YaS=g3!?|R zKB2wfx3qcOt;%;sX6Ny#Mc*p_^f+Vj!{ez1b{YTmuWk7qZbumT)hlHGR<|R}eybaQ z+uISo=GM}KPjFX`5_mc@^D$-JD{F1XH9s)YVxnUiOC z^(56gKeaxelR83LX}tcqNO|0|SM7iSfeFT^+lx{jhwXl9=>B?z@#(tHXkIw6#@~e5 z5wo_dia)Wz9zEBQsc!3y*Pvf#aG|c7$dkRJKWqD2v&ft}2m*vFvDHvmB{QNM+ zz{cVXp7_-&V`k`DOMZ3+ub;EhXn45Bk|&+Pm;d?3c&|3_A)kK=#xXK}ewf98dD0n- zV_XupJZHQNV_U>{9`P7su-L8f+hZ0R+7Yw1EFQEYzBkF2Oz9PAIXCgnFvE)RY>l_# z3p1MM;P`>tji0^A=JR+-Rt@8T7qyLe_XxKYLnm3tchVu1$9fMn6WdqyO2^SO1u97CXB?2Tw{M&R}+b zPVSUIoWbmVyP#D9afI0&)w4?iaR#$HXX?ZR;ta++WE^}4G@e*ac&u;gXTP}SHNt&5VLz-NhdM8H=<7-&&RlKJN`)*;8jbAo=b z_Q){S8wWxSVQ$5GW@j+g8-Ilw0`i@~SZ|Dk8Upg2!B}rB0yPBWJA<*_SO97W$ae-~ zy%EQbd>&(s5%(9`d5n7}9%={=wv;nFgK_UjP(!$oRL<-S#=2r6)DZUh)G<4Qv99O^ zHH04n>X@CuxHqdo4Iz1bIkPhu>xvqvAuQ6>F*}2CUpImpLV*qC%+6q}D?WxA!d)1z zGZ^zg7pNgzg!y*{V_oq9)DZT;{5XR#m*VpfvZI`t$5=~5dm~cE%wx>4_?-L*d>&)X z5c%7I&tt3;;(pA`EMev`)(LU{qMgTh{^EW|JCCtW$oM?QIwAAVW2_lsJm{xSBiYC> z)(LUHUq4dQ>_A?|nNJA<)Ki2EJ+&S0z);(kZIGZ^cHxZjcQ48}Skj{Ohd^BC)d zxQ=M&G2U%(zXx=3H9LdxZiD;1c3W4oGZ^cHxZhpUYnYwESSQ5&Ugd5Lvojd)PPpHt zHm+u8FxClizu&oD!|V*kdl&BaE-+qaFxClizx%;>oxyld!~O07^Y0ACIw9`&!Z1J1 zV7%Ai^RT(K9BJ(u@deQyWpJVG2Z$2 z!F@pUuDF@UcsF2n9%HTVEz}Ir50CMF@*eId=*JO8el@5WBF7QNdrL34uOi10#+ux3*$M;P-JnU$YR5qVI`;;q8)37hph9%>V%t4-&c6dYJCmL zKT&wh>VXYPJyP<*Zt-_=?1)+0>QisoU{)vG4E;KTS)CB$aR#%xAIAA97-MGq{4lE% z;<%i_SjWR!7LL~*V_gNug?1ieT?OMuyFJF(n4Mv)MPNK=XPDIqv0r=4`a(O8SzoL+ zh%qpXec5BaFNRs25c{>qtS_|lnDxtQgV-;_*sne2`(l{Y39(;$%=$t*k6FL0Hi-Q) zjQ!eUzAuJZoe=xA$E+{3^O*I^YJ=D>!`QDq=KErp)d{g*d(8SmJC9kvtTu@KGK~G& zW4ccJ?8sjnAHifUuQ6@6XO1I2D7>!#`Y-~<7fQ* zFsl>dK6M7OIw9s~XE3YF;dq_FtnP>7{S=I2Wc>Uvivh>$3}!V$HeRghA;z|d*|->H zHA5D^#cmx7Vip_2%nyqP?TA^;5YI=vGfam%A!0mRv3`gcYlaMC{h<)l4AIVGtQq!) znjzY;X1En{p=O8} z>x8Z~TN%CKx#cl(ZbQuw?L5|LzlVE&ae6ChHFboiCVZR2afGq$v>gp|{N#nPEwekq z=w~AMX*I&#>TzQ`eYnu@b6`JS>|d?y|1YweC@!798P{1=L-EG zCohctnLR&@^RvvSk{LN4!`K(&IE!(9&_D7&hA{@laR%RSJWKIxHN-fw)EGMDxjU(A z#b__k-Hnd5+KXB7!El+Z=;UFsBW@BLZE5SZXs!}(wIdF)+ILi*kaFirbEE62;q=d+ zBNZN}btr4GBPZ30i^6Z)&xYTCM?PZw&3MH4oAKp29B<`dob@1P|L{^~7C&ONzw72k z^;SEM1u@3F0ODjA<3~Qm9A~v7Zf><>Y_}kO{7rg{pT`(8+L4oD#TfG}hz;$C%Q*PW zd-mJ*N%IaWi*$Npk!y90h*ucDGOmeiPZ?fzGX4Ync2wIOKEow$FNRudwx5!KnIE(x zMn6184r|Nf_DzeKSX;!5!{Z)cXMG`N{&}3)x~h?J5Hk*sUs~-rUc{^~9@l->EXNOG z=7-0gRy+DZ%>3|p61|@@Cx{t`#}mQMVn)pR;&FHnDTjlYadq8Cwb5>|2{^R-i@T4&V5cUe0hS@IUG%_fj z4sY*RWuhr$ei)s2>Nw%?tXK~vY3CR8pFfWg9#@|mrIfB#o~%7}lvw|bR?ENJ>d4N= z!^gnei`Lv}y4-rHsnU&bx*+SVDe+uS%2Gfu1J_oThjG*TBQwlO)Ff&C_hHscPiq!;kIe(6Zk#Rjax~hjvGuF zM?-Bm{Mct--c2^vSYUeeV>s>D<2AXyc4%6~@_i}KaWoGD>fI&r5o6MR>K{%Warime z`O{s~zLIm&s#gxD&yuSt6Uu+7{9N#cDPf9QF%0sz%=x9G;mW(&t|sHStEN9UO;rBL zs%7~N_@vvtOoe0mD#NR$oBlM9GVPo;*1~t>XI0#-w7PZgn*OaDM)|hBt&>bmhi^9> zUKMH+!|L?!O~u?+n0B-bqlp3MOw#9}X*c2TNqPT#Y!#Qql8QBYE5VIHi;t6EN4_n;j(l65!~1{T^b6{@+D+N~_`0d*Q9qgzsIm0hwXTXhIDN~s$s>&N zZKvf+^M0yUilEDXc%SCi|94Zh_LFFb>t!tSpH=w)nKXWpNz*rs zYDb?ZEqz<3EhJGkKKZu%KH}}XPoBd+OFWny(2t_x0gyCYg+MT2l`#>0+h#5$Eqp=YgDEqjtZ2= zBir^;dM*BpG&%j2@R;wH?~AuP${TzKf*@}B9+y-=D4&vtCf?IxEb+q}WI z<)1fxEROO9&*8`DC~xo_e(e1E@^*gg{MzyR?*H;bcAo!#DL?RgoX-jTbHa1@z0B`@ z{+Z!9MKaZaE~6J4zJTBV-c@j%@@>pu%h?XUs~Z5nIT?5eejC#I+miu^vvUZ_I66Fi zGWCx9US52pP};$9Kgil6g=BNmWLjvNIdz}0mR$d!Eq}cW{08#z?<~Jp_Pc*9)w`{g z=RY2FsO70|<^C~?Q)X)5H^{RZrAEBJ5cuYGES*!gRq9@^1&1EPZ@G0ZqY7N|x{)F9 zZ7eO7SUAuhepB=^#KXtT$9CfG+`v*B9t4{HiKS6P&Za!cNVecec*$UM^Rj za#)FKVxv62sdmZx63jnf|k-mE~;W?202h@4xxIVsiT-?da{kWhsXhZ|w`y z==wG2%&@AI!%E!GrQ|>3+R{lI%h6-&)ns{_IMbv*V(9)tuMf?NgC-Pp+z^PBo5Q<}|OW}2{TB+r*Q zzT$w-$D?rZC|o=W7muaCyOr9~M&rv{`m*8=?5DJAOhv}USU5a}XV${S^|jiq?{n?E zPoDFC{g(f~dH#Rox$0g!orJ`dqnrNqq8wJ_XPIe>(>l<7WnC$UmHGS52X=E$F|`RA zLW{32MBfBzX-dOaWR3Dq+U%&d^!S$2wE44wrtkMnGi79D=Yiu>#wz=7j53*2l?>vO zI8(#4G4zinMNNI*%`vS$9zz!{J8SA>7?`skt$f1qm9Y(rn*Pq3V+uSGqwst#9)*j? z#Kog<@hE?Iyd?F1szN>2xls-)Pk(Gr12@QNEdokY4l9NM1?c$29&|4JTf8%}+R_GZ zTBRLHDNDbM3pRD#)7!KnX(XL{X1gi2$hg2VZ-&tw5uHsva{|eXEGCs89-5^^#k8i?#zySAw+;+~l&297P{qk*Je)c+G zFRWc0{LU!d*FNR_p=Bvqfcbkhf2YE>nNJ1Cb%feExgr)5hHb-$I<35GQZv?}|H0sZwt4Js&s&IOq4A*S|VgJ~aUD zKRk!G^JC=iS3Ks|YnUpQdawCj{vl&f0Ds4$KC!gr>%A!a3aLaV?MT>`_Ai=mc<6f!F-0UY?2ZWch=2-`8ntL zc60k*S+5<%N#M)a{Q+AcPDkstb6@*|Y+MhTbqoAgSZD}=`}rN0*M~akh8pg{9rd#o zRRe=oHVK>oep*IsJv5r7l-%f!|6Ogx9Tb2T~>kGVRViN{<$&BSBAU%oHi&eaeUuJ)+#@$hXu zp!PVm!adXVhoK5rLr}Pyl}%f&hM@3c@!hE+V&ZL6slP&%ao=wxm78rar5_Eo;qYVR zY6uEfdsKK1KX&fBp~Bnwv2))C6|ROr_`Sn@PbB<4;=W%KK6g3t!_^oSzAaZ{w26V- z_}=us-U`$6pfH82G1_qW*tj|#;qxTl7au3TUVK}Az4*2~hxgCb1_{5H+t*i-62IIs zHTp74;oEXGMul(7W8M$4a(~yLaDUfe zv)}o#@XrrFmOZ;vMd5Ac9{N$S6`3g{Gkj~MS=*?-~`u4X8ot9L=pymQX**R07(cX2>!{o?_0 zhrPCZ{yxdo3yjh)#6E649bX@80vw&Y6AY+PgNt_xH#9$D4fSe82bH z@A*FGdG4Ki$DPE?s=oK_D98PI6SiOb=b!4^i02FO+3~Q>+-gqZYyS1K<^7?YE$GE4 z2jLE}Ex7C>Ju`Gj&kVgZ(sMld*`WN)&>?BO@)pkq(JC+b$j=F7o}6cf$$m!XerA}g zXMkee{>wAQ|H(7Vk373`9T)jopUmYy_qy{Kf2_U#Jj~A|WzGK|*Xx<#|6k|$=ZEg= zK*ISWpEL6LCZ9jDM$Wsr%TwlV{Re9<`^%nkUiN2=^qla&J~K?#Gdl5}O6(b+^vuxf z8K9*1dd4U{GxU1KICjg4>Tj}d-!&m9dCxGV=Y;?DnPIY?(f!wFfRa90&lsg=hRJ${ zDUP{V(vcFX88dKsgcBkMx|-A#=Gm>6xKJ zdS>|l^zo9O8Co7M>6xKJdS>X5o*6o%XNC^xnV~~^X6TTf8M@9-acT*oL$mXRG>n6cXRTJZt%aJA4aOwauaD=dzyiHYuN|r#x2OPnTA&eI(fC zOV8MeZ)a}hFV|X(<&gSuNc{`W{W~OoFTLa`^4!0dM$Sw9JEZ$T+@F8e`n- zuaNQa(z;l4?*j;Z7HR8KkbZBjVM$z;QHUe+`wbIy0zst&4xP5uN_StJ- z?6q>XVHksv@t;SPuw%a0!1(j*YB;OrYe-RUoN@P)L1^A~1^^b$`5GAgs<$`3O+5%1 zQ(mrtY`!3wWFt%L_Qz62{=(Xl+Hp#4_3ZdNtCeDYtg!W8pp|FM@~ zg|k}%7Kr;7tZ+tcz^*^P1S>3(ttM`J{x4Wz#;5Yg_F#D_^sPfzQM#P}9;P-U1 zk$Xo8%#$}inzyHID+I^8ZZW32)Lw;v9AYQ%M$X;@*iiMtKw#tp{)bfs}#kMfw+_khuF*N+Bc zkMs4QQU8s`!Cy*a#KYV;eQh8(!)6+cF*ElV>sI%|9kp{nNbeI6W19udp7lV+W1nl- z^H?{WJxa&m&|cW%Zeu90s<#KL?N@N>iuSmK_NRK>$%6;?HU=ot3e7lY^xsC0p{|h7%d-W)MT7Z7_!i2T5ZH7|Edmv-GLVOw#&5bOncLV z87Z&Kd1>?D=K&aL_!t>2FinvFbT-IfSYgLv0T?s(wCz?=()G`2n71!e-k#-_%?dM< ze@x3)HY>bdFBl_x_!x}kXLffH5av2o}m8jFUVubb_ zw>+4aww;S#*%*forQhm}@i7<&(RSp`3 zjM+ARh5df^F&G!qwx5#GV63_6D|80rGTsr|N1e8fA&g9W%Yz3#G<}fMV9ecrC^|Quu`#w8Iuw=Kw{2FKlg79I`r2lNQK=#@ zl8y&sxDr9{?~Ddxv**K6xsc0fac4N%tDdrrdo&y)58m+Lrni*;=B15s%J2zr{Xz>o zH|Qr=^hXQqws<2n?%M*d1Ra8y*UfQ3t#>f9Kr`Gz*V%EOga(K7h zHDI*OE`{ZG_d!N&PbJJ=;~Fr&TvQU<#PrAc(be!mX{vMMnw_O^>Y%~Mc)u;U_A_4o zz6?4m55;*UYGR|R*MO1p72e!3rvKdw(+#fzFTd)IT7WN%&q}`u?Z!PLtH9ROZICfA z^?c)S&lB)v>1W|(jE(pNzk>E_dV)+6jn>&1Ah*D<3=9UC(CyS>5iUs(ki zb8d<@_KvTFj1PZnW;g>XA!A5rT4US$%E)N%8)^Gtuz@zeOUC&2wJ>A1mBySn@ZiI1 z&y4H=%YkwFq}j#_hYcD1{4W@XYc2=I=(jtJ!rhlc2#zz-PO6UP?U{?_8?$gZFy89W z-UuC49T`jA8e;^NSq_Y0PbwO#R@#v9_>4kE?D1s~-TbBP>$`R=c5#F8VunBNeU=rL zrC$yOw!ARxMvNu;-@9OB%n<`t*stUT!|&o!u)>&q&kWo7rC^1N-|sL&U(N?BTy=Yg z5%z2;SYZ|4`Not~F<^zoR?Rmq99{}m_@d-!<5K<@u)<0Czcvawmx2}M{3W-suuBXu z7CT$Q2wp|wxiPFu4(RxE3^1lIl?CiKmjYw890%d>?&`?+Y1cgvezFQOu0FOIURF8D~#j2DafgWDKaW7#d8dg+m4%gY1)Q;*pELLKywom2t(a0_gNTXJc%2 zV;5AKYeU9;mGWVMLuYJ^rw`^rCEqz)#Ir3>_+fQ4Zx3si9i8>h*ceM!S`UNw*^u${ zi_91^>x_-DX67}J*%y)Vv-9b&K<7VfsZXqgQ$PCSwfqO*>_4@z!t)~Ngfq6g8w+4$ z3t!uOH3T=L&yVKqdUf()WPRP1r)n$I>lQ@w_V4BMVN4pQ%?ca+PyiKex6KL%9H;p| zdtUwb=+^jZXc07T_c@RY3#@k9tgwCa>=^ljVr%8s8q;SjiRSHI?dksyySU3{g@rF? z#>gL2*e*N{!Csq7qj~##B@5d7IBZtfd_p?3FVAJm=xBzo+my#$O+LZUKb?h4|@r~S=V`LGu&->NJ7#{VjalCnXv=4Yu-PYp-9HzhfzUr*9$T;{54XZ!? z0^eLJf+Oj=+b&lV2F*ze5e==*08tV-8$#>np*!;On{Y)!bg)ZfP7)}J9` zfs^TM*Hrp*SLq{AC$JbcdT|t*e((1IrYNx)oWsi^W1meEU_f+nELbN5#+@yI>GHOO zeNW5N-?=dXo>Tu7LMKC}6#*V>Lfb!Q4nW2mZ6`yyk+qTWC)$30x(*&A-G$r!c%}Vh z7*nH;2M2eY0V$UUpcQuPJOf_k2tX^m(QO9oA4}s|;5EuO`_~_X!e&5|!*$TSJ%;?V zSF3|o_(kkO=t%Qr?6YPe+|3$*j4M_zgh`RLk@4s+3jt2mL51>#@A_j3(x1gT9=uR= z4J;x*#@n=ACVK!f{zco4(Y2A$N!#Q8sDp8YP44;QVZ!X>$G9wJJ1iqV#uc;;#vyL3IQAYKAit)B zk^j(jm-Ow(k1_1xOUO)qR%ko(5^OmG&|7mO@KnKk7inG6sd%&| zt&1C@Do%hU-{iy0rGJ7+-Sc7L4jTc|D@34WZFAJeX! z3ZE1!fDzL+!kHTRv1F-TF#VVOc;D z$FbsQg}K)@!N38f&CG;Tr>uDjRwX?wZ6onYx`qN;7+4K^JrkqS)>Iv7&{ml zi(Q##lx`6Xj0NjA#VYJ$K>B?95>x3)M+hYHeeo-!cNK>c5+hV`S z3%$tmc1YJL#=`U?QCauAy2y*?*}2=*T7zo-}cMZG*Po*yI6D=`#(@H`kroyeP!=VP89 zZ}WW2^OLtlzvljVo98S1A@^5DLy4 zid8x`fNBed;+8>C#>u=rF```qIFpB-^9_zNh7TV?&!cu4P@^|Ke7w`>MOdMg4x5Gz z!8t8;n6;LkqrKLk#kwK*aOEzeRhr%yy=Ip&g)s1q23={~Dr1|$7V5)3x*24naoZTN zP=WdgARJBO9T>mHHJ;y{=5TE8P<%n#qMr@-n?nH_@7B`3(1!Xrx2i9Ur*WfvqM#<_ z_os-0P#Wjb=?PGi@LbA%V5dH|r0EAesjoR_CqU5kr;zQ7^tgVO1BR7Kk4^mdL6n5w ztiA{DXq$1?-%r6d@+zd5;{e|gS7Bl8eNaroQ)}))M%vHVcD4ijV&6e&%2!#NfRAb1 zuC)Dz#%o0T8Ef8n3IQ4SLSVo?sE{E6SJ8MGX?s}gJ;+V_8E23_xaCHeNBU|Z38>6< zKvvp5PWn%2KVt~_q}zWIicmi5ZwYvx=4GetXEdMEw4X76^2c*Lgoc#gl|2DtXrIfM?QbeViQbjS8 z+7xRmcBQ6LM`=K@ffA?$DGin86q_rJl`oanN@a?bl@j!2ysl)Sm_QhF&Jl#a?^ii4E_N++eW zGK}IdWr)&6>8gyNI6@h&bW_?Y-6?igMk;-kC}k4GNlFi;zcND^PjS4`M;WNhQKnOz zuJlvFmBq?Diu05~N`$gP`I+L+%21`JGFe$oakVl^*`n-L_E6lTY*1pAW$H>bR#~a; zQYNY2sTDMyt{6fY@fl_SbA zLy8ZT`^t6Yrt*m5Bjthew{k|gL-CICFID`bJf-+lc}x}el;;$mE6=Fnq4J92E9C`M zJW}3Je51UiiaW{^icgf+RPj`KPw~C-mMWers``vxiu!`8Qcz5xYU)d>@}cOX>gsE% zdPjBdl$7dQs!B~UwVH}5R5dNdv}zivNTH^um|jgs6+UW4iW${U)RgKw#h0S5nt>`( zt63;!Q8Q6RS~VNRY-(1jNU!Fkm{ZM86&cms6mzRNsKQsxOfj>Xiz>3H`6%X7^H4=L zH9y7t>ZeqZQ!Plbpjv<`a;t?Y7FIu_ip*+Wih0#SRFO|DO0lT=IaTCWi&HGF7Nd%S zYAK4P)Dl!tSS?Mlv|5rX@~TBB7E!;TilS;oiWSweR8d^5La~Zko+?VI)hSk2D^o>j z6)B=>qlzMGIf~`f8fqD}f?9`S9krHPNv*2ZqgYR^t5#D%ZA`JTT3mgxb`;yGZPZ3;3pJEtsM=O-rUs}X z6hqYZY8SP$x?AZ&uPsWHIz?TpM$v17`YWC1-6(cb!_e~& zV=0bR$Ed$3Un>JC4phHYBh_!zaTLd?{nfA3L23lW2=!}qs5(L&tU8qm^!{`zWml{9gS*ouU4u#!!q=7prsC1?nu- zp{!7Uq4?P190of2w!XRN5Uijka0+RXw0?rq?!gtNNRInBrk|yShU? zs-B>DLfxtEQctRP+M+>GHtodtowT4=Aip{kKT4U`?trf*qS_`eUR#pRwptaM|YB{vL z6!U87wNJD>S^~_(x2M;adNn;(-K192H>sdk)>qR#p|ZYSt)lnP zhG^kh4|;XchHKwy6DdyAMraY*1Z^_K$=XP5lr}}1Msb=pT8q@CYCll?K^voet^KHt zqc~0*rj6Bp(q>VdrH$93wAtDmigUE@v`N}rZ9c{MTD11PHcwkXae+2No36!ZGbzs0 zzM;xR+G2`}sd~2dv$lld5~`l7E!CD&Tu#;Vv}M{#iYuu)Mq8mRq_~i(7iqs}t0}Ig z>YueWS}es_s$QzC)z(v7Pu0t`b=pRX8>xDQwn1A(aTQhnqHWf;P~1Y*YqYJ}Hj3M* zdabry+evXJRj<=_Xby@Fs@|aO(l$}tMAe(M-P#_Cd#HM=_N%s+;$EuWuIlCk3^;zwjc9Y^wsy?sX(C$#YL)90wf3*7)?^E?9?V%P&F^;OQXpgmL6rX8- zX@6@kv{w{gX}7f7+8a&LZ`13Zc2|3+rO@xv>tF4GrsKoK`YE^xmYSa5`IrQulv(uh|T24KOK9Dj4v<_M>J*VD*GJ~|iT5dg$K3L1657mZJ z%te?>@2F+c^XmEZO!Ue~|K`(kQ_M}e%=)LaCo{b=k!yB6KgIld7Wy|o?a4x~%(|ae zP%lccs9s5{pcT20(^dO59({+V7;FGH{LdI7zhUXo%-{d2vTURW=s_tiqR$`mW>RrKy!Hkx^N zt*UP5owYEnI>qWb>X+02y&lDS`ZYC94bmIvacTqozIs=!uQ%53s*Uw0>NB;8-b{a{ zHq+mz@6_hHU4N(A^%R<~R!gs=`)YOc%W4bVU$3dRpjQpOw%$~4NU@<_R}a<$^+tLh zt*6$8VjI1s-b?GMg-{I9TkAvhG5RQqqx1-UtUgtrOmVV4K_97))+bS%q(|%1_3`>Q z6u;4j>uvQ=y(`78dMCZR-di6;aghF%-cb+N`%&zthv@_L_IekJUG!dhJAIfwg5n6h zgWgS#)W4?qwcc6pseh|aq&QLUs}Iq?)4!+qy*_|cBlIa0r|5(AK6(^Y^r2Tby}v$< zochzN9aVp=kE1wF@1g&o&(RlAT%^y_XX!KaxfJK>3-#IhkNSLy^Yz90O#LT)0mTJ+ zjQ+E}T3=6by}n9cp|8__q4_I(AQ90qc7E$>9P7+ifi@d`T_m0ev;xz{iy!C zeoQ}3@wk3a|4l!lpP+a`KcsKh&*-Npp3)uqF8!ST2gN`19r{k)sh_5JT0g7r)z9mH zQv6fjqwm)*>X#^9(s%3o^k4PM6ff%+^v(J<{VK()`d|7M{kndI;uU?9zEQuX$5D*a zx9Ydnhd759ZEPQKMR&@4+sc+sM~?dTjCp*WGVj>Ewe!{Qwe2-mt4^8k`Kp!k-MPB< zfB$;rkh!RJlF!MzjZx-etOy!6^qn1LE^6PC&)~qKD04B^YZ`Z6)ha0S%%}S}SIxbJ z>076E%Dlz#zRq?X;xKRNluns%$lk|U{o;L`-{7r7=0SOSJ0InIj#K~8oH7@+q2%LR zH2`HU##&9|9=+QFWiD!;kk6%~Hk7#-%b;=3po6&F5b$@3H)m*nuMG;N&&h6LH4(DAk6rL=a=-eCcDe>yjk!-da4 z@(ibAZN-I8AM%W$-?kn3!Fyh zNpkp{HT|49b3Vj{biO5riynabNkivba=4h|WSZ}BIuDb>MGv{DpL28`CWnhTo~HR; zrt>*DTzRn4xuC@<*KbV=e!T1}SWmw@%{**Yen^Zf<+pn@f>&I-*i$Pwdvad*B*x`h z_MBY%C@w2>*%0H(Jb#P>JG=Xlxfn~S@auM=XD-HKjhVBj$je-=WzId^|7@dczCzDj zXhugYaph&6kNV`fFc)L7#?0B1`w{+v%eBm__I~epd1WJRde$6eKBr?!C+B58t%|QR z+b64BdYKE2U$up`)QokXec(IK2uXa zJ?x#lcu??dM;PThQ(or6Glu-TQeNhwhkn$L$je;RZtGgl9`jX4mk;xYXR0_ie^$@F zgz_>USfP@0dY(G=z2iG#Y|{qLv|*?5P2o=1qjeQ$WK?bYvoVpDJa76+PM;=$E{zpu zpRPyRd3*$Cy_pyP;(E?EllJ3tny(eV z@moV@OtJGW&Bu5cjl~+l+0)D`{`1J;llQR8(~9pJ``p33eT)l#)(Fm?X1)+BI?KPP zZ5Qj17#GK#^JboN#dAm0ukq{uF)sXBBe?BMkaLOskZZmlFC;iv06YYn>K>Nznk`sBQs zKMAYktUlG>_5S)87i-HJ!Do#B%$cG2Iz033#3Xs$CJQ~9#Q3%yn#U(8&b2~g#YH~{ z)jG&N%!S^}x&IQm#(MfsjEh>%C&qh(q;T~U*=Rf_#YJzdvEssiaKHKQp8>>tg+_b^xI_2Q^RF^_adCeXpAAG_=KMR5 z#eU1=`AtZ{g+}})WMVvw?z!jOKFq~^c_!VXMPBCOGr&Le8Q{U;Oiu9`pe}s|c=tGy zQ+x(UMg2VKo6d`idv{mLKc>9Q`M&>%@-pZ9zR1g5)NZBE0JUuKKFq~^e-nKM@Ta`Y z#bW&j40jc(TUK#r?eo zeFhM%C&tBnU*vNi$l*+ii{4mc#f8s{*FGK}=0b1g zGctgE;^mI^Z7oNm6@PTFrv3d--RxUQW5v0)LUcWkkKn8?XX5)a&GUF#@nL;qJiUF4 zi?LWEID3k5WiI*|ou`OvzE)h!gV_ETQ)eG6V=Z|qQ z7HiC${YBo2i$47ezQOIZ{#IPfefnX|vxZ4=F&691oc$}g*GG(N=3*}FZ^gx2xaW^? z;m;Z~XMbKdF|L_ctdR$gYz}edKgPxR$r>})&gHcqA|H|e7#BUT#>|EP=}hs*;$vLY zvc}AX|2gtu|D-tgEHq|bp?ZFM%0Vey`Hyii7HbmYGn=(=^&>P%anS>7%zWpDOsG&l z!vAAj)UqZqK9~C8d{Ugp5*jlX?}e0f{n-+n)oI1W`yzs_KSE>0x%SrAJ{}*zS#Rdz zoM%rfF3x}M?PFZ{vqo_CG;`5UO?qGRToU7aec&|_?>j3l{8=wJ``g_aOheF$|NPxV$A(2;xinUsYyHZ7>G2Vq^=96` zQAJ=+D}H-hci`SW#)Us?1ZPh(7yVp%mKnoozE)h!rQh!bU7DnLFVa+S&zHIIJV*W_ zFLTiwds=bPGxwGhXMdq#E!M$9yrKe4DjCbb+4|M0xoge533a?|Ixo|N4wz#L`CP}bE`*~)D)cD?ne^Ol5v(KMYYsI-Ap)vC}y&qLS6_(wV{}>nktYNN>3UG}p@@6i^;=Gx^ z%h20#g2oj-iE*Lld}2HWjm!C@IQt8Y;Nn_WjjplIGC5uMj>NdQR&(Bp3!h7LZD*gv zxTxj46=$D1rBb;15qiN{Z|2-T>qVceNsJ5qQ@Rdc>zCc-pBNX{?W%OYaF)#OH1kVz z&F4IG;aPyL|LmC<7d}EC;1_?77MjohN$Ki=IgiB}(Hm=+i|b)Jx?fc7oXKg$#dU8z z-7kd3igRsPuhbqN!C7zS;#$X^R$N^7xVMjS;m;bu+0)ELKd0z=Ud26^#JHGC7~Knm zCMhni&)wYfWiI^1HC*InE_!26D=vEGev;zsFEq@BC-)$8abGA&_Xu(9_zikKn8~b8$~$Pb)6&LEPKNxbSC<;OuGUqMwv>zvHHHs=sw76k`x#ItQVa9 z&0O@xK2}`x%>8_f^Sp#!aP~BFajz8jT#-+Vi#c-M%*FlpCDn@j$GGrk4Uct^?x*aT z6qohvBku23ocj?PGZ**MKj^+G@*m^EpEb-Cx(`}$_7oa37x&`hG_I&kj0-*I6XW9k z%lV`@`wNZW;=73``o1Rf7b(2B_%7oeeMckmGH3m@r~SLN8iz~rSJZxt%X;RYNj_%Io+5ANO}i|$ z4=Xj?UUA10hs@VhSZZH8GSc2C>urb3fB$oheM6lHm)?q({$-85LAuedS}QI**O7nR zG96_udWfKYUcJbTG8bcQq;W;wii@!t(zwFYijO_L+^&xDvp1x9$^7=><@VbRE7>d1 zI>@|pzIFD`dRBJjlfzRsSZBA*D(mu34i{tHp>f~PykstV)2PpDG#8l*PlNnL-inJp z3sTR*(~8$Wv&N2JjIi%{cimydkF;HC_sJaL(wKP)%FlWA3`Cx}@B#7^c`M#y)pC1i zkBau)G_K5V6kcbaJ+_i7pIknl^f5G+&?m-)e>WOSXk>on`{nk@EvwkC*;Ap++oxM+ zKQOSWD{sY*-(O?T48!bkRBOeX4_<1&P;jVABlFJWzl;2f#@%rwhl}3EQJ+FDbKx0B z{>3OSbJ0&u>P_UW__7zpU`tS09K650<7BJeP%IVw{m}GJ-_4Dy&$`vpcKPKfhphRg zeV6T-D)ikkkA6q!WU=DAQgkcp*tE2~7mpg+dsowxLtVdxB>AA^rF*=mAP8lvBqA>iMmj zrTKcD53)9YBvddbu4xXT*ZQ<|68IUsA8m)Uq?i*$U&`gx8oYs7jo7kcS9qSPC* zCMmsq+^zIdKjPSZte+~)0vzK5riU3Z=j9<*FAbwuQ@u@|kuW>OKM;6*ED{C%a)#{vIxk zJyW;f*7*m&Em z#^H{cdqa0+PjO}^ABP;98`JRd^UksP#MXH;Mr|MVeiV+n*K^zCJ%b#@+I$C%>*m{L zrRi6puPp`Lx8wU_pT=9|{G~NR9plxGy8^a0-g=t;&btduNAD^fn6H}5|Dry9sn4M! zD{p(;EZos+cj&IxWlkFj<9hdLl~BkB9ANk$a<^1tdTw4b9aq3 z<6h70)8F&C&7(zPax`+S`&fVADd*Xp&soNHCHml{-P@(}D*ioYm8aeuiJcGbb#R@B zRvJ0~qoLl!`R`g=*~cm`_ZH9N z*OS)U<&m&oF!R17HLkTysF9sM@NsKdyyxk ze%y0pRiuMzJ$W~mdJ{Tc53BwY)rfoj2R?G2ZvKIW@2zL*)z~Cswo4Sln}~%6aKCKvn5}x=rTNXO(IpEy5k)%R+Ze_B$YibA7g|wbEO8(lr+ObBL^w^YT5; zDld;KYh=%O9)I4-_jFk!=jAoA$|uLu>V7ScEBnZLtGuj{*GIm0$oFx1tmJ6qT3S!> zS<&_0w93o=?w(Pgd>>3sUOunl^&)z%IWA8tjhvV7=~j7pUb0>u*GePLOTKr@waL*? zZ~xQJ0Pbrg-(Pu+5;~C9jkRt}RO4D(zUIh^M10&@R(X0b=iTG+es8^WU#2>9|MA=Z z3mR8X$?-{~2lsr;y@`25;*%5=9rQ|46F=kl`OA8lTaD|j@m@PIzQ~C2#f$gGqpLS5 zpRoSk`h+~!3G~*)@8R*dSJH^NJ9uwAde+39Pgpl^eL~({=hAy?*x54|_C(&3fIN?Q zU-A)ick6}f!@ReK>pgRqYF+iNweR6lcV9@1$yff#!AjHm3_SR9v_~&3#~NXd0q?l5Xf_lM{hmrxb8n`#PKt) zv$^NQG#Ec>lIIWmxU}w`-F2Rx%^KJF#Czp2{-@WI1TWXQD*5x8CMd)@i}grYlSDO` z42^3XF=y{Nc#S1|T(4wkyw*u}arf-%DG8tdtLujQJ;HNw_rhJop99_+&pxldz2}>t z@y_#k?783ZxNh{+xwgG)J^OfE7h1f>c}={u!ogc_J_q8ry)_Bry8B^IVs&V(@ zuH`j#oimdDgSUn629(lZbTeYfJ$TWQ>5xHPg}<{#F^ud}y?NA^Ajq!Him zxO+&@c;~rBQLOT&J`?qHYa9aIy}5XNUPRBDxbq3e)LWmBkFSm2_SUeg%hU56mKcNg zBp~NJK9XLjKFqtl?&nwTwGuAzwIAkP``l|4 zKaP8yKUhDjy!@;zzTXc$tu)^G_#Q>|NAm7@CFtdG-L)TRy!+=hO{jFg7o_)5k{b5+ ztWz@1Pp&bcR}ZFriT1!6jIT^|9n2cHmd9dWbFC+D*0Y}*JwBZG=%s5rT3wT^G>PP0 z{#JQDuSGZRu{`?!h5Lnrj;SNzT5Vn{F)HWc*G<;TJV7UF#6KVEz}<=u5IA8!qh?3s&eeA0-yyL(B{c;~sse1A#EbH4(;YrQBN%2W3L-{tQ4qHs-^L;O~J^vuhpk@YhFur~SU4_yz%_XX}Acx=~q zc~U-MeZ2Jvd3V1qA8$>9r#vTj{|?^E`@Hi!fAhJKkmovq-nH?2#M-#OzjKde?pf&A zFCM-13H#-|%&Go^^%GUpk96LOjQGcUtmJ6C?^y{RALbMGaZhf4slWJMt@3V9N&lgz zmBu^I^ZdWMU-Ng$eC*ulSzC9X=Jk*7*?W#jYS`cH=kfm_Z}n$bF(R+Iw(g4Z=3tu)^G#Lta*M=PI?<~?i0opIlcVt(Q! z?RU-7-CLq_rrQ6a5&n{or`D5q_u$s>+9h-(di@U?hrDKjyK6tlCye0o$Amr;j)ll2 zk!MeL?+K3Xo<(hvnw5Xpc8*?H0gsYS<_pJ--8pq2KgVF-NQcPLKG%O|ChM*8vX7(} z9*Oy*tl?3`@wV`{%*+1dY0w-UVveGB@^Y^Uj}R&5?$K~otf8Ejdw5Ih(7TCe9Xz$N zzm;C{7xU#>FE0DY8aXffTY1Wwt!EVBjvr$Rjc{RdO8-Kbui^U=ZsZe z?(LiX!C3Re8DPBMu|BqWeHIuS)epvq4i|xOaNBzLWX^eDy#1gUUPyTk82=em9E;sQ z1B~bIm%uUW&I9Az_r! z3K-k^6~~Ux-vOiV%wiaP_AM}eyQVlsb$$hm)8?1JnibvvN_R zvtWh08yCk@uTFy*H;pWYS=XKgD_mT@9=3|U0E}Ix2V?l=KVaT9`ulQ^Ui6^0w*gjb zeI6Jup z_h5xPQU&8;$4g*rt~A8yb>9Hv4;^Se{;z?t!iiv9mq|s&hS`f__6P653I`Uazq708 zJFvokexv!-cnyqYh8M?DnN?(Lo~HzkeESj@mz6DwF_Yf_qpd@2xNmHQ327$4t(#lH zckejJyJ~?4qX&DL`~VwIvfau$0_`S@Te8BocvJ+MQF$=Y zwv_tc;a?vM;4)xb@T4J@qxT_W=;xKO&-tyum@z|TyhHCd#^n($F{s~RV7xG;1zvi* z5*QD>ZVq8XRvQ7+roi#VXN_HSU0qgv1u!-{N#kuj0gQJ}H^+X}egVewKZM}5gNJ|- zR#e8onkRv=?d{6wn|3=eu6P&%w<4As%bQMtm}AEb|4Bz66;Oc;*5Sr_?Va6>} z55c)SPYg!eqQmfF>AwbJ*;LozMT2*S8K*424!+|QFk{AlZa`SJmj>g7tT#Z>o*9hC zNB#!BaRFe)KMwALkc&0IjNME93NefQfzjuS{m@wt2FBj|uY*#+AIun>^*U4;P#etn zuHX$gx4JGchUK~m;T-~jacTR*aG>@BgYngmN1@&<%_`ov)DI_o!>*{3#~@39wNlx*U`-N*NV-(Z4VAF zbO?&&dt@*Uo_iWHmyAF&J{fiz)R+-y#tSv#U|^vLG~?evaZq>X2sGovAvd5%rU+!* zH2Ma_Egyl55B8se9Xp3(iY`52_2LNR?VGz#!D6~T<)(ZeLf($490!5)|JVBMZUJK` z&$yHFJI)Qq+?3x#K8(w!-heqzM&PUKK`@2%r=xE`uD!$YI&B{&UEugZIBZd856)UV z7{3|Q85uig9fF+)bwb7#p@VVG^p41QD0mPyIn)su>%3v1|PaY1!{gpd-Fq-oB z$bavZ0r;#}M-MJ0pR5^2;&I9!IMvyM3n+ge!w3}j-A3)_yY9a(yl2Bm$6{FK#)|LD zpkIxyz}S=Ww%c8Rv0PA9>~(B2Fg{9K99KPF3yj@;s$+{%+rWM`7=2o-f%|2OVaV+H z9$b09I-VJ}7#J(l=f6FpV}WtR^D1~;-2{w3l(*rz=3&5i=SM#r*tk0|hVHM9v0b)9 z%{{>gL2Kb;s>hJEZH^DHRjWr3{wyb$anIC;5IZajFm8PM0IDp=28<7jK88}Q{lScb z&OC;hvulGHFP;AvwiFBk#!s^T3k8M*0%M~wX)&y6S}#zduspF`54 zf+;;%IPE8xSM>!(V^BH_ZC4i<|Nbovo;y?v1}ymmFFmR6!5h(OFk*#2Ogx?r3(Rfg z!BS7s;(@R00prN6|H7rb^?)(1#uJEc% z@U)n*;B$lV%-F}!Z&FSeaq1qV=#t)p0ht~`=)%mv7_nh3R2~$FW~}Xf5z)Q z8smp|&nC|z*V8*2<5i>Vl3TCX- zq6QYOy$BfR*zCA?>jGe`aR~7o^pfpWz)0M?=>sT-zzc3fVX*=Ry}gW!D)@Wrl<&~T-JnIA8PQMYU2 z-u&}C_~@P;SG6e>t!$} zs1{a;o9Dru=^A0b%F7_OXD|-jJkNuzAJ@n0br%Aot>!T3wKWZzv2)5u=-ehXn$dQ5 z0JQqs7eBxmL!iO+RA@8dxhJC_&VCWhIHk}qST^t;B_M2vFPicAi_gKI`Zr@WpTclw$T|1`OMMFdWiLWC z6V91g1TK7j8O+$IUI_^Q{1TWk_|8BG9+C>p*s@DZO8k4(gG~kwf-@PefEnK$%L6};NsSkx{h&`;9}iyMPz+{8rb07Tt5qB>yuS=) zY;rmeyt;n@!Up?6!S`1^_;5iXSl#$6`03>!Z{@2VtZ=;~931*5nDI@O{&4B?pJ2x8 zTZTbo&$F=bSx@jOch!S|PfEgpoW5wr?Bfc-$>wQsO2KlFt*4I%bN@074%bVIK}CAO ztM)z~eATc&^s4TQW-M}}9hQo^0A}1WraiX1c@fN5AZJ?)|MyQ|EOostRv2&v7^lPx z!cQ+;1T$U^9E`mtT>vu{xIYA!-6uacp2r~=`|}lGOgXMSrmMaU%-HLEJFGHpJD5?a z))sr^*aD2x@3h4iT{i*auCjyi!l> zkKPUginYPJ{nmQ$(89JjZp=ntY}8>0R+_O97z-PN(0AB&m{)ixI(x45V78wIp?}a0 zI2SYwZ?)Ut!4&Pou}$yIz*vvAUv#|;j4gg1gtv~Lhxy%y;Vk`{2P++HL(h&j1LNW0 z?eUKP4(PV86;`;v-h)p@wa0h6&qJl%tq`VM_28S>HaKtcWnj#;a~Oty+6&EiX2?(s ztK1XKXrIv^ub1eBW_&Yz0Cu?41I<|OxBj@KNLOU6_jmyAFW3zkXDuCu9b0xq#)q4S zVxOP7A!Fos$8E3mp2+x$`fX?Q!iP1s+8Pz_k$@N0+kEPD!G~^)8+F{aX=-O=Y&5w) zZlXHn#}c+-VO`Mfd|rLRl+Jj=(I3OF)Ap>2wmCuc_de0{wqb93;Qmd+uvy)%ICowT z3>`h*i0RuBLz*-M#$DxlqTih{#sQ@jK3p0Mj5+g#puKE;V0_T4B|f}W2N)Yg4aEXf z=Q}tI!%hSPWB8}T@Lc40W4mv6-11dJU@Y3C2X<~>9~d*{>5hTF*8#@a<$Ger!cCz6 zi0M!-@#Vv!PjFWkLVnn+Ja3&8O^TAQZ^y{-AAfgaH zJ3Jc}{ZkNQjST=P3gNW+8{zHOh0u57Y)G@CG)`JP3z}9hjd#**gj=;rqrLD37mhTuLTE<+g6m*%DAl_$BJUgsYFQf1=znZ3OltoH zGDc)s2Mt?(fsD%j^-!ZvX*A>DUK`*`wKSUXN#r_cSMUpDjEPtW9cC9s#_LNqK;vHv zp&8E&oC`BQ{{k7a*P9LH-hP2*eDlq0IJ>J5n(61Df&u-T5%BTUTUkReK>!8QKLITXc$rxx>05WBPTg z!7r!_GTzu4f~|UXK*nvq#KQg|q1fU5mzXl3qX(;>qThWf(hV8Isjls%ZpirNn;7^k zJQO3YG{g5Py5Y0J&2Yt)Zg}I$eAqp`D=tja9CH`$h+RH!hD-Z&z&2fDVf)ywIE3D} zflr#jt%jM5F-DXJyVCo7e6c1Fy~2l{MNjnL@#DURZRWSY7+2+{Ey^ARj3?;2(u>~D z=T@gOj@Db|L2(_5dC&|pewNuN@zrt<#;i?kbktS>V}T+!ZF_!P4vbI7#ov!?m&-x= zMiYTiqxU)Z#KOQDez3Ykln2MOEe8=leG7~Q|E>%%oEXYh2d@zdOz0*j%~}(YCl=Y`EVXzL_`^o;_`iW-O3u7DN|ojb@Ca z>%{2OZICgRt{*v@w?W2-`!<5l=dICALyV+ru|e1=xQ7_j^*99Y{17+d~%1N;hxf*Eg5`5US{?g(ZKzj74{M8*JP z>7jo?XwHSeIQ{w!`YwGQnDOMuzrnBlTrlG$O+mkNZGiDguXhl(q$Mz3eE$l@PY(q% zUh4b?Qsn3aW-QVD9b~+`02n*wQ!vfs7+?%(_6An>nhR$9H|1+Mb$T9{vGk=I(Cf?2 zFn;YNSlqX{2Z!yAgDulr17n#hanSBBy0^Ho>e(A`>%bhC6?+M?f3w(w&A(PKXO=d= z*dg6(s8XXd^qj3>-05Z>eCP8TvTvUQO=oGCwd7(CUj9zOZFv>|W6ito;MU@Wz}OdG zLFTD*;d%oVv#wj>!HY|8!t`NtA;@tB(u`T+!QYQugJK640%LjGD~S8EBUH<#;={9z zJh&_8dnn)^0*o_WT!Ss6Lx6GpqMH!9sw4aybOpjXH}YWY-7n}f=?;T2lKx!XXxKi3 zu}!%OU@vpfFk=OKS@5fQ+%RK-KZ-$>3$=mK@7xy7#b7wq+FIWVrO zToLX@+96u)hO1xv;=#;+w#M<}BB0sL*6`xpF@urw;ayvybHYGiTyd!@#-$kqj6e73 zg0cA`fN|!6ieO)GjQ-n1T`5feVN_wIfRa-2QA$%Rt&~$zD`}LX6pJb)m2}GgY45w^ zvN*c7XG^T8*cGuiRP2ff_wHct1uJ%9@4X@h}-Q8a4o z8e5F@yUubCj>OHw^S;mfe%~LT{N_5>o;@>r=FIHg1KzVI3#$&S&Z@GkEE@{|1~7x= zV7XXrU~N{P;q&oK*%^W)+w>E5)h-t1&;uSuNHG*of6* z%~(s;0oZ}Hg+&oqmO`n2I6%g*w$Ccq}F1}n&NvIf8gtTpps=~!uCY1W)& zX8Bn=U_0i^I&u3+Zmc7)BkPaSjfDb3*+@2y^<=@oU>3qY zWxY`QQ2^31)Rl}u^DVOTY)kc zIF~H|E?|p+i`nPE&vAYQi)LHdPT)?qiEU&%*jK=>*m|~s?PA-2+t@0$nr&yhfxFok zY#rOf_5$~^HEb>0$F=~su$62xJHYk>_p>kAb#|BC2Hs}Bvj^-MdklQc9^1N;d&eHKKbWFCMA4NO>?M1`UZ6Z@-!LaT z3_Q$^vs3J6b_IBa{mOn}*Vr-OG4?$>$Ih}iU>rNhVp#$^1U$sPW=Gg}><8cv>;yZ_ zeq=uZe`4p^MRu7b0u$L)7SC?5TfkfFTXu;(W%q&i*-3`)jD`k~(ibFAhrcz$1pm3!ou%=Q;si@RYY6EL4m6a+=9i=|7 zzT%@)Rq83#fz=gnrJB+}@xxC8#lTMkB>+DSlv?;{pwz`r16VXtS}UD^os@P;E2V|f z8Q59rsI*iXEA4^pl`cvXrMVIe3|2ZQfl5=QE3m8bsnSeos00Cnlx|8}rH#@Z*j?$N z%vR~^Z-G}nnlg3W&mbT zGpU!Ai^^5yGRiIGuJTxU34E!%P@XGql;45BD>sxsl!wZB;Cba&ZQeG<;ly{1vUO-7y{!}umy85T0t9O*&l$>g2 z^*1H6`c%2Ec&Pc+`$~TGoN^BM4)_i=6HzNC>g9yp9n|tbJrCGDMXijeml18XR6DBe z)Rri1)GlgowFj_=+EwkZj!=gJhpL0r5Ousd4meI7qmET0)K8DBvhHRPCn@RC@w@s(n;%wS-z8SYGv2{ngrP6JQgyp;})JRDFOxYGt*i%GF}P zVrpr%s9I7j3oNUaQY)yH)T+R$YIW72nraPT4YiJ1Pi>?&1vXWitHssUY7j6;EvHsf zJE$#yEz~kOc{ zY7x~-4Od43N2&oh3d0qOpcF@|EpVm`iWjaHgxcj$Dx#&qxN;SgYPdpYwB(0kp!P_3 z5r9$)SLh2b>Y_A&N8RB?W0YpJvc zlfaYeY4wD%wSs{2%@8mArr9#Fqlr>XPRnZTLq z6m^lhR$T{Nr>;;}t8>(OzFQ_dEOmi87dTgqQWvW$ z)n&kC>QZ%;xu?u0adYDDmn|^}c!+cvroxK2ZNq9|0e!_tdBA z@9G`k9rcNNM*T_s1^A14UcI1RQWJrR>SgtsdR;vSJg5Gs{;b|muL7^Czp5A2hw3fh zE%mH=MSYB;D<~InbW42(e5U@UzExkUiuM*Iot9C{rg;E8v^-iaEx(o)m{$8l%c^D3 zUZ`17-l%`7uhe(Icj{|AHgqkGrlO?R+_cP^JJ4OruI1G7YWaZqG*9g>wSZO-SWshH zZmqCZ2v|tVplMoBtq8D)mP5;=71N3Xi)+u-=W21S0AvBwVW?RY^@_qS18Nlm7K2?5 z)G7=tjJC>YK3WxE6|JIHT?^0*prQF|wY5fCePDg9uGU0rt+fQU)S7E8v{qVqV0o>Q zR#mH})dSYk8ft!;Lu(9dtToeWX>~LcXlgaIl3E3=GO)7drIppV<_q-IN^7OG23k#E zP0d>?qczn6fq_~H`~;##36zqkQ5jZVD5X%t7gnWF%AiI~wB(IaR_m(`&;|hqX+yN3 z+F)%saJV)?3(-bt1Azmzep(x?qt*r3MQf*Z(zDoD;ACx_Hd|Y!tpKjj7HUhisoHel zbZwQkKpU@x0mHO;+88ZDn+Tk!g= z0(e3@tbMQT*J6M%+G*`uZHKlQxLNx~`%>GkeFgkV+otW&;E&(rTziE55quNd2P3^w+wYEun27IPH2HOJ5 zO(@S$b1%;BLirgrzsA{kluM}j16nwWa#Jg+m)1+_MNx|D-g*_i60nk9UazKe-2fW8 zpI%dMpw|V~)obf@^!j=+U@^Uf?xmN}9YBX}>Sgr`dJSL=y_W8ySJx{8E9+HtRe!DN zKwWp!GwZqZ{J{LWhn`n2tY-jb(9`NU^sM?TEe8tIUuthO4XEkwv`_RjdV2j6luUXS z-CfTP%&zCw^XU2X0>A=#Aw8pBN-qK|qAPk%y_{YVSW)-X3+leQKhR%Kr@z(e=>b3_ zNrP1py&kY0j?>|6DV#5b`q^Mn4pVb=wW&&FjNoG!}Umg3UG=(QJ<>M z(Psf?>C^Rj`sex*;1Ye2zEoeP4+jp{N9m*WG5T!aY<;diPM@GJ1TNGU>(lg^`efi_ z{WHC#-b8N=Y^`_FyXd|2LBK)!0KKn1L=OT6>236`da&LQ*idh(H_{vHEr2cb=6Wl= zt==BkUhk-P)<4y|0lVov^?rJPeIRh4K2-0ZkJU#4N9uukZ#_bv1e~M~)`#gc^eAAI z-cE0(FW2V-=j+{JH4;aGD9vyt3boszbkKX~3-s~8@p>QBo`l+iQHJU4;g<=k+MMOP zc}XYnQx#vDUrD_8(t@VYv&u1+&CEI{_=cjF4bm5kcJl5n8)}DD`6h<+Wb>f#Zp)tZ zTK!zLND{;E08Y^co$*aRG2Wcs2_vcGk7k$Dt-A^qCxyHdreeX@_ee$JFR z`9}I&t>>EAZU_vj)echp8OX)Vr6Hmeey@<6hpFE zx?#I%$0@eduLoalH)Z~Z%Qu=EId*ok+959dPstU;qLaxy`b(VR zOg0=v#AzIbjfey3MIZl(i$0PK&BG8}YuBJG2{Na7DD*O?_DLVSC1(P) zLq2>DPIHpbyKzFLSavSTZizUU0Jc82_Z(7YP^Lojli1y}8WqcrQ!1*>bz3mpR!8z06-8iMI4! zUybH6r@CEs?&YMHIoZ&4g}va^rm&Ye)fIlqoZ8tk`D@G1lsx;DEy;Sp@2pvBwNL$( zd4_xIlJzpDc)mjXzkTYSAajbR(94``5)gl3FF4tJj8h-aBMt?B%9J2;>f?39pY$>( z8=;pu^_}!zxMfR_Io0ii_>*4dWJA{#_JUKJ!d~W7SNJJ&YUfMDpZrY8vmyRMFF3`V z+PC^8af-Rn%Y1mH)d{Z)9^vuM&&-rO(a}-+QAJxBJsFoFLSb4%`$LmN9NSN z(966!Kb_o;;DZ}(N{DnG=65 zBRKgs1@YN_?mMTyK`~= zC-(DWxhHetms>ylfbXo)(9)BQ;MKts%H&EQ`%AEwdEE+WEIru}kN>q{!d&A!{&e^t ze&FjTPQfcos+MqNX5E0tF1_HfOPVI|zQ6E}`3G~EQ(cd}za+OK_|dw9oL(XIt#-yP zSm6--5%k~H$Pv&U?U3H5cMi)YaZGytI&XW67h6^^K=6IgFKVS&_N3RxD3%TR9|iw& zkIj-mJ_t_!UxxpATzbLDX9NCMT%RRD=2SNi{1@#APX3pK|I`loDLDCm6#iF2JEX4) z|H+2@e+B=Elb?c<{|n(i*^^#_|70`&MX7)`mzwa9n-@(x9^EH@Kt{I+%f^mBs^Jze z!*zpNfo^#QT9bcO3S1$aq<3(=#$Y&Vot!vqFsvBucHN(&^J5D|n$}`U(8#_*Y z!Mjqbkc}Oun22`lIK@`@W5=7%DTf#)^~;V^-S!x-$5$h{9T#InHg;T$5!u*rF-Bx# z$0@eLA3IKC6or0KJ9eDvMq#|3z{ZY~4*?i2va#byW5lYGjUA_$h<5Ba#a8%Z$7zg2 zzwCHYY?H>6xUfI;+0XAoWyJMN1((EUp`c02*G746vZV;C>tj~#b^ zI3T%?so^y4;@(LO7voO%QEIptcd}0n7voO$so^y4!vEB88h4uiZ5}PQ=D@$=H12c{ zwuQYNr*WrynQZKM(zvs#WMju^+(kQfoW@=FW5;RSMZZ$R$sciF{CByyF17Pt<@Bs; zfzOx35jUN7oSvEKu^u2BJ5JBK=~xetjUA_FxM;_Y(`SM3$Bv6N0A0(DQ(d}$ufWER zlMnP9AR9YQeWB+G+1PQ4iD<`;Q*4Dlc3i9hs9$!R>NdrAr$(#Tb!|9T#In zHg;T$5!u*rimmX$j?)-L;yFO=*m0^Gf$<_6J5D|@jF<4|V?1e$7$X}yPB9U6?Ks6* z_+!Uuj6}ceIQc;LySOieJw5-$JWma$=fAjjQp4%_FYd?GaC-iW_EW>@`7iuW4Hs*G z+`l|@riP0(KrYzZaj^y<8#|u#{Ew(YHg;UB0m#OVi!}h**m1E2pgyLC)3}R!CpBD* zJI(FXa53&=pBgU4o$OP?Y21bXso^y4H2>4&DU^^JPUBAZAlch-8h5&v$;OT+jXPsx zW5;RSMLTw!#$EVh$7$R}A5+80A9_B}ocZr^ab0TXzsd)%9TYGzES5KHjQ0=N@Q$af*zw0(ha_Lij#J&!wVDS+=P40j z$H@m_W5=m4zkJgqVBun~06R`~Z`5iOFe6Wy06R`T2pc<2eG%8P<2RQKNbWmvVc-1u z2B#QDJ3gk+j$|7<9#(a?Q;ee>r@CT{>^S)#Z0xxI)wRjjvg1@&jFBBDAB2q^r@n|- z*>S2X#>kG755mTdQ(wfj?0AceTax=uT-amnDZStKf0JX=!T+^u|7ZKzy=;_Uv3KFl zvFFyrOg>lCzXJH&n=|~^rW+ko34Gw5Kz|eG4!#X{{&cTj%)o4#-&^Pd8!WGWa^+P2 zj^Od(dk;`V{wHH{3fJn4YqjmZ$?waXGh&E)W}A56zPlEi`AxX=!7KZzW zqMh*j{rn_;K;j?hTXxD5TMXA~d$*sT#Q(?pE?w(?^}7FVJpWVnn0x-NxfheM!Sekx zFh+I84E1lG$&B#^zZ5hjrp(eqG1)LDi_~B4FU`sQ(wy}BPx)iljx;9^NORIpnv?!^ zb?=AVj?3;p*!i`#-u$v$LFbSo9?lwxZ%t#kYCe8G#99C85_90qLOk7`T+S1PR1SSS z^w>7CGX(xV*%?QmB+9PMywr>;nJ7KV!^Fmxf?iiVwLvKLubm=+t zPM4nSg`Vs!{ZCQF%=_~OIs46xHo@Zs|DsYhzO+~|=XGC=pDj~_XXxa?AJ%+9He}Bw zdy9X&Cx=sQT8w*mF<$oy+8&kPsSkK=X7791xRr4@Zs2HzYf;kaS?usYbn6TkwgSzpk%c-t^xol3Q zWHIMSKh25pa=OMV-sKO?6X6fV-zmjEUWz|)5r3hl_{U4}cS`YhVod0m#)8H{jD@pt z=ohhcZ>)M8?(_-!BDUB1PJGd`ck%N!t&N?$zLRr5xNIZoO^M6)rex2jhkOy6abqWb z7w@aK)63VDZ2q6{$IgGL?;rF_)=OND&j<0mziw@8Da0q!qYvXO>t!EgF2#yV*ZN=e z=YMjoLG!Xe)`@-tyxn65z6s|tKacg2+ulIG$M3?q%)4L>F}`e+e-QM;y`%hJr1>i* z6m`eIzSZz~{*9rZ^Qb~hbF}FP{bsCVUhO&UcNzNB@Ujur{Qkf-p2I#hT=Ll|bIE6? z%q9PwlK;+M>o4~!6|>O4CO&t~an)k(MP`nzjWv+ubE>%HvokfE#vtk6hdER7*Bix$ zPMBnhv%-dSbdHWGj|!E4vVncPuzznC;gt1g!}+mxWIfuTI)C#=*1LH8`|A)(&NXBG z4r6EI^2f4qUDx98+p>J7zFT_P-p+>lL~Xr4Pb@jkmLBaR?0U4vSc z?ddq_UxYP=bdHW){#e{)0P&%Xt6v|pNghY)len(jj;zNuKQ>-m*1LGhzFRS)wy148 z8#(^2>st1*Kd|{%<0ax_)uld(>&orOdie9P@uGfNZMl5@n2qFLQa+-xYwyM9(7Rc& zq-#iZt#OZC?ue%{v{X_o=^A9?^2g#`(@l#jd^#fj8f;{H=nbKF#o=%E@>t9EXvdVU zYdh}3f7zbmC-uci*CwCe|4aJ4TGVxoubAg#pK?A>dsd+~T=svnarMPXHnKe(C;j{1 zy?^PNQXg&SMq>I4<`BHY$}z6ANu~Yq5Ki%vVwha_&5+SXyAS&mu=+nCHtg*N%LRSm2GUsm*VlS<^aWs z=ITGq0V|fmMz$B8NzX&kj&<$#=ZQsF<3m2t5!$n^P5k}8zx6SB9Bu5aw#1yVyC3cD zcf0G#b3mSBc4IBKgZ^3lB%RCWl=rfTCnp=(o{p3L{r}GwG2dMAvBp_MC$)1)j=$af zk>fAhOV@H@&VTe-VP_-X`zdT}KNphhlGk0<+@KiHwcocvEW#=4UHos)cJ%9C-TTz` zzqvw|_V0cA@H4_@yvP^2FRXT4asHdnF1^)X8yhPwN!L#LOng@Dv-k?PM_TtB zU4zca?c6H$LmZV~M~&qaOFBn3E`KZ@uq{X2=8GBP^T0;7hu#o+xvp&Qiiv0^*&gi} z(sgaeUHC8CQ=Fu}d~6O_*AsQor(_!!PZ?V)_SCK`K4kwl8&_W}8mM>>}c*0 zia8_Szw-Sh-@kN^iu;u6CjI*`w(=a1=a}7CQyX%hMI7hs?!@=8-6o3Vw~dW6g^e|4 zsGF>J@p!UxU5jk2zDw64`+sFa{-m^V%6_`IY(rxyu4Rp@Y%ldarA@N`vW=@RCi&sw zcGt4{m`a{Os)de2U|-Ip9-o9yal@IjvAR{Fq(|+W^Yi_8(uOXM^p*`h!M@Mx&Yf5>3F|0Yi)2KXusf^>-_m}72f0vt= znpKtWE?9w=zFd_bT~vTyd{UJswj9G-ZEe8&hhH~_r*$In`N^X*%&ndLlu_^xApxmUXy+<2()o}+5;u>N>A@4y=T z_fN(p%W{Kj@E5Jda61{>sRl37$b+xzT!XhV3-EMZYVgq31^L+SHTZtS<~iiDeHHln zUNw00Db;w!AvJh5ujYI^+HGGZ^l!2z{AhW&FCSbgy)onda=XI81Y z!VI3;k`Fr2hv(ViVXW>EZT9Yw+wA&9wCSqdO?~NG@aya`4`JIEo9o<3UMYJKqQ{d_;9#9V(C#_$hucb^M}tz;{Rxq$plUKiIFl5)m%{%M4j zJC5YxFU#;VRYxVu$Z*Enp9|$ezFzpwTvBi>7qT((1qVzD#?XUi{YF zcyu%u^3Lz?%<{jCphH@c;>M(vt59301@ATFjU2`lKa?!IlW{#C(@PCg< za%fh@gFg-BLiXwR+PoDwmJ2xr$0LygRmiTm-lsLfxRCR&yfL3+UJBWvIpf#nkLE(I z9^y1-tqbKsZk`Zht_v8&g`B$iD>D?wLN<=uX6{;pc(|lv)mLUT+7~he`9vs3tB~6- zA29cA9L0@QFd>8sxsdNNFC84sg}jWsAqQ8D;X+0s|Hs~Q7i5byRE@A4P#>=*CoPgr>0IFzO)ukf&vNs^9FzNus#lceLnbe=59 zj*f*Cxk9dQLw-x-454H15+gVrlcb!F0rw4~ca__gq~qwE*R5lc)c#UF#%hlw9k280 zZyl4Q<5NaRvZU+Mv5+aRN5?cCbbXSPqomO3dyYp}cN-+>IH+ZULB}L(PAF$S^6A6x zH_FF@GX)!)?ga2cPr4X~7Zo=f_3OvS4lKZfGX@(%29L~Z#=@^ma|&~oKG+blMCVM% zpWBZw`>GgENE2)bxo?JU7WC@Fz0V={vmR^+`LeTO9xm9E$G#}dgVkU|$VXdsb5GuG zym3C{0kKq;6J+f2lLM< zK3UH@f)JmGOFugzr*1Z`wC~KzAU-V9d54g(b>|y{XLsT;QH6O#y7LYpqr5|m0o^+D zMu-p7&pU)Xf3ub0wj!8c{0Z@S_p?LD#Paoxp6j~tzKBo2tDhZ0ZXeXz7{0kDf9X+< zCqDn#A>@Xv>dC#Q&o|C5@5Xc1 zoMb+llQf^A(r>cnQ^4zuhR}~gyauP+WC+=NOStLyp&u7AVBRou@bdmVGv-%t+D%5v z}4Kk@u@ZcA_s4><{!y6{f3#7B7%8;#CPzZO@@%? zr-hqwO+MwX5#QzmHyJ{@`%W@@PVB~KAifm_Y%+w5xHQ>(G_@z@R+99@Jj~O7lObgP zs*}u8%LZ{FX+93l9Bj~hOu+pb79MWq>pg%AN%OIgTd*Ny?asr@{mc4W^O9ueC~cQb^%96ik3eISH;BChTOyBR{J+aGRTzB!72 ziMS^A>t+Z!w9X`R;N}tBfw)HZ>1GJ|J>pqq?NBb{G0flKUfm2K8-@=vAJ6K^Q!D4g zzRKpIJhjquOBeI&7Y^R|W*_eR`4l6nUTt1s!W3g@$3EuV=O&N+rYA47WQrlABW8q& zb~2;?@Zno$G~~fkrWiuf{Aiipj~D7& zj|WehVhGuA|0MI&_4538#3#C9UZZsV+ISA;F^W4Q%$k9fc-up`C(7nEgnaPz2-B^9 zWqt(l2`-h_5OPA-K4#C`mAG$sFfUX*uOZ~V?On`P_bTuWhz~2A*ASBYF_7yhk6(M9 z=$Y3L(yMtV^V1upd1UUkJUUNaL&%}EdzcSHy!Z>mCn85)L&y_sh*_d@N#6TRa~|xT z*AUV#c&zzDVo81h@hRk%*AP;hI?=rRYboAfW<$=>@d@#M_C>aSkqDDIezz;=fNY#EHJ`u-!=zNTwnkyVIyL1&9xIcTM~q!y2-$p9TjSgxjku7G z^qINWxCMrgQ5U-y`o;QO$SpTB@W}fM3?YLZO^wBO>hS!B(((!q78pXhhnF;t-mArD zuG0A_=!Hy7d(Tn6Pc8mtoWdg>E--`)@R;RrpIDp!vhTI&^=N@1WP;Pv@!NyCJZ9K) z^Az+#(z<7U8pPZsmz8^DhWxR>5c1Tnw#NS7J98l$BEHQZ`xyBUUw5^dk$9z=akJ&8 zT*w&2Ir@o@A*B1mbjI3&U3nSA_0dxwBjxdqjeuj{z5@$NbhqmRN z5Z6cj{R|;bCERta?$U;zKwJX``WZrQ?^M$8yw-+~MO>o>`58hsFVWO^bvcN4L|hXG z`x!!RKi9>$d%OeQ-IF98h-;yteuj{Vr`|eR3~ssZ&bBTudT?P#=lE6SY@ z8r7N~$KPAT@xBY|%`|h|`K~EJeDyEAxHwK+(19nyZq%KvW-*)>(&yD~GXTeza6Z6m z02jv@+~Um6&@Vze{q7CqJ=f1Qx8izzaXoL?72CJO{2s?b=6LRf@2KMc%g#ibi7TQV zLelTiZtp_**=y^~h}F>!AvZkp;+?QgU+`qB8L%$eA!M3y-h37GE%ZGm+Z62(a%jzR zd_3AIku%PW-V*JYuzju>u_)Rx0`?UjjpF?4C1$|q(GDTk!0&Y3k@xRFXBL z>)}`)4*z|=2}wRqR~7Gu{A(;f3j1vDMsjid2=QnSyP&uMyfOV<%q2Hv@5qOq8q2TY z{QgE^d_$cfd=vcrWLX#FEFQ}jqn%4x-XBxEmcTBkST|no#@J+e8vQTTr5A5lw>Q7{ z!*x?gir3(QefioG$Q71&-4yaJ>^~nnfIn|Di1&VW-4wDR`X2>-{VkpNF68p8b7d$m zk>Q3(@oI>6R#*L$4_$rT6tW8JJ#gLUaou@^y=ccJx4`ewpM_fS>VSHmFddml(%?_N z3Vu{8FNp$7huj|N@uOLKhU4^L>5%)Q2y%WDMk$AEBPEdYqd1B`a+(yk&>#6m^5Tfl z4_Qo#BF~2}&=)yIia-)pL+ygd`;h^d0l7l*Kvx)882L@|Am2$*U{UC@B6o-f&;v)= zkYl76uo&9SiE9-D7K1Jqd?*eqj^oV8P2vgkL}n4nqv8$pwz8@eKsJ>!C>)tf$|9eN z7fN}sQpl`Q79{}J$O~^hP<+v1E@U?;f#QWcCY6zGr6Nip)Nnvs9>ojUR?49lK`8Bz zjl>^kI-+z!UKKwabwKHe>?YN5)EuP)vZqu-%k5DDQNssE?NHhy$4XNx(@ITbaA}4N zEkVE_oNI>C9@rlFUg`q_fq}@!(g5vs0Cqqwm&Pa^fE{qHCXj?3;X@tdL1_VOfxIiV zkVB;#up6t3+$bipyL3fq&AOl;0l)y{S?LZmfCe(D1j57W!0Nb8C!DVhtc`XnAYV*N zU`ynyDGz-oU?=pr4|1=J1CF!utMo&Lm82{y;mE<#i-n^MLk5-zWLg=5(gPV;1|!=_ zZ`J81ioaikv~O6R+P7_ z1hS-1{ueKx7xJc1wwN-&GRSd~4mo7X0m~sjNk-&HsR*oy+$NckKcy}OVSznR%QTaAU{bkvaHMo&PKM9Zpdpg z7dRK$Qz#F~eBgZKQ|XJGCyRiKkV|C%GNmj7E<+xY!N~eD0yqMBS(+k$%WC9uX@cA; zEs@7%B{I3RLY|h6$m6mCd0#ppYfD$i<;dyM71$ecIdZ7<1`dQ=j$AW?U^xsKSJok; zN+@!(gdvy8dgNT0h%7G?kn?0M^07=q-j->|$+89|3K)glC~Hs_0x3hx8svBx3d>E% zg>nXX1{qVfAScRM;92B}*@4_BKLdY8wwPVWC~^^a5qVPfBCp7=z+aIs<$#rs`2#ElxDOdx{s8+L7>^7re}EkU9zuqfKfpEu zDc8$mWO_LT{1HEok*VYy@B)4wBO}Ts;1&ElMpl$-z#I5^jLa&xfOoC@Di4q+BKpkzWum}!1{*G)YIg$OP1~Pc$LdkVA$tl3*2GUUWJjqB%K}zblzzZ|$m!A^IbH?=2O^(KC*)`u3Z%R)ospSjIB+;J zxO79dmJnbF^1k#yZkIm5KFH=md0|E)vq?K(7s%1b4buhK9db0zbqDrBZj(@y0YJ*G z5{fbmI1KquLQ#4F#~^#m9N-+}6Ny0nkNLp)$Sg7uc}W%n7bDlmB;*`f3S5dDB~y_X zWCd^qa*|9(zM0v;*~n26j(jXDk&h-EI2m#!@|8>mPJ>*DbJKt`k*_2gWgc)Ia*9M- z*+rs}VPqNjGMtZA*Pg)pr_Fwx-kV-KepJGsaZ4<2;{6bNSFW>omoD>@^%dIUUEnTz zde=3*H=5qXF28dh-m=w&``a{2)4TF}e9_Qc=0u$Q^E_8TtR zm$}_L-Q{<;%e>(xp3pVVhJYZvqh01(PHqgyerizwy}R9x%kO~yC;ro+1y(y`^D(~X z-k^l#buRK&h~dA>qi1#F``X^;9pPtcc#!9g0AVk4dfzsUBfY~uHGB{3JG$a#$Elq+ z?T=gik~zIEoUTRh$WO^b4&LLTF8#+iwNo&68!MhNpWC5rLZ_;&EWOOTuZv7ru_Vb} z=9h+#N*;GRp8n960U0)pw%WAg6!Y(X9BJ8592`GITDXI)-^xRHJj;tdN{wOmwD)A(-eA{drkE*@1GxJU3WnH zSG=OQZJcD_T3zi_GOa2%xUh?d-O#vg;AJ$`&@Yy z1Q+*XHsnA9B;&p^`4T-*y3htzNpbFvrD9EzvRMXmtKUvVp>RYK*A=dI^PrAD`%<;R|~_=7Q> z6JF(*$GhVBFsWM0gbm#fnmxhECS<^Ivpu+o;eO;~NDZgBoyGHcAM8`ZM&%Y5pw5vz_!JR(n&)#aNJUG8bbk6`=Tp2Q_bp^FUdYMzK=vt(gIjt*%z07G{A=;O@U5*Z#!y^BN%tZ_X*#v9;9ng&Xbg!?o*-v7^ij$V2wf7l{u{|I%17MdYOy+j`T7Y z_YvvsI6V{6V~s&JcAR2<6l)B!p*YYQgSc2@5Eu9OKXH1748t0OZ0tC#F>YavK{m9m z5aXB{F6Wk!Io)fgvBsb_|B1(9jUjBrb;(|ET4RWDp*4mF))-_@Ym5V~`AO@Fdst(T zUgor}5PF%@8si?;6=Y9qj6YpmtT9MW@t=%!1#$9+)*HlWjUhNa1JhuQL3)|f+@m#y z$c;nu?KfAR9Kpr?_!7Bp#QY&nYYcjZze*(+>x$Q~m$_JDkY3zJspaB%LO!I1i}59U znTz>G*Oj?=?vY;R;$EOQq=t)_lf8K6q~v0aK{+R`k^e=7{qCf@fX$@ zJHcsJ=YHe0x4VDLALDqA zhff`ca$j>CfWA{UEoRo1Aj5NQIG=yIvwyb94U8Jw!+G}7jbg&G)-%kVct1z>iGCe3 zwlx-h5zbeBe=N2_lWmUim%@3Y=G$U#u0H1&doi5%ztlEvFWNeecDkpj6PI^?p#Sl& z!g=pLUm7{SxaHqHPq_6Re9^BV3&-)qv*+SmopuS)cOk{u2p-WYoOjJS-yluDhJ9n3 z{*~0;((a}GukQ);JBaso^gHy-fBLr-ja~`i{M3YixM$(j{O0Wa@VXaUf9-JIPtx5< zKgEo?I+B-jtSz*i*lU28_vsn1jIFN zkl*i03V&8djpYk(x>5hcv`rFv3*%M_iUftyxyR%qg1o8d|ckHv7SE{^`C`4 z2M70vt-Sa2zWJ{HlV4)bkPhA8DuZI*bed`QavN#+{I%2Dys$VXwstLihc@?x*m6&{ z$8NvyVN6ipnbeMq5g+tjwwc+_;m9#3+W+dya9(&$bWE9}evW70{&;6y_UQEf7t#0c z%DVeM-*ejcJox)oBlzLxU7UgJh1FkKpTv{KeeHMUovS?jq_*6ep4`!a61#mRo!%@aF)2M3<-`BoUcdu;L>f#=DN zk;{xPvuX!o5w}-U78-T%+)v*koZrs7z)0x1>44q1*y-i@IeKv^=j8<)?;+L=iN_5( z(7`z|ujZWEL^mYvdj8lw1C#W2^Fbb8Z+s7AZ5J*6MMQ!_;#QoK#!PAI=kTM)Wr+o0E0JhrGtf*r!Si z%J-nS()+gU?k}>8aLUh8X^r9c_jZ!(?esQl4A*B+QeC@eh}`DWddvO4nfgo2VZ0OW zo7k0(`;oI8%WsD}GZ)`rRL?%~z}_O^&h5kJ#SE#>jh`^?(i+1ltua1`Pin4Ps(xR` zzIyqMKaYkxOUHJL-T$M9arXOgr?kd!N^6V{+LzWCPHBzdEOWl7{~fF`e)}=pDXlR+ zs4MsVzr*F{;rp>?OupCb^z!_Xp4HE>c?~mXKJh$oWmyw@poWscdV^4mpW^Oa;$P-h@ z?+*ox^Bhb#$85>L? z(;DBI3%_Z=AE2EIgDNG<_~YN3YrV0@`sxX@Kp}jq!AACM{gYWJbPN~r(&1fZd{9IF z2JLNqTryd{9J<^5b$?4wC1zMOf|1xY{SowSYodEu?_FFcDETg zs13i;@CP&cRcpSg)?0INp;mk!{F+iYh%fu|oe_a?+V$q0;g0bUviI#L#=ici&C2sK z@O6lP5y-8Gmz{JYJB*8v@8)LU4>0eqLJr1!v6JyQpAYlfPHw{ay@;QXOL6Rn@ey(q zjyvFf60#4D%VQqc$?iBGg?`tEY>Rm>WO*Eq#(i7m^(|xmjsDzijIa6EkO6$xUl)uv z>4)(sw+BY980-tpU){{>H-_IVmy<`JUv}~!&X-2N>|`aJkHqzwzgc1Y)i)#WsI4^8 z9DZU7SwH21JUefjInAujh5UTZ2GcRd!G)|_W3AbAYArr$#7Q&P%$mH0q4Gm@Ilp$PgtZTM zaTC>C8N$M^~v zGVL4VRO`xI$bexl{2hHyo8nl=W385&)t6S}c5-A{mHR&_%U{Faafoj~rWWQg&sw%} zS>NVn^}vjL0sL8v`6y)Pye-V2zE!x8^jwbcb6ERUDr3GCTAtgO;9HhQWPjlwdgzIn zEawH9H-9O_BV6*3_YGrYhr(RQWsZ49x2%QvEnM#<=GCENyNx|j8F>PZUt|6V8K32i z88jp}_k=#EZ0lrM%591H^cN3)Fn^%gxl1k{)Z>ZqwNEbYH9x>muIA)tVb5l6FoleW zJ!(#?%7g2r_nHY~DkjS!^@7YPKNsR|p6$$UpH=4Gucw-SV*K7Z+L_%a@nkuF z-c<9!5YB~cS`2xCD|m9>DnVwy7M^@s)v4yXN%?uUa!bq^cyCFuPj{Q9TYm0fKbY%6 zJ$dGvZ_K`JJ$N4YwGa1KfZGelaE#O7VlNyoFh0q$MGoT{=9T{s1^G?H-wW~HP5OwxjXhecw)bWC-!5|o{=i}{{Cou2Y&?07JQR_I=)#y4P^)Ghn)b+f%IMd z$@nJzcHnk=f4?SnI`jhe!ngk&*b`9~SQk4O24ZKxM&L$#o8BMC^?~)V7hxFM-U8gh zzQk^U&+y&;2`F2!M}l@tG(yRZJqUHN&!Id@e$=cBRu3g7>esU{C*v$Lc7SBTPK5E; z0T7Pz1$I9Kp^erkjj-#W7i3SAAnXQdhFut?P_kp6Lm+m$v_#2LVaG-t_}>lK4LdaIV*f=4U2;$ri*bnVfRJ|Fa$c=I;(;f@jX>k&JCiY=h#9rp5Y{9+| zFJ(R}gKzck#0+&POPGm00-s}s7EqS6LfDav9c1HY# zeH4FT??ho`9d?HlRyMI>$^-1Gc!j+bv~!|_@+D?y30%bs`yaMqr%6?16|0V&6yIZ~ z#ak3bxrTioFR)kRg|*+}DA-Gszfk`%c741;d1>twxyULhUtoq-Qr564*k|z;b<@F* zjMzJo5i&1|hjIzKN74e*Dk^qFe2bkZX_OeID+jO(MN^#Ee{!BVQ8HnV!$Qo^vdUUk zQ8~rZp^Z~4qw<2~LCJ`n64Y)S_N=%8-LS{w2FrrI6gOBl_@m;|0s5{DmIm!mf|MSZ3uO%Z>dPFM!l~LFF!Xr4&?dvHZ$U*o{&E zSOEJx-e5mUVPIkGD=Dcw#jcZ*%4_WS_zrtiN&rh>$H{kyqc_l7`HfXj&R~yA1?4&` zja?t7Svg=i>^NcAhf)bx342U@lw<52^TE!M%F3VEcT*Ku6?;rPmFLVC=!@MaN7%2- z02+#kJtsG@k0wA#WVMw2tR{Av><7Dw9Y1FoSH4220nJy8um<*i{0P2_-Nt^L-N4=0 z8}vKmUX(q+b2zsfJCn*|cg$i|N|}rK>4W_w+u+S=%+G?@*|H2#Sc>^s5<6=)vm(j{ z7F2O!%baY^!+&8fIQcB>Wlr{_A3Hp|)&9TYGt2nJk1zL4d`7q4d`*a_+33o__)kOo z5RV5piNnT(jY&3(3RE#eU;Yq(W@u01@q!2EzGF1W*TzwxgAIwk)FCqIb`{{^@7;+x~p_}#r zCz}xWgS__1O{N_mfx35Ue8q2~uFT2)#iPB+bw9?*KF7q3mJc$gy49}kwDfjdTx-_O zbX?}*x~KklWcf_jP02-nsjkeaF7;Q~e~goThjFKp<0d%O<%NzU`)tSeBj)G!UUX7B zQxNm*=f3-ZQ#&K!!)H%UJMB32_ZDJKb!ATW&(U8|_hX#wvmxf>gUqRJRm7b1c3fQR z)#AI!*Cj5lTQcl7TQ2%b_A;ls)L&8eW1Q^UA?6}(f>T`sF&936j5FzbHs!UdPLFRr zd0hJ4@zOh6op$<<)OFg_{hQvVuIaj#WiRm$^mcV6pSfID)_lMe_eOzUQ+2f6)hu)dzmM+Webd_CdChxbWYqE9-6Qer%pl-4FC1smoK^ zxUTg#y-nQ@Vk_1CKrh!_ymhasFTy)aQ@ks2t?z#Go>wSODaE@Jh4fmr*W8SED5jL+ zor*#pDzV3mEEmdCO7X5mAtMXzG3)7LcuFbW!6@WkbM~5VhmGMWrFb`^kYRcDo0Z(g z@RTxOXh$PrWoYud6~#LiBlh4D8NZ~RVQ5~VnPqpyg+ zs+2`3gTG-^!(SgNp;W+c>GXFTACxNi?Y$uWa#9Ld4nGC)H-O4OU;Grr-*OCKF&4aO zaKPLuz5y97l@1`jIADChir#@-@P$Vs|Hfa9XqId*c$VMhanX)DxM+v;#Hk&blZ~h= z^T0Z8@uDtqVI%YQ(2Hvk7wyaZX_NfP{UR=GWd7Wxr~VQb*OGbZ*L9QIAuigHxwlJC z?GP93$b2mSJvk=Cg^kR^pcnljF0Li>?(NlN8{)!7=Dl2c@`t#%mdu;xZser8WJ6ro z$UG2w;SX_fEtzAwy8emp8VSi*mtsA5zQ)(hB!l;Q`S?Q{IwS0a{I9h0zHVx+^`Q@` zsVm#a{JsAlwrQuA>&iSe_I5UQ`hU0mf7jmbx_0`c_V3<&W;S2F&TPHhX?m<$XFjR> zt?7_t@g4WgA~-MP(i_iA$GEGezRYQ+8++AUUFTcVOOj`|-8bEFUdT?LJIxB)-fpRAp1XqAG&b> literal 189284 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 Y$FNH{19#B{>47_%9L|Qb!+zoa0dB5ZD*ylh diff --git a/homes/assets/starter_rv_interior.glb b/homes/assets/starter_rv_interior.glb new file mode 100644 index 0000000000000000000000000000000000000000..21608ea0c68307d10e8e8d75d59d17e658abe789 GIT binary patch literal 15564 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 literal 0 HcmV?d00001 diff --git a/homes/assets/tent_interior.glb.import b/homes/assets/tent_interior.glb.import new file mode 100644 index 0000000..fc01ba7 --- /dev/null +++ b/homes/assets/tent_interior.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dkfqs051shmxe" +path="res://.godot/imported/tent_interior.glb-576cc47c2c633f7ae635651598663518.scn" + +[deps] + +source_file="res://homes/assets/tent_interior.glb" +dest_files=["res://.godot/imported/tent_interior.glb-576cc47c2c633f7ae635651598663518.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/homes/home_decor_controller.gd b/homes/home_decor_controller.gd index 8f9aa5f..f67207f 100644 --- a/homes/home_decor_controller.gd +++ b/homes/home_decor_controller.gd @@ -130,6 +130,8 @@ func _unhandled_input(event: InputEvent) -> void: func _process(delta: float) -> void: + if _toolbar != null and _toolbar.visible: + _toolbar.set_interactive(_can_decorate()) if _drag_instance_id.is_empty(): return # Menus and other gameplay input handoffs must cancel an active drag before @@ -472,9 +474,20 @@ func _on_home_changed() -> void: func _refresh_toolbar() -> void: if _toolbar == null: return - _toolbar.set_active(_can_decorate()) + var inside_home: bool = _is_inside_home_space() + _toolbar.set_active(inside_home) + _toolbar.set_interactive(_can_decorate()) if not _toolbar.visible: _clear_selection() + elif not _can_decorate(): + _toolbar.report_status("decor tools pause while another menu is open") + + +func _is_inside_home_space() -> bool: + return ( + _network_home != null + and String(_network_home.get_local_space()).begins_with("rv:") + ) func _can_decorate() -> bool: diff --git a/homes/home_world_service.gd b/homes/home_world_service.gd index fd02d93..4ec0645 100644 --- a/homes/home_world_service.gd +++ b/homes/home_world_service.gd @@ -9,23 +9,42 @@ const DecorCatalogType = preload("res://homes/decor_catalog.gd") const STARTER_MOTORCOACH_SCENE: PackedScene = preload( "res://homes/assets/starter_motorcoach.glb" ) +const TENT_INTERIOR_SCENE: PackedScene = preload( + "res://homes/assets/tent_interior.glb" +) +const STARTER_RV_INTERIOR_SCENE: PackedScene = preload( + "res://homes/assets/starter_rv_interior.glb" +) +const HOME_PROMPT_FONT: Font = preload("res://ui/fonts/Tuffy_Bold.otf") -const EXTERIOR_BODY_SIZE := Vector3(5.6, 2.5, 2.35) -const EXTERIOR_DOOR_LOCAL := Vector3(-0.2, 0.85, 1.48) -const EXTERIOR_SPAWN_LOCAL := Vector3(-0.2, 0.25, 2.45) +const RV_EXTERIOR_BODY_SIZE := Vector3(11.2, 5.0, 4.7) +const RV_EXTERIOR_BODY_CENTER_Y: float = 2.7 +const RV_EXTERIOR_DOOR_LOCAL := Vector3(-0.4, 1.7, 2.96) +const RV_EXTERIOR_SPAWN_LOCAL := Vector3(-0.4, 0.25, 3.95) +const TENT_EXTERIOR_BODY_SIZE := Vector3(4.6, 3.0, 4.6) +const TENT_EXTERIOR_BODY_CENTER_Y: float = 1.5 +const TENT_EXTERIOR_DOOR_LOCAL := Vector3(0.0, 1.0, 2.3) +const TENT_EXTERIOR_SPAWN_LOCAL := Vector3(0.0, 0.25, 3.3) +const RV_EXTERIOR_PROMPT_LOCAL := Vector3(-0.4, 3.72, 3.02) +const TENT_EXTERIOR_PROMPT_LOCAL := Vector3(0.0, 2.48, 2.36) +const HOME_PROMPT_SIZE := Vector2(0.95, 0.28) +const HOME_PROMPT_CORNER_RADIUS: float = 0.08 +const HOME_PROMPT_TEXT_PIXEL_SIZE: float = 0.0045 +const HOME_PROMPT_TEXT_COLOR := Color("c3dfe6") +const HOME_PROMPT_BACKGROUND_COLOR := Color("0a2d3a") const EXTERIOR_INTERACTION_DISTANCE: float = 2.7 const INTERIOR_EXIT_DISTANCE: float = 2.1 const INTERIOR_ORIGIN := Vector3(1000.0, 300.0, 1000.0) const INTERIOR_SPACING: float = 14.0 const INTERIOR_MAX_SPAWN_SLOTS: int = 64 -const INTERIOR_FLOOR_SIZE := Vector3(8.0, 0.18, 4.5) -const INTERIOR_WALL_HEIGHT: float = 2.7 +const TENT_INTERIOR_SIZE := Vector2(4.0, 4.0) +const STARTER_RV_INTERIOR_SIZE := Vector2(4.0, 6.0) const MIN_EXTERIOR_TRIANGLE_AREA: float = 1.0 -const MIN_EXTERIOR_SEPARATION: float = 9.0 -const EXTERIOR_FOOTPRINT_HALF_EXTENTS := Vector2(3.85, 2.55) +const MIN_EXTERIOR_SEPARATION: float = 14.6 +const EXTERIOR_FOOTPRINT_HALF_EXTENTS := Vector2(6.65, 3.73) const EXTERIOR_SURFACE_INDEX_CELL_SIZE: float = 5.0 const EXTERIOR_MAX_SURFACE_HEIGHT_DELTA: float = 0.24 -const EXTERIOR_CLEARANCE_HEIGHT: float = 2.7 +const EXTERIOR_CLEARANCE_HEIGHT: float = 5.5 const WORLD_GEOMETRY_COLLISION_LAYER: int = 1 const DECOR_SELECTION_COLLISION_LAYER: int = 1 << 8 # Includes the player's 0.45 m capsule radius plus enough movement margin for @@ -113,7 +132,9 @@ func apply_manifest(data: Dictionary) -> bool: var home_data: Dictionary = PlayerHomeStateType.sanitize_save_data( data["home"] ) - var exterior := _build_exterior(fingerprint, exterior_transform) + var exterior := _build_exterior( + fingerprint, exterior_transform, home_data + ) var interior := _build_interior(fingerprint, interior_index, home_data) var presentation: Dictionary = { "owner_peer_id": int(data["owner_peer_id"]), @@ -191,19 +212,27 @@ func choose_exterior_transform( ) if dry_result != Transform3D.IDENTITY: push_warning( - "RV exterior used a dry fallback with obstructed clearance." + "Home exterior used a dry fallback with obstructed clearance." ) return dry_result - push_error("No dry, level RV exterior footprint was available.") - var fallback: Transform3D = spawn_transform - var column: int = posmod(owner_peer_id - 1, 4) - var row: int = maxi(floori(float(owner_peer_id - 1) / 4.0), 0) - fallback.origin += Vector3( - -12.0 + float(column) * 8.0, - 0.0, - 8.0 + float(row) * 7.0, - ) - return fallback + var emergency_result: Transform3D = _find_exterior_transform( + owner_peer_id, + triangles, + surface_index, + spawn_transform, + [], + false, + false, + ) + if emergency_result != Transform3D.IDENTITY: + push_warning( + "Home exterior used an accessible emergency placement." + ) + return emergency_result + push_error("No dry, level home exterior footprint was available.") + # The authored spawn is the only universally reachable point. Never strand + # a home on an unchecked elevation when malformed terrain offers no site. + return spawn_transform func _find_exterior_transform( @@ -229,7 +258,7 @@ func _find_exterior_transform( ) / 3.0 if ( require_spawn_clearance - and position.distance_to(spawn_transform.origin) < 6.0 + and position.distance_to(spawn_transform.origin) < 9.0 ): continue if _too_close_to_reserved(position, reserved_transforms): @@ -240,6 +269,13 @@ func _find_exterior_transform( ) if not grounded_position.is_finite(): continue + if ( + _world != null + and not _world.is_home_exterior_position_accessible( + grounded_position + ) + ): + continue if ( require_obstacle_clearance and not _exterior_volume_is_clear(grounded_position, yaw) @@ -444,16 +480,48 @@ func get_exterior_transform(owner_fingerprint: String) -> Transform3D: func get_exterior_prompt_position(owner_fingerprint: String) -> Vector3: - return get_exterior_transform(owner_fingerprint) * EXTERIOR_DOOR_LOCAL + return get_exterior_transform(owner_fingerprint) * ( + _exterior_prompt_local(owner_fingerprint) + ) + + +func set_exterior_prompt_visible( + owner_fingerprint: String, + requested_visible: bool, + action_text: String = "enter home", +) -> void: + for fingerprint: String in _presentations_by_fingerprint: + var presentation: Dictionary = _presentations_by_fingerprint[fingerprint] + var exterior: Node3D = presentation.get("exterior") + if not is_instance_valid(exterior): + continue + var prompt := exterior.get_node_or_null("DoorPrompt") as Node3D + if prompt == null: + continue + prompt.visible = ( + requested_visible + and fingerprint == owner_fingerprint + and not _dedicated_runtime + ) + if prompt.visible: + var label := prompt.get_node_or_null("Message") as Label3D + if label != null: + label.text = action_text func get_exterior_spawn_transform(owner_fingerprint: String) -> Transform3D: var exterior_transform: Transform3D = get_exterior_transform( owner_fingerprint ) + # Exterior local +Z leads away from the doorway. Player visuals face local + # -Z, so turn the authoritative spawn basis around to start the day facing + # outward instead of looking back into the home. + var outward_spawn_basis: Basis = ( + exterior_transform.basis * Basis(Vector3.UP, PI) + ) return Transform3D( - exterior_transform.basis, - exterior_transform * EXTERIOR_SPAWN_LOCAL, + outward_spawn_basis, + exterior_transform * _exterior_spawn_local(owner_fingerprint), ) @@ -461,17 +529,26 @@ func get_interior_spawn_transform( owner_fingerprint: String, visitor_offset: int = 0, ) -> Transform3D: - var anchor: Vector3 = get_interior_anchor(owner_fingerprint) # `visitor_offset` is allocated by the host as a compact room-local slot. # Keep it bounded as a last line of defense if a future caller accidentally # supplies an engine peer ID instead of a slot. var visitor_slot: int = posmod(visitor_offset, INTERIOR_MAX_SPAWN_SLOTS) - # Build the origin as a value rather than mutating Transform3D.origin. - var spawn_origin: Vector3 = anchor + Vector3( - -1.0 + float(posmod(visitor_slot, 4)) * 0.65, - 0.25, - 0.4 + float(floori(float(visitor_slot) / 4.0)) * 0.55, + var exit_direction: Vector3 = get_interior_exit_direction(owner_fingerprint) + var lane_offset: float = ( + float(posmod(visitor_slot, 4)) - 1.5 + ) * 0.28 + var row_offset: float = ( + float(floori(float(visitor_slot) / 4.0)) * 0.28 ) + # Spawn just through the authored doorway. Local presentation then walks the + # avatar farther into the room before returning movement control. + var spawn_origin: Vector3 = ( + get_interior_exit_position(owner_fingerprint) + + exit_direction * 0.42 + - exit_direction * row_offset + + Vector3(0.0, 0.0, lane_offset) + ) + spawn_origin.y = get_interior_anchor(owner_fingerprint).y return Transform3D(Basis.IDENTITY, spawn_origin) @@ -487,7 +564,9 @@ func is_avatar_near_exterior(avatar: Player, owner_fingerprint: String) -> bool: if avatar == null or not _presentations_by_fingerprint.has(owner_fingerprint): return false var transform: Transform3D = get_exterior_transform(owner_fingerprint) - var door_position: Vector3 = transform * EXTERIOR_DOOR_LOCAL + var door_position: Vector3 = ( + transform * _exterior_door_local(owner_fingerprint) + ) return avatar.global_position.distance_to(door_position) <= ( EXTERIOR_INTERACTION_DISTANCE ) @@ -504,11 +583,46 @@ func is_avatar_near_interior_exit( ) <= INTERIOR_EXIT_DISTANCE +func has_avatar_crossed_interior_exit_threshold( + avatar: Player, + owner_fingerprint: String, +) -> bool: + if avatar == null: + return false + var local_position: Vector3 = interior_global_to_local( + owner_fingerprint, + avatar.global_position, + ) + var threshold_position: Vector3 = interior_global_to_local( + owner_fingerprint, + get_interior_exit_position(owner_fingerprint), + ) + var exit_direction: Vector3 = get_interior_exit_direction( + owner_fingerprint + ) + return ( + (local_position - threshold_position).dot(exit_direction) >= 0.0 + and absf(local_position.z - threshold_position.z) <= 0.85 + and local_position.y >= -0.25 + and local_position.y <= 2.25 + ) + + +func get_interior_exit_direction(owner_fingerprint: String) -> Vector3: + return ( + Vector3.LEFT + if _home_tier(owner_fingerprint) + >= PlayerHomeStateType.STARTER_RV_TIER + else Vector3.RIGHT + ) + + func get_interior_exit_position(owner_fingerprint: String) -> Vector3: - return get_interior_anchor(owner_fingerprint) + Vector3( - -INTERIOR_FLOOR_SIZE.x * 0.5 + 0.6, - 0.35, - 0.0, + var tier: int = _home_tier(owner_fingerprint) + return get_interior_anchor(owner_fingerprint) + ( + Vector3(-STARTER_RV_INTERIOR_SIZE.x * 0.5 + 0.6, 0.35, 0.0) + if tier >= PlayerHomeStateType.STARTER_RV_TIER + else Vector3(TENT_INTERIOR_SIZE.x * 0.5 - 0.55, 0.35, 0.0) ) @@ -705,7 +819,7 @@ func find_nearby_exterior_owner(avatar: Player) -> String: for fingerprint: String in _presentations_by_fingerprint: var transform: Transform3D = get_exterior_transform(fingerprint) var distance: float = avatar.global_position.distance_to( - transform * EXTERIOR_DOOR_LOCAL + transform * _exterior_door_local(fingerprint) ) if distance <= closest_distance: closest = fingerprint @@ -713,6 +827,41 @@ func find_nearby_exterior_owner(avatar: Player) -> String: return closest +func _home_tier(owner_fingerprint: String) -> int: + var presentation: Dictionary = _presentations_by_fingerprint.get( + owner_fingerprint, {} + ) + var home_data: Dictionary = presentation.get("home", {}) + return int(home_data.get("tier", PlayerHomeStateType.STARTER_TIER)) + + +func _exterior_door_local(owner_fingerprint: String) -> Vector3: + return ( + RV_EXTERIOR_DOOR_LOCAL + if _home_tier(owner_fingerprint) + >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_EXTERIOR_DOOR_LOCAL + ) + + +func _exterior_spawn_local(owner_fingerprint: String) -> Vector3: + return ( + RV_EXTERIOR_SPAWN_LOCAL + if _home_tier(owner_fingerprint) + >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_EXTERIOR_SPAWN_LOCAL + ) + + +func _exterior_prompt_local(owner_fingerprint: String) -> Vector3: + return ( + RV_EXTERIOR_PROMPT_LOCAL + if _home_tier(owner_fingerprint) + >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_EXTERIOR_PROMPT_LOCAL + ) + + func set_local_space(space_id: StringName) -> void: _local_space = space_id _refresh_local_visibility() @@ -822,24 +971,44 @@ func _ensure_roots() -> void: func _build_exterior( fingerprint: String, world_transform: Transform3D, + home_data: Dictionary, ) -> Node3D: var root := Node3D.new() - root.name = "RV_%s" % fingerprint.left(8) + root.name = "Home_%s" % fingerprint.left(8) _exteriors_root.add_child(root) root.global_transform = world_transform + var tier: int = int(home_data.get( + "tier", PlayerHomeStateType.STARTER_TIER + )) + if tier >= PlayerHomeStateType.STARTER_RV_TIER: + if not _dedicated_runtime: + var motorcoach: Node3D = ( + STARTER_MOTORCOACH_SCENE.instantiate() as Node3D + ) + if motorcoach != null: + motorcoach.name = "StarterMotorcoach" + root.add_child(motorcoach) + else: + push_error( + "The starter motorcoach exterior could not be instantiated." + ) + _add_box_collision( + root, + "Body", + RV_EXTERIOR_BODY_SIZE, + Vector3(0.0, RV_EXTERIOR_BODY_CENTER_Y, 0.0), + ) + else: + if not _dedicated_runtime: + _add_tent_exterior(root) + _add_box_collision( + root, + "Body", + TENT_EXTERIOR_BODY_SIZE, + Vector3(0.0, TENT_EXTERIOR_BODY_CENTER_Y, 0.0), + ) if not _dedicated_runtime: - var motorcoach: Node3D = STARTER_MOTORCOACH_SCENE.instantiate() as Node3D - if motorcoach != null: - motorcoach.name = "StarterMotorcoach" - root.add_child(motorcoach) - else: - push_error("The starter motorcoach exterior could not be instantiated.") - _add_box_collision( - root, - "Body", - EXTERIOR_BODY_SIZE, - Vector3(0.0, 1.35, 0.0), - ) + _add_exterior_prompt(root, tier) root.visible = not _dedicated_runtime return root @@ -850,59 +1019,26 @@ func _build_interior( home_data: Dictionary, ) -> Node3D: var root := Node3D.new() - root.name = "RVInterior_%s" % fingerprint.left(8) + root.name = "HomeInterior_%s" % fingerprint.left(8) root.position = INTERIOR_ORIGIN + Vector3( float(interior_index) * INTERIOR_SPACING, 0.0, 0.0 ) - var half_width: float = INTERIOR_FLOOR_SIZE.x * 0.5 - var half_depth: float = INTERIOR_FLOOR_SIZE.z * 0.5 - var wall_center_y: float = INTERIOR_WALL_HEIGHT * 0.5 _interiors_root.add_child(root) - _add_box( - root, "Floor", INTERIOR_FLOOR_SIZE, Vector3.ZERO, - Color("a6754e"), true, - ) - _add_wall( - root, "WallNorth", - Vector3(INTERIOR_FLOOR_SIZE.x, INTERIOR_WALL_HEIGHT, 0.18), - Vector3(0.0, wall_center_y, -half_depth), - ) - _add_wall( - root, "WallSouth", - Vector3(INTERIOR_FLOOR_SIZE.x, INTERIOR_WALL_HEIGHT, 0.18), - Vector3(0.0, wall_center_y, half_depth), - ) - _add_wall( - root, "WallWest", - Vector3(0.18, INTERIOR_WALL_HEIGHT, INTERIOR_FLOOR_SIZE.z), - Vector3(-half_width, wall_center_y, 0.0), - ) - _add_wall( - root, "WallEast", - Vector3(0.18, INTERIOR_WALL_HEIGHT, INTERIOR_FLOOR_SIZE.z), - Vector3(half_width, wall_center_y, 0.0), - ) - for x_position: float in [-1.75, 1.75]: - _add_box( - root, "WallNorthWindow%s" % ("Left" if x_position < 0.0 else "Right"), - Vector3(1.65, 0.95, 0.04), - Vector3(x_position, 1.55, -half_depth + 0.11), - Color("153640"), false, - ) - _add_box( - root, "WallSouthWindow%s" % ("Left" if x_position < 0.0 else "Right"), - Vector3(1.65, 0.95, 0.04), - Vector3(x_position, 1.55, half_depth - 0.11), - Color("153640"), false, - ) - _add_box( - root, "WallEastWindow", Vector3(0.04, 0.95, 1.55), - Vector3(half_width - 0.11, 1.55, 0.0), Color("153640"), false, - ) - _add_box( - root, "WallWestDoor", Vector3(0.04, 1.9, 1.25), - Vector3(-half_width + 0.11, 1.0, 0.0), Color("2897a8"), false, + var tier: int = int(home_data.get( + "tier", PlayerHomeStateType.STARTER_TIER + )) + var scene: PackedScene = ( + STARTER_RV_INTERIOR_SCENE + if tier >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_INTERIOR_SCENE ) + var shell: Node3D = scene.instantiate() as Node3D + if shell == null: + push_error("The home interior shell could not be instantiated.") + else: + shell.name = "InteriorShell" + root.add_child(shell) + _prepare_imported_interior(shell) var decor := Node3D.new() decor.name = "Decor" root.add_child(decor) @@ -913,6 +1049,153 @@ func _build_interior( return root +func _add_tent_exterior(parent: Node3D) -> void: + var tent := MeshInstance3D.new() + tent.name = "StarterTent" + var mesh := CylinderMesh.new() + mesh.top_radius = 0.0 + mesh.bottom_radius = 3.05 + mesh.height = 3.0 + mesh.radial_segments = 4 + mesh.rings = 1 + mesh.cap_top = false + mesh.material = _material(Color("9a7049")) + tent.mesh = mesh + tent.position.y = 1.5 + tent.rotation.y = PI * 0.25 + parent.add_child(tent) + _add_box( + parent, + "TentDoor", + Vector3(1.25, 1.85, 0.04), + Vector3(0.0, 0.95, 2.18), + Color("173b32"), + false, + ) + + +func _add_exterior_prompt(parent: Node3D, tier: int) -> void: + var prompt := Node3D.new() + prompt.name = "DoorPrompt" + prompt.position = ( + RV_EXTERIOR_PROMPT_LOCAL + if tier >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_EXTERIOR_PROMPT_LOCAL + ) + prompt.visible = false + parent.add_child(prompt) + + var background := MeshInstance3D.new() + background.name = "Background" + background.mesh = _rounded_rectangle_mesh( + HOME_PROMPT_SIZE, + HOME_PROMPT_CORNER_RADIUS, + ) + background.material_override = _prompt_material( + HOME_PROMPT_BACKGROUND_COLOR + ) + prompt.add_child(background) + + var label := Label3D.new() + label.name = "Message" + label.text = "enter home" + label.position.z = 0.012 + label.font = HOME_PROMPT_FONT + label.font_size = 28 + label.pixel_size = HOME_PROMPT_TEXT_PIXEL_SIZE + label.modulate = HOME_PROMPT_TEXT_COLOR + label.outline_size = 0 + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + label.width = HOME_PROMPT_SIZE.x / HOME_PROMPT_TEXT_PIXEL_SIZE + label.double_sided = true + prompt.add_child(label) + + +func _rounded_rectangle_mesh(size: Vector2, radius: float) -> ArrayMesh: + var half_size: Vector2 = size * 0.5 + var clamped_radius: float = minf( + radius, + minf(half_size.x, half_size.y), + ) + var corners: Array[Vector2] = [ + Vector2(half_size.x - clamped_radius, half_size.y - clamped_radius), + Vector2(-half_size.x + clamped_radius, half_size.y - clamped_radius), + Vector2(-half_size.x + clamped_radius, -half_size.y + clamped_radius), + Vector2(half_size.x - clamped_radius, -half_size.y + clamped_radius), + ] + var start_angles: Array[float] = [0.0, PI * 0.5, PI, PI * 1.5] + var perimeter: Array[Vector2] = [] + const CORNER_SEGMENTS: int = 4 + for corner_index: int in corners.size(): + for segment_index: int in range(CORNER_SEGMENTS + 1): + var angle: float = start_angles[corner_index] + ( + PI * 0.5 * float(segment_index) / float(CORNER_SEGMENTS) + ) + perimeter.append( + corners[corner_index] + + Vector2(cos(angle), sin(angle)) * clamped_radius + ) + var surface := SurfaceTool.new() + surface.begin(Mesh.PRIMITIVE_TRIANGLES) + for index: int in perimeter.size(): + var first: Vector2 = perimeter[index] + var second: Vector2 = perimeter[(index + 1) % perimeter.size()] + for point: Vector2 in [Vector2.ZERO, first, second]: + surface.set_normal(Vector3.FORWARD) + surface.add_vertex(Vector3(point.x, point.y, 0.0)) + return surface.commit() + + +func _prompt_material(color: Color) -> StandardMaterial3D: + var material := StandardMaterial3D.new() + material.albedo_color = color + material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + material.roughness = 1.0 + material.metallic = 0.0 + material.cull_mode = BaseMaterial3D.CULL_DISABLED + return material + + +func _prepare_imported_interior(shell: Node3D) -> void: + for value: Node in shell.find_children("*", "MeshInstance3D", true, false): + var mesh_instance := value as MeshInstance3D + if mesh_instance == null or mesh_instance.mesh == null: + continue + for surface_index: int in mesh_instance.mesh.get_surface_count(): + var source_material: Material = mesh_instance.get_active_material( + surface_index + ) + var material := source_material as StandardMaterial3D + if material == null: + continue + var flat_material := material.duplicate() as StandardMaterial3D + flat_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + flat_material.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST + flat_material.roughness = 1.0 + flat_material.metallic = 0.0 + mesh_instance.set_surface_override_material( + surface_index, flat_material + ) + _add_imported_mesh_collision(mesh_instance) + + +func _add_imported_mesh_collision(mesh_instance: MeshInstance3D) -> void: + var parent: Node = mesh_instance.get_parent() + if parent == null or mesh_instance.mesh == null: + return + var shape: ConcavePolygonShape3D = mesh_instance.mesh.create_trimesh_shape() + if shape == null: + return + var body := StaticBody3D.new() + body.name = "%sCollision" % mesh_instance.name + body.transform = mesh_instance.transform + var collision := CollisionShape3D.new() + collision.shape = shape + body.add_child(collision) + parent.add_child(body) + + func _rebuild_decor( parent: Node3D, home_data: Dictionary, @@ -1115,9 +1398,9 @@ func _refresh_local_visibility() -> void: for wall_name: String in [ "WallNorth", "WallSouth", "WallWest", "WallEast", ]: - var body: StaticBody3D = active_interior.get_node_or_null( - "%sCollision" % wall_name - ) + var body := active_interior.find_child( + "%sCollision" % wall_name, true, false + ) as StaticBody3D if body != null: excluded_wall_rids.append(body.get_rid()) local_player.set_rv_interior_camera_mode( @@ -1145,12 +1428,20 @@ func _refresh_nearest_wall() -> void: ).normalized() var horizontal_view_weight: float = absf(local_view_direction.x) var depth_view_weight: float = absf(local_view_direction.z) + var tier: int = int((presentation.get("home", {}) as Dictionary).get( + "tier", PlayerHomeStateType.STARTER_TIER + )) + var interior_size: Vector2 = ( + STARTER_RV_INTERIOR_SIZE + if tier >= PlayerHomeStateType.STARTER_RV_TIER + else TENT_INTERIOR_SIZE + ) var hidden_walls: Dictionary[String, bool] = {} var outside_horizontal_wall: bool = ( - absf(local_camera.x) >= INTERIOR_FLOOR_SIZE.x * 0.5 - 0.05 + absf(local_camera.x) >= interior_size.x * 0.5 - 0.05 ) var outside_depth_wall: bool = ( - absf(local_camera.z) >= INTERIOR_FLOOR_SIZE.z * 0.5 - 0.05 + absf(local_camera.z) >= interior_size.y * 0.5 - 0.05 ) # At a diagonal, both near walls occupy the view. Use the camera's viewing # direction to hide both instead of choosing only the dominant position @@ -1181,10 +1472,14 @@ func _refresh_nearest_wall() -> void: for wall_name: String in [ "WallNorth", "WallSouth", "WallWest", "WallEast", ]: - var wall: MeshInstance3D = interior.get_node_or_null(wall_name) + var wall := interior.find_child( + wall_name, true, false + ) as MeshInstance3D if wall != null: wall.visible = not hidden_walls.has(wall_name) - for child: Node in interior.get_children(): + for child: Node in interior.find_children( + "%s*" % wall_name, "GeometryInstance3D", true, false + ): if ( child is GeometryInstance3D and String(child.name).begins_with(wall_name) diff --git a/homes/player_home_state.gd b/homes/player_home_state.gd index decd34a..a89d6a3 100644 --- a/homes/player_home_state.gd +++ b/homes/player_home_state.gd @@ -7,8 +7,12 @@ const DecorCatalogType = preload("res://homes/decor_catalog.gd") const HOME_SCHEMA_VERSION: int = 1 const STARTER_TIER: int = 0 -const STARTER_EXTERIOR_ID: StringName = &"starter_motorcoach" -const MAX_TIER: int = 8 +const STARTER_EXTERIOR_ID: StringName = &"starter_tent" +const STARTER_RV_TIER: int = 1 +const STARTER_RV_EXTERIOR_ID: StringName = &"starter_motorcoach" +const MAX_TIER: int = STARTER_RV_TIER +const HOME_UPGRADE_COSTS: Array[int] = [50] +const STORAGE_CAPACITIES: Array[int] = [9, 18] const MAX_PLACEMENTS: int = 128 const MAX_INSTANCE_ID_LENGTH: int = 96 const MAX_REVISION: int = 2147483647 @@ -16,11 +20,8 @@ const GRID_SIZE: float = 0.5 const FREE_PLACEMENT_SEARCH_STEP: float = 0.1 const FREE_PLACEMENT_SEARCH_ANGLES: int = 24 const NEAREST_PLACEMENT_SEARCH_DISTANCE: float = 2.0 -# The starter RV is intentionally cramped. Later RV tiers can replace these -# bounds with larger layouts when tiered interiors are introduced. -# The starter interior is 8.0 m by 4.5 m with 0.18 m walls. These bounds -# follow the walls' inner faces, with a small visual gap to avoid z-fighting. -const INTERIOR_HALF_EXTENTS := Vector2(3.91, 2.16) +const TENT_INTERIOR_HALF_EXTENTS := Vector2(1.91, 1.91) +const STARTER_RV_INTERIOR_HALF_EXTENTS := Vector2(1.91, 2.91) const PLACEMENT_EDGE_PADDING: float = 0.02 enum Privacy { @@ -50,6 +51,51 @@ func get_exterior_id() -> StringName: return _exterior_id +func get_storage_capacity() -> int: + return storage_capacity_for_tier(_tier) + + +func get_next_upgrade_cost() -> int: + if _tier >= MAX_TIER: + return -1 + return HOME_UPGRADE_COSTS[_tier] + + +func get_next_storage_capacity() -> int: + if _tier >= MAX_TIER: + return -1 + return storage_capacity_for_tier(_tier + 1) + + +func upgrade_to_next_tier() -> bool: + if _tier >= MAX_TIER: + return false + _tier += 1 + _exterior_id = exterior_id_for_tier(_tier) + _touch() + return true + + +static func exterior_id_for_tier(tier: int) -> StringName: + return ( + STARTER_RV_EXTERIOR_ID + if tier >= STARTER_RV_TIER + else STARTER_EXTERIOR_ID + ) + + +static func storage_capacity_for_tier(tier: int) -> int: + return STORAGE_CAPACITIES[clampi(tier, STARTER_TIER, MAX_TIER)] + + +static func interior_half_extents_for_tier(tier: int) -> Vector2: + return ( + STARTER_RV_INTERIOR_HALF_EXTENTS + if tier >= STARTER_RV_TIER + else TENT_INTERIOR_HALF_EXTENTS + ) + + func get_privacy() -> Privacy: return _privacy @@ -248,7 +294,7 @@ func get_nearest_valid_placement_transform( candidate_validator: Callable = Callable(), ) -> Dictionary: var normalized: Dictionary = normalized_placement_transform( - decor_id, position, yaw_radians, mode + decor_id, position, yaw_radians, mode, _tier ) if normalized.is_empty(): return {} @@ -322,7 +368,7 @@ func restore_from_save_data(data: Dictionary) -> bool: if sanitized.is_empty(): return false _tier = int(sanitized["tier"]) - _exterior_id = StringName(str(sanitized["exterior_id"])) + _exterior_id = exterior_id_for_tier(_tier) _privacy = int(sanitized["privacy"]) _owned_decor.clear() for key: Variant in (sanitized["owned_decor"] as Dictionary): @@ -384,6 +430,7 @@ static func sanitize_save_data(data: Dictionary) -> Dictionary: or next_sequence > MAX_REVISION ): return {} + exterior_id = String(exterior_id_for_tier(tier)) var sanitized_owned: Dictionary = {} var owned: Dictionary = data["owned_decor"] for key: Variant in owned: @@ -408,7 +455,7 @@ static func sanitize_save_data(data: Dictionary) -> Dictionary: for value: Variant in values: if typeof(value) != TYPE_DICTIONARY: return {} - var sanitized: Dictionary = sanitize_placement(value) + var sanitized: Dictionary = sanitize_placement(value, tier) if sanitized.is_empty(): return {} var instance_id: String = str(sanitized["instance_id"]) @@ -440,7 +487,10 @@ static func sanitize_save_data(data: Dictionary) -> Dictionary: } -static func sanitize_placement(value: Dictionary) -> Dictionary: +static func sanitize_placement( + value: Dictionary, + home_tier: int = STARTER_TIER, +) -> Dictionary: for key: String in [ "instance_id", "decor_id", "mode", "position", "yaw", ]: @@ -483,6 +533,7 @@ static func sanitize_placement(value: Dictionary) -> Dictionary: position, yaw, mode as PlacementMode, + home_tier, ) if normalized.is_empty(): return {} @@ -509,6 +560,7 @@ static func normalized_placement_transform( position: Vector3, yaw_radians: float, mode: PlacementMode, + home_tier: int = STARTER_TIER, ) -> Dictionary: if ( not DecorCatalogType.has_product(decor_id) @@ -530,11 +582,12 @@ static func normalized_placement_transform( (footprint.x * cosine + footprint.y * sine) * 0.5, (footprint.x * sine + footprint.y * cosine) * 0.5, ) + var interior_half_extents := interior_half_extents_for_tier(home_tier) var maximum_x: float = ( - INTERIOR_HALF_EXTENTS.x - half_size.x - PLACEMENT_EDGE_PADDING + interior_half_extents.x - half_size.x - PLACEMENT_EDGE_PADDING ) var maximum_z: float = ( - INTERIOR_HALF_EXTENTS.y - half_size.y - PLACEMENT_EDGE_PADDING + interior_half_extents.y - half_size.y - PLACEMENT_EDGE_PADDING ) if maximum_x < 0.0 or maximum_z < 0.0: return {} @@ -580,6 +633,7 @@ func _find_nearest_grid_transform( ), yaw, PlacementMode.GRID, + _tier, ) if candidate.is_empty() or not _mark_candidate_unseen( candidate, seen @@ -630,6 +684,7 @@ func _find_nearest_free_transform( ), yaw, PlacementMode.FREE, + _tier, ) if candidate.is_empty() or not _mark_candidate_unseen( candidate, seen diff --git a/main/main.gd b/main/main.gd index 00d2b40..324c268 100644 --- a/main/main.gd +++ b/main/main.gd @@ -40,6 +40,9 @@ const FishingShopInteractionType = preload( const DecorShopInteractionType = preload( "res://world/decor_shop_interaction.gd" ) +const RVUpgradeInteractionType = preload( + "res://world/rv_upgrade_interaction.gd" +) const PlayerStorageInteractionType = preload( "res://world/player_storage_interaction.gd" ) @@ -148,6 +151,13 @@ const PLAYER_MENU_PATTERN_SCROLL_VELOCITY := Vector2(-7.0, -5.0) const SHOP_PATTERN_SCALE: float = 1.75 const DEDICATED_IDLE_PHYSICS_TICKS_PER_SECOND: int = 10 const DEDICATED_ACTIVE_PHYSICS_TICKS_PER_SECOND: int = 30 +const HOME_ENTRY_INPUT_OWNER: StringName = &"home_entry_transition" +const HOME_EXIT_INPUT_OWNER: StringName = &"home_exit_transition" +const HOME_EXIT_FADE_GENERATION: int = -104729 +const HOME_ENTRY_WALK_DISTANCE: float = 1.05 +const HOME_ENTRY_WALK_DURATION: float = 0.55 +const HOME_EXIT_WALK_DISTANCE: float = 1.25 +const HOME_EXIT_WALK_DURATION: float = 0.62 @export var fish_catalog: FishPoolType @export var pelican_buyer_profile: FishBuyerProfileType @@ -260,6 +270,7 @@ var _gameplay_started: bool = false var _save_slots := PlayerSaveSlotCatalogType.new() var _shop_interaction: FishingShopInteractionType var _decor_shop_interaction: DecorShopInteractionType +var _rv_upgrade_shop_interaction: RVUpgradeInteractionType var _storage_interaction: PlayerStorageInteractionType var _title_music_tween: Tween var _title_music_transition_generation: int = 0 @@ -290,6 +301,12 @@ var _pending_existing_root_path := "" var _local_recovery_attempt_id: String = "" var _dedicated_runtime: bool = false var _dedicated_metrics_accumulator: float = 0.0 +var _home_exit_transition_active: bool = false +var _home_exit_waiting_for_network: bool = false +var _home_exit_start_position: Vector3 = Vector3.ZERO +var _home_exit_walk_tween: Tween +var _home_entry_transition_active: bool = false +var _home_entry_walk_tween: Tween @onready var _shoreline_ambience: ShorelineAmbience = %ShorelineAmbience var _rain_ambience: RainAmbienceType @@ -743,6 +760,7 @@ func _initialize_application(dedicated: bool) -> void: _player.wallet, _asset_reservations ) + _player.cooler_capacity.bind_home_state(_home_state) _player.bag.setup(item_catalog) _player.inventory_layout.setup( _player.bag, @@ -760,19 +778,24 @@ func _initialize_application(dedicated: bool) -> void: ) _shop_interaction = _test_world.get_fishing_shop() _decor_shop_interaction = _test_world.get_decor_shop() + _rv_upgrade_shop_interaction = _test_world.get_rv_upgrade_shop() _storage_interaction = _test_world.get_player_storage() if not dedicated: + if not _home_state.changed.is_connected(_on_home_state_changed): + _home_state.changed.connect(_on_home_state_changed) _shop_interaction.setup_local_player(_player) _shop_interaction.local_player_range_changed.connect( _on_shop_range_changed ) - _game_ui.set_shop_npc_player_in_range( - _shop_interaction.is_local_player_in_range() - ) + _refresh_shop_npc_speech_state() _decor_shop_interaction.setup_local_player(_player) _decor_shop_interaction.local_player_range_changed.connect( _on_decor_shop_range_changed ) + _rv_upgrade_shop_interaction.setup_local_player(_player) + _rv_upgrade_shop_interaction.local_player_range_changed.connect( + _on_rv_upgrade_shop_range_changed + ) _storage_interaction.setup_local_player(_player) _storage_interaction.local_player_range_changed.connect( _on_storage_range_changed @@ -947,6 +970,7 @@ func _initialize_application(dedicated: bool) -> void: _home_state, _network_home, _decor_shop_interaction, + _rv_upgrade_shop_interaction, ) _fishing_spot.setup( _player, @@ -987,6 +1011,7 @@ func _initialize_application(dedicated: bool) -> void: _shop_interaction, _storage_interaction, _decor_shop_interaction, + _rv_upgrade_shop_interaction, _player.item_effects, _player.cooler_capacity, _network_session, @@ -1024,6 +1049,12 @@ func _initialize_application(dedicated: bool) -> void: _home_decor_controller.begin_decorating ) _network_home.local_space_changed.connect(_on_local_home_space_changed) + _network_home.local_transition_finished.connect( + _on_local_home_transition_finished + ) + _game_ui.get_screen_fade().transition_completed.connect( + _on_home_exit_fade_transition_completed + ) _game_ui.rv_storage_requested.connect(_on_rv_storage_requested) _game_ui.setup_data_and_identity( _data_root, @@ -1539,6 +1570,9 @@ func _input(event: InputEvent) -> void: if _game_ui.get_decor_shop().consume_escape(): get_viewport().set_input_as_handled() return + if _game_ui.get_rv_upgrade_shop().consume_escape(): + get_viewport().set_input_as_handled() + return if fishing_shop.consume_escape(): get_viewport().set_input_as_handled() return @@ -1653,17 +1687,12 @@ func _unhandled_input(event: InputEvent) -> void: return var home_owner: String = _network_home.get_local_home_owner_fingerprint() if not home_owner.is_empty(): - if _home_world.is_avatar_near_interior_exit(_player, home_owner): - if _network_home.request_exit(): - _game_ui.set_storage_prompt_visible(false) - get_viewport().set_input_as_handled() - return if ( _network_home.can_local_decorate() and _fishing_spot.can_open_fishing_shop() and _game_ui.get_player_storage().open_storage_from_home(true) ): - _game_ui.set_storage_prompt_visible(false) + _refresh_home_door_prompt({}) get_viewport().set_input_as_handled() return var nearby_home_owner: String = _home_world.find_nearby_exterior_owner( @@ -1671,9 +1700,18 @@ func _unhandled_input(event: InputEvent) -> void: ) if not nearby_home_owner.is_empty(): if _network_home.request_enter(nearby_home_owner): - _game_ui.set_storage_prompt_visible(false) + _refresh_home_door_prompt({}) get_viewport().set_input_as_handled() return + if ( + _rv_upgrade_shop_interaction != null + and _rv_upgrade_shop_interaction.is_local_player_in_range() + and _fishing_spot.can_open_fishing_shop() + and _game_ui.get_rv_upgrade_shop().open_shop() + ): + _game_ui.set_shop_prompt_visible(false) + get_viewport().set_input_as_handled() + return if ( _decor_shop_interaction != null and _decor_shop_interaction.is_local_player_in_range() @@ -1703,14 +1741,24 @@ func _process(delta: float) -> void: ) _print_dedicated_metrics() return + _maybe_begin_home_exit_transition() + var show_rv_upgrade_prompt := _can_show_rv_upgrade_shop_prompt() var show_decor_shop_prompt := _can_show_decor_shop_prompt() - var show_shop_prompt := show_decor_shop_prompt or _can_show_shop_prompt() + var show_shop_prompt := ( + show_rv_upgrade_prompt + or show_decor_shop_prompt + or _can_show_shop_prompt() + ) var shop_prompt_anchor := ( - _decor_shop_interaction.get_prompt_anchor_position() - if show_decor_shop_prompt + _rv_upgrade_shop_interaction.get_prompt_anchor_position() + if show_rv_upgrade_prompt else ( - _shop_interaction.get_prompt_anchor_position() - if _shop_interaction != null else Vector3.ZERO + _decor_shop_interaction.get_prompt_anchor_position() + if show_decor_shop_prompt + else ( + _shop_interaction.get_prompt_anchor_position() + if _shop_interaction != null else Vector3.ZERO + ) ) ) _game_ui.set_shop_prompt_visible( @@ -1718,11 +1766,7 @@ func _process(delta: float) -> void: shop_prompt_anchor, ) var home_prompt := _get_home_prompt() - _game_ui.set_storage_prompt_visible( - not home_prompt.is_empty(), - home_prompt.get("anchor", Vector3.ZERO), - str(home_prompt.get("label", "enter RV")), - ) + _refresh_home_door_prompt(home_prompt) _game_ui.set_rv_storage_button_visible( _can_show_rv_storage_button() ) @@ -2577,12 +2621,23 @@ func _refresh_active_world_bindings() -> void: _decor_shop_interaction.local_player_range_changed.disconnect( _on_decor_shop_range_changed ) + if is_instance_valid(_rv_upgrade_shop_interaction): + if _rv_upgrade_shop_interaction.local_player_range_changed.is_connected( + _on_rv_upgrade_shop_range_changed + ): + _rv_upgrade_shop_interaction.local_player_range_changed.disconnect( + _on_rv_upgrade_shop_range_changed + ) _shop_interaction = _test_world.get_fishing_shop() _decor_shop_interaction = _test_world.get_decor_shop() + _rv_upgrade_shop_interaction = _test_world.get_rv_upgrade_shop() _storage_interaction = _test_world.get_player_storage() _network_sale.set_shop_interaction(_shop_interaction) _network_shop.set_shop_interaction(_shop_interaction) _network_shop.set_decor_shop_interaction(_decor_shop_interaction) + _network_shop.set_rv_upgrade_shop_interaction( + _rv_upgrade_shop_interaction + ) if _dedicated_runtime: return if _shop_interaction != null: @@ -2600,10 +2655,16 @@ func _refresh_active_world_bindings() -> void: _decor_shop_interaction.local_player_range_changed.connect( _on_decor_shop_range_changed ) + if _rv_upgrade_shop_interaction != null: + _rv_upgrade_shop_interaction.setup_local_player(_player) + _rv_upgrade_shop_interaction.local_player_range_changed.connect( + _on_rv_upgrade_shop_range_changed + ) _game_ui.set_world_interactions( _shop_interaction, _storage_interaction, _decor_shop_interaction, + _rv_upgrade_shop_interaction, ) _on_shop_range_changed( _shop_interaction != null @@ -2617,6 +2678,10 @@ func _refresh_active_world_bindings() -> void: _decor_shop_interaction != null and _decor_shop_interaction.is_local_player_in_range() ) + _on_rv_upgrade_shop_range_changed( + _rv_upgrade_shop_interaction != null + and _rv_upgrade_shop_interaction.is_local_player_in_range() + ) func _on_water_recovery_starting() -> void: @@ -2631,6 +2696,7 @@ func _on_water_recovery_starting() -> void: _game_ui.get_pause_menu().close_for_water_recovery() _game_ui.get_fishing_shop().close_for_water_recovery() _game_ui.get_decor_shop().close_for_water_recovery() + _game_ui.get_rv_upgrade_shop().close_for_water_recovery() _game_ui.get_player_storage().close_for_water_recovery() @@ -2679,6 +2745,7 @@ func _on_active_hotbar_item_changed( and item != null and item.is_available() and _player.bag.owns_item(item_id) + and not String(_network_home.get_local_space()).begins_with("rv:") ) var active_is_catching_net: bool = ( item_id == FishingShopStockType.CRAB_NET_ID @@ -2828,6 +2895,8 @@ func _finish_quit() -> void: func _exit_tree() -> void: + _cancel_home_entry_transition() + _cancel_home_exit_transition(true) if _dedicated_runtime and _network_session != null: _network_session.disconnect_session("Dedicated server stopping.") if _title_music_tween != null: @@ -2845,52 +2914,46 @@ func _exit_tree() -> void: func _on_shop_range_changed(in_range: bool) -> void: - _game_ui.set_shop_npc_player_in_range( - in_range - or ( - _decor_shop_interaction != null - and _decor_shop_interaction.is_local_player_in_range() - ) - ) + _refresh_shop_npc_speech_state() if not in_range: _game_ui.get_fishing_shop().close_for_range_exit() - _game_ui.set_shop_prompt_visible(_can_show_shop_prompt()) + _game_ui.set_shop_prompt_visible(_can_show_any_shop_prompt()) func _on_storage_range_changed(in_range: bool) -> void: if not in_range: _game_ui.get_player_storage().close_for_range_exit() var prompt := _get_home_prompt() - _game_ui.set_storage_prompt_visible( - not prompt.is_empty(), - prompt.get("anchor", Vector3.ZERO), - str(prompt.get("label", "enter RV")), - ) + _refresh_home_door_prompt(prompt) _game_ui.set_rv_storage_button_visible( _can_show_rv_storage_button() ) func _on_decor_shop_range_changed(in_range: bool) -> void: - _game_ui.set_shop_npc_player_in_range( - in_range - or ( - _shop_interaction != null - and _shop_interaction.is_local_player_in_range() - ) - ) + _refresh_shop_npc_speech_state() if not in_range: _game_ui.get_decor_shop().close_for_range_exit() - _game_ui.set_shop_prompt_visible( - _can_show_shop_prompt() or _can_show_decor_shop_prompt() - ) + _game_ui.set_shop_prompt_visible(_can_show_any_shop_prompt()) + + +func _on_rv_upgrade_shop_range_changed(in_range: bool) -> void: + _refresh_shop_npc_speech_state() + if not in_range: + _game_ui.get_rv_upgrade_shop().close_for_range_exit() + _game_ui.set_shop_prompt_visible(_can_show_any_shop_prompt()) + + +func _on_home_state_changed() -> void: + _refresh_shop_npc_speech_state() func _on_local_home_space_changed( space_id: StringName, - _owner_fingerprint: String, + owner_fingerprint: String, ) -> void: var inside_rv: bool = String(space_id).begins_with("rv:") + _refresh_active_hotbar_item() _fishing_spot.set_fishing_environment_enabled(not inside_rv) _game_ui.set_rv_interior_camera_mode( inside_rv @@ -2898,6 +2961,171 @@ func _on_local_home_space_changed( _game_ui.set_rv_storage_button_visible( _can_show_rv_storage_button() ) + if inside_rv and not _home_exit_transition_active: + _begin_home_entry_transition(owner_fingerprint) + elif not inside_rv and _home_entry_transition_active: + _cancel_home_entry_transition() + + +func _begin_home_entry_transition(owner_fingerprint: String) -> void: + if owner_fingerprint.is_empty() or _home_entry_transition_active: + return + _home_entry_transition_active = true + _refresh_home_door_prompt({}) + _player.set_local_input_suppressed(HOME_ENTRY_INPUT_OWNER, true) + _player.set_camera_input_suppressed(HOME_ENTRY_INPUT_OWNER, true) + var inward_direction: Vector3 = ( + -_home_world.get_interior_exit_direction(owner_fingerprint) + ) + _player.face_world_direction(inward_direction) + _player.begin_animation_action(PlayerType.CHARACTER_WALKING_ANIMATION) + _home_entry_walk_tween = create_tween() + _home_entry_walk_tween.set_trans(Tween.TRANS_SINE) + _home_entry_walk_tween.set_ease(Tween.EASE_IN_OUT) + _home_entry_walk_tween.tween_property( + _player, + "global_position", + _player.global_position + inward_direction * HOME_ENTRY_WALK_DISTANCE, + HOME_ENTRY_WALK_DURATION, + ) + _home_entry_walk_tween.finished.connect( + _cancel_home_entry_transition, + CONNECT_ONE_SHOT, + ) + + +func _cancel_home_entry_transition() -> void: + if _home_entry_walk_tween != null and _home_entry_walk_tween.is_valid(): + _home_entry_walk_tween.kill() + _home_entry_walk_tween = null + if is_instance_valid(_player): + _player.end_animation_action() + _player.set_local_input_suppressed(HOME_ENTRY_INPUT_OWNER, false) + _player.set_camera_input_suppressed(HOME_ENTRY_INPUT_OWNER, false) + _home_entry_transition_active = false + + +func _maybe_begin_home_exit_transition() -> void: + if ( + _home_exit_transition_active + or _home_entry_transition_active + or not _gameplay_started + or _water_recovery.is_recovery_active() + or not _fishing_spot.can_open_fishing_shop() + or _game_ui.get_player_storage().visible + or _game_ui.get_fishing_shop().visible + or _game_ui.get_decor_shop().visible + or _game_ui.get_rv_upgrade_shop().visible + ): + return + var owner_fingerprint: String = ( + _network_home.get_local_home_owner_fingerprint() + ) + if ( + owner_fingerprint.is_empty() + or not _home_world.has_avatar_crossed_interior_exit_threshold( + _player, + owner_fingerprint, + ) + ): + return + _begin_home_exit_transition(owner_fingerprint) + + +func _begin_home_exit_transition(owner_fingerprint: String) -> void: + _home_exit_transition_active = true + _home_exit_waiting_for_network = false + _home_exit_start_position = _player.global_position + _refresh_home_door_prompt({}) + _player.set_local_input_suppressed(HOME_EXIT_INPUT_OWNER, true) + _player.set_camera_input_suppressed(HOME_EXIT_INPUT_OWNER, true) + var exit_direction: Vector3 = _home_world.get_interior_exit_direction( + owner_fingerprint + ) + _player.face_world_direction(exit_direction) + _player.begin_animation_action(PlayerType.CHARACTER_WALKING_ANIMATION) + _home_exit_walk_tween = create_tween() + _home_exit_walk_tween.set_trans(Tween.TRANS_SINE) + _home_exit_walk_tween.set_ease(Tween.EASE_IN_OUT) + _home_exit_walk_tween.tween_property( + _player, + "global_position", + _player.global_position + exit_direction * HOME_EXIT_WALK_DISTANCE, + HOME_EXIT_WALK_DURATION, + ) + _home_exit_walk_tween.finished.connect( + _on_home_exit_walk_finished, + CONNECT_ONE_SHOT, + ) + + +func _on_home_exit_walk_finished() -> void: + _home_exit_walk_tween = null + if not _home_exit_transition_active: + return + # End the walking action on the same frame translation ends. The fade and + # authoritative relocation may take longer, but a stationary avatar must + # never keep cycling its walk animation during that wait. + _player.end_animation_action() + _game_ui.get_screen_fade().fade_to_black(HOME_EXIT_FADE_GENERATION) + + +func _on_home_exit_fade_transition_completed( + generation: int, + faded_to_black: bool, +) -> void: + if ( + generation != HOME_EXIT_FADE_GENERATION + or not _home_exit_transition_active + ): + return + if faded_to_black: + # A local host can apply the authoritative transition synchronously from + # request_exit(). Mark this first so its completion signal is not lost. + _home_exit_waiting_for_network = true + var request_started: bool = _network_home.request_exit() + if not request_started: + _home_exit_waiting_for_network = false + _player.global_position = _home_exit_start_position + _game_ui.get_screen_fade().fade_from_black( + HOME_EXIT_FADE_GENERATION + ) + return + _cancel_home_exit_transition(false) + + +func _on_local_home_transition_finished( + accepted: bool, + _message: String, +) -> void: + if ( + not _home_exit_transition_active + or not _home_exit_waiting_for_network + ): + return + _home_exit_waiting_for_network = false + if not accepted: + _player.global_position = _home_exit_start_position + _game_ui.get_screen_fade().fade_from_black(HOME_EXIT_FADE_GENERATION) + + +func _cancel_home_exit_transition(reset_fade: bool) -> void: + if _home_exit_walk_tween != null and _home_exit_walk_tween.is_valid(): + _home_exit_walk_tween.kill() + _home_exit_walk_tween = null + if is_instance_valid(_player): + _player.end_animation_action() + _player.set_local_input_suppressed(HOME_EXIT_INPUT_OWNER, false) + _player.set_camera_input_suppressed(HOME_EXIT_INPUT_OWNER, false) + if ( + reset_fade + and is_instance_valid(_game_ui) + and is_instance_valid(_game_ui.get_screen_fade()) + ): + _game_ui.get_screen_fade().reset_immediately() + _home_exit_transition_active = false + _home_exit_waiting_for_network = false + _home_exit_start_position = Vector3.ZERO func _on_rv_storage_requested() -> void: @@ -2913,6 +3141,7 @@ func _can_show_shop_prompt() -> bool: and _shop_interaction.is_local_player_in_range() and not _game_ui.get_fishing_shop().visible and not _game_ui.get_decor_shop().visible + and not _game_ui.get_rv_upgrade_shop().visible and not _water_recovery.is_recovery_active() and _fishing_spot.can_open_fishing_shop() ) @@ -2925,15 +3154,96 @@ func _can_show_decor_shop_prompt() -> bool: and _decor_shop_interaction.is_local_player_in_range() and not _game_ui.get_decor_shop().visible and not _game_ui.get_fishing_shop().visible + and not _game_ui.get_rv_upgrade_shop().visible and not _water_recovery.is_recovery_active() and _fishing_spot.can_open_fishing_shop() ) +func _can_show_rv_upgrade_shop_prompt() -> bool: + return ( + _gameplay_started + and _rv_upgrade_shop_interaction != null + and _rv_upgrade_shop_interaction.is_local_player_in_range() + and not _game_ui.get_rv_upgrade_shop().visible + and not _game_ui.get_fishing_shop().visible + and not _game_ui.get_decor_shop().visible + and not _water_recovery.is_recovery_active() + and _fishing_spot.can_open_fishing_shop() + ) + + +func _can_show_any_shop_prompt() -> bool: + return ( + _can_show_shop_prompt() + or _can_show_decor_shop_prompt() + or _can_show_rv_upgrade_shop_prompt() + ) + + +func _is_any_shop_npc_in_range() -> bool: + return ( + ( + _shop_interaction != null + and _shop_interaction.is_local_player_in_range() + ) + or ( + _decor_shop_interaction != null + and _decor_shop_interaction.is_local_player_in_range() + ) + or ( + _rv_upgrade_shop_interaction != null + and _rv_upgrade_shop_interaction.is_local_player_in_range() + ) + ) + + +func _refresh_shop_npc_speech_state() -> void: + var interaction := _get_active_shop_npc_interaction() + var dialogue_text: String = "" + if interaction != null: + dialogue_text = interaction.get_dialogue_text(_home_state.get_tier()) + _game_ui.set_shop_npc_player_in_range( + interaction != null, + dialogue_text, + ) + + +func _get_active_shop_npc_interaction() -> FishingShopInteractionType: + # Match the interaction and prompt priority used above: RV, decor, fishing. + if ( + _rv_upgrade_shop_interaction != null + and _rv_upgrade_shop_interaction.is_local_player_in_range() + ): + return _rv_upgrade_shop_interaction + if ( + _decor_shop_interaction != null + and _decor_shop_interaction.is_local_player_in_range() + ): + return _decor_shop_interaction + if ( + _shop_interaction != null + and _shop_interaction.is_local_player_in_range() + ): + return _shop_interaction + return null + + func _can_show_storage_prompt() -> bool: return not _get_home_prompt().is_empty() +func _refresh_home_door_prompt(prompt: Dictionary) -> void: + # Home entry belongs to the doorway in world space. Keep the retired HUD + # prompt hidden so it cannot overlap the compact door-mounted sign. + _game_ui.set_storage_prompt_visible(false) + _home_world.set_exterior_prompt_visible( + str(prompt.get("owner_fingerprint", "")), + not prompt.is_empty(), + str(prompt.get("label", "enter home")), + ) + + func _can_show_rv_storage_button() -> bool: return ( _gameplay_started @@ -2950,6 +3260,7 @@ func _get_home_prompt() -> Dictionary: or _game_ui.get_player_storage().visible or _game_ui.get_fishing_shop().visible or _game_ui.get_decor_shop().visible + or _game_ui.get_rv_upgrade_shop().visible or _water_recovery.is_recovery_active() or not _fishing_spot.can_open_fishing_shop() ): @@ -2958,20 +3269,12 @@ func _get_home_prompt() -> Dictionary: _network_home.get_local_home_owner_fingerprint() ) if not owner_fingerprint.is_empty(): - if _home_world.is_avatar_near_interior_exit( - _player, owner_fingerprint - ): - return { - "label": "leave RV", - "anchor": _home_world.get_interior_prompt_position( - owner_fingerprint - ), - } return {} var nearby_owner: String = _home_world.find_nearby_exterior_owner(_player) if nearby_owner.is_empty(): return {} return { - "label": "enter RV", + "label": "enter home", "anchor": _home_world.get_exterior_prompt_position(nearby_owner), + "owner_fingerprint": nearby_owner, } diff --git a/network/network_home_service.gd b/network/network_home_service.gd index 33fa6ee..4885961 100644 --- a/network/network_home_service.gd +++ b/network/network_home_service.gd @@ -27,6 +27,8 @@ var _manifests_by_fingerprint: Dictionary[String, Dictionary] = {} var _fingerprint_by_peer: Dictionary[int, String] = {} var _authorized_owned_counts: Dictionary[int, Dictionary] = {} var _authorization_result_owner: Dictionary[String, int] = {} +var _authorized_home_tiers: Dictionary[int, int] = {} +var _home_upgrade_result_owner: Dictionary[String, int] = {} var _interior_slots_by_space: Dictionary[StringName, Dictionary] = {} var _next_interior_index: int = 0 var _suppress_local_submission: bool = false @@ -103,6 +105,17 @@ func get_authoritative_owned_count( return int(owned.get(String(decor_id), 0)) +func get_authoritative_home_tier(peer_id: int) -> int: + if _authorized_home_tiers.has(peer_id): + return int(_authorized_home_tiers[peer_id]) + var fingerprint: String = _fingerprint_for_peer(peer_id) + var manifest: Dictionary = _manifests_by_fingerprint.get(fingerprint, {}) + if manifest.is_empty(): + return -1 + var home: Dictionary = manifest.get("home", {}) + return int(home.get("tier", -1)) + + func place_local_decor( decor_id: StringName, position: Vector3, @@ -337,6 +350,35 @@ func finalize_decor_purchase( _authorized_owned_counts.erase(peer_id) +func authorize_home_upgrade( + peer_id: int, + resulting_tier: int, + result_id: String, +) -> void: + if ( + not _session.is_host() + or peer_id <= 0 + or result_id.is_empty() + or resulting_tier < PlayerHomeStateType.STARTER_TIER + or resulting_tier > PlayerHomeStateType.MAX_TIER + ): + return + _authorized_home_tiers[peer_id] = resulting_tier + _home_upgrade_result_owner[result_id] = peer_id + + +func finalize_home_upgrade( + peer_id: int, + result_id: String, + applied: bool, +) -> void: + if _home_upgrade_result_owner.get(result_id, 0) != peer_id: + return + _home_upgrade_result_owner.erase(result_id) + if not applied: + _authorized_home_tiers.erase(peer_id) + + func refresh_world_presentations() -> void: if _world_service == null: return @@ -442,7 +484,7 @@ func _process_manifest_request(peer_id: int, data: Dictionary) -> void: not NetworkHomeProtocolType.validate_manifest_request(data) or str(data["session_id"]) != _session.get_session_id() ): - _reject_manifest(peer_id, "The RV update was invalid.") + _reject_manifest(peer_id, "The home update was invalid.") return var record := _session.get_peer_record(peer_id) var fingerprint: String = str(data["owner_fingerprint"]) @@ -456,7 +498,7 @@ func _process_manifest_request(peer_id: int, data: Dictionary) -> void: data["sender_signature"], ) ): - _reject_manifest(peer_id, "The RV owner could not be verified.") + _reject_manifest(peer_id, "The home owner could not be verified.") return var home_data: Dictionary = PlayerHomeStateType.sanitize_save_data( data["home"] @@ -464,7 +506,7 @@ func _process_manifest_request(peer_id: int, data: Dictionary) -> void: var prior: Dictionary = _manifests_by_fingerprint.get(fingerprint, {}) var is_first_manifest: bool = prior.is_empty() if not _valid_manifest_revision(peer_id, prior, home_data): - _reject_manifest(peer_id, "The RV update was rejected by the host.") + _reject_manifest(peer_id, "The home update was rejected by the host.") return if not _moved_decor_clear_of_players(fingerprint, prior, home_data): _reject_manifest(peer_id, "A player is in the way of that decor.") @@ -472,7 +514,7 @@ func _process_manifest_request(peer_id: int, data: Dictionary) -> void: var manifest: Dictionary if prior.is_empty(): if _manifests_by_fingerprint.size() >= MAX_MANIFESTS: - _reject_manifest(peer_id, "This room cannot place another RV.") + _reject_manifest(peer_id, "This room cannot place another home.") return var reserved: Array[Transform3D] = [] for existing: Dictionary in _manifests_by_fingerprint.values(): @@ -523,10 +565,17 @@ func _valid_manifest_revision( # no prior room ledger with which to compare its first manifest. return true var prior_home: Dictionary = prior_manifest["home"] + var prior_tier: int = int(prior_home["tier"]) + var next_tier: int = int(home_data["tier"]) + var tier_is_authorized: bool = ( + next_tier != prior_tier + and int(_authorized_home_tiers.get(peer_id, -1)) == next_tier + ) if ( int(home_data["revision"]) <= int(prior_home["revision"]) - or int(home_data["tier"]) != int(prior_home["tier"]) - or str(home_data["exterior_id"]) != str(prior_home["exterior_id"]) + or (next_tier != prior_tier and not tier_is_authorized) + or str(home_data["exterior_id"]) + != str(PlayerHomeStateType.exterior_id_for_tier(next_tier)) ): return false var prior_owned: Dictionary = prior_home["owned_decor"] @@ -619,6 +668,11 @@ static func _placement_position(placement: Dictionary) -> Vector3: func _consume_owned_authorizations(peer_id: int, home_data: Dictionary) -> void: + if ( + _authorized_home_tiers.has(peer_id) + and int(home_data["tier"]) == int(_authorized_home_tiers[peer_id]) + ): + _authorized_home_tiers.erase(peer_id) var authorized: Dictionary = _authorized_owned_counts.get(peer_id, {}) if authorized.is_empty(): return @@ -1027,7 +1081,7 @@ func _process_transition_request(peer_id: int, data: Dictionary) -> void: data["sender_signature"], ) ): - _send_transition_rejection(peer_id, "The RV transition was invalid.") + _send_transition_rejection(peer_id, "The home transition was invalid.") return var owner_fingerprint: String = str(data["owner_fingerprint"]) var action: int = int(data["action"]) @@ -1036,7 +1090,7 @@ func _process_transition_request(peer_id: int, data: Dictionary) -> void: owner_fingerprint, {} ) if avatar == null or manifest.is_empty(): - _send_transition_rejection(peer_id, "That RV is unavailable.") + _send_transition_rejection(peer_id, "That home is unavailable.") return if action == NetworkHomeProtocolType.TransitionAction.ENTER: var record := _session.get_peer_record(peer_id) @@ -1052,7 +1106,7 @@ func _process_transition_request(peer_id: int, data: Dictionary) -> void: avatar, owner_fingerprint ) ): - _send_transition_rejection(peer_id, "You cannot enter that RV.") + _send_transition_rejection(peer_id, "You cannot enter that home.") return var interior_space: StringName = ( NetworkHomeProtocolType.make_space_id(owner_fingerprint) @@ -1076,7 +1130,7 @@ func _process_transition_request(peer_id: int, data: Dictionary) -> void: avatar, owner_fingerprint ) ): - _send_transition_rejection(peer_id, "Move closer to the RV door.") + _send_transition_rejection(peer_id, "Move closer to the home door.") return _apply_host_transition( peer_id, @@ -1282,6 +1336,10 @@ func _on_peer_removed(peer_id: int) -> void: var fingerprint: String = _fingerprint_by_peer.get(peer_id, "") _fingerprint_by_peer.erase(peer_id) _authorized_owned_counts.erase(peer_id) + _authorized_home_tiers.erase(peer_id) + for result_id: String in _home_upgrade_result_owner.keys(): + if int(_home_upgrade_result_owner[result_id]) == peer_id: + _home_upgrade_result_owner.erase(result_id) if fingerprint.is_empty(): return if _session.is_host(): @@ -1336,6 +1394,8 @@ func _on_session_state_changed(state: NetworkSession.State) -> void: _fingerprint_by_peer.clear() _authorized_owned_counts.clear() _authorization_result_owner.clear() + _authorized_home_tiers.clear() + _home_upgrade_result_owner.clear() _publish_queued = false _last_submitted_local_home_revision = -1 _pending_local_decor_transactions.clear() diff --git a/network/network_protocol.gd b/network/network_protocol.gd index 49aca95..5b3ca89 100644 --- a/network/network_protocol.gd +++ b/network/network_protocol.gd @@ -47,6 +47,7 @@ const FRIENDS_CAPABILITY: String = "friends_v1" const MOVEMENT_RECONCILIATION_CAPABILITY: String = "movement_reconciliation_v2" const FISHING_REPLICATION_CAPABILITY: String = "fishing_replication_v2" const HOME_CAPABILITY: String = "portable_home_v1" +const HOME_UPGRADE_CAPABILITY: String = "home_upgrade_v1" const DEFAULT_WORLD_SEED: int = 13001 const MAX_WORLD_SEED: int = 2147483646 @@ -205,6 +206,7 @@ static func make_client_hello( MOVEMENT_RECONCILIATION_CAPABILITY, FISHING_REPLICATION_CAPABILITY, HOME_CAPABILITY, + HOME_UPGRADE_CAPABILITY, ]), "cosmetic_snapshot": cosmetic_snapshot, "identity_fingerprint": identity_fingerprint, @@ -346,6 +348,7 @@ static func make_server_hello( MOVEMENT_RECONCILIATION_CAPABILITY, FISHING_REPLICATION_CAPABILITY, HOME_CAPABILITY, + HOME_UPGRADE_CAPABILITY, "chat_v1", "mail_v1", "profile_v1", diff --git a/network/network_session.gd b/network/network_session.gd index 66d5101..7c259e0 100644 --- a/network/network_session.gd +++ b/network/network_session.gd @@ -340,6 +340,7 @@ func _register_player_host() -> void: NetworkProtocol.MOVEMENT_RECONCILIATION_CAPABILITY, NetworkProtocol.FISHING_REPLICATION_CAPABILITY, NetworkProtocol.HOME_CAPABILITY, + NetworkProtocol.HOME_UPGRADE_CAPABILITY, ]), ) _registry.update_appearance(1, _local_appearance_snapshot) @@ -668,6 +669,7 @@ func supports_server_capability(capability: StringName) -> bool: NetworkProtocol.MOVEMENT_RECONCILIATION_CAPABILITY, NetworkProtocol.FISHING_REPLICATION_CAPABILITY, NetworkProtocol.HOME_CAPABILITY, + NetworkProtocol.HOME_UPGRADE_CAPABILITY, "chat_v1", "mail_v1", "profile_v1", @@ -1638,6 +1640,7 @@ func receive_server_hello(data: Dictionary) -> void: NetworkProtocol.MOVEMENT_RECONCILIATION_CAPABILITY, NetworkProtocol.FISHING_REPLICATION_CAPABILITY, NetworkProtocol.HOME_CAPABILITY, + NetworkProtocol.HOME_UPGRADE_CAPABILITY, ]), ) _registry.update_appearance(local_peer_id, _local_appearance_snapshot) diff --git a/network/network_shop_protocol.gd b/network/network_shop_protocol.gd index da9419a..e58556e 100644 --- a/network/network_shop_protocol.gd +++ b/network/network_shop_protocol.gd @@ -5,6 +5,7 @@ const CAPABILITY: StringName = &"shop_v1" const ART_CAPABILITY: StringName = &"art_shop_v1" const BACKPACK_CAPABILITY: StringName = &"backpack_shop_v1" const DECOR_CAPABILITY: StringName = &"portable_home_v1" +const HOME_UPGRADE_CAPABILITY: StringName = &"home_upgrade_v1" const RELIABLE_CHANNEL: int = NetworkProtocol.SHOP_RELIABLE_CHANNEL const MAX_ID_LENGTH: int = 96 const MAX_MESSAGE_LENGTH: int = 160 @@ -15,7 +16,7 @@ enum ProductCategory { ROD, REEL_SPEED_UPGRADE, BARRIER_POWER_UPGRADE, - COOLER_CAPACITY_UPGRADE, + HOME_UPGRADE, ART_KIT, ART_UPGRADE, BACKPACK_CAPACITY_UPGRADE, diff --git a/network/network_shop_service.gd b/network/network_shop_service.gd index 8294b53..e4d6f9c 100644 --- a/network/network_shop_service.gd +++ b/network/network_shop_service.gd @@ -12,9 +12,10 @@ const DecorCatalogType = preload("res://homes/decor_catalog.gd") const FISHING_SHOP_ID: StringName = &"main_fishing_shop" const DECOR_SHOP_ID: StringName = &"rv_decor_shop" +const RV_UPGRADE_SHOP_ID: StringName = &"rv_upgrade_shop" const REEL_PRODUCT_ID: StringName = &"reel_speed_upgrade" const BARRIER_PRODUCT_ID: StringName = &"barrier_power_upgrade" -const COOLER_PRODUCT_ID: StringName = &"cooler_capacity_upgrade" +const HOME_UPGRADE_PRODUCT_ID: StringName = &"starter_rv_upgrade" const BACKPACK_PRODUCT_ID: StringName = &"backpack_capacity_upgrade" const MAX_LEDGER_ENTRIES_PER_PEER: int = 64 @@ -34,6 +35,7 @@ var _spawn_service: PlayerSpawnService var _network_fishing: NetworkFishingService var _interaction: FishingShopInteraction var _decor_interaction: DecorShopInteraction +var _rv_upgrade_interaction: FishingShopInteraction var _wallet: PlayerWallet var _bag: PlayerBag var _item_catalog: ItemCatalog @@ -71,6 +73,7 @@ func setup( home_state: PlayerHomeState = null, network_home: NetworkHomeService = null, decor_interaction: DecorShopInteraction = null, + rv_upgrade_interaction: FishingShopInteraction = null, ) -> void: _session = session _spawn_service = spawn_service @@ -88,6 +91,7 @@ func setup( _home_state = home_state _network_home = network_home _decor_interaction = decor_interaction + _rv_upgrade_interaction = rv_upgrade_interaction if not _session.peer_removed.is_connected(_on_peer_removed): _session.peer_removed.connect(_on_peer_removed) if not _session.state_changed.is_connected(_on_session_state_changed): @@ -104,6 +108,12 @@ func set_decor_shop_interaction( _decor_interaction = interaction +func set_rv_upgrade_shop_interaction( + interaction: FishingShopInteraction, +) -> void: + _rv_upgrade_interaction = interaction + + func can_request_purchase() -> bool: return ( _session != null @@ -154,6 +164,19 @@ func can_request_decor_purchase() -> bool: ) +func can_request_home_upgrade() -> bool: + return ( + can_request_purchase() + and _home_state != null + and ( + _session.is_host() + or _session.supports_server_capability( + NetworkShopProtocol.HOME_UPGRADE_CAPABILITY + ) + ) + ) + + func is_local_purchase_pending() -> bool: return not _pending_local_request.is_empty() @@ -204,12 +227,12 @@ func request_barrier_power_upgrade() -> String: ) -func request_cooler_capacity_upgrade() -> String: +func request_home_upgrade() -> String: return _request_purchase( - COOLER_PRODUCT_ID, - NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE, + HOME_UPGRADE_PRODUCT_ID, + NetworkShopProtocol.ProductCategory.HOME_UPGRADE, 1, - _cooler_capacity.get_level() if _cooler_capacity != null else 0 + _home_state.get_tier() if _home_state != null else 0 ) @@ -308,6 +331,15 @@ func _request_purchase( product_id, category, 0, 0, ) return "" + if ( + category == NetworkShopProtocol.ProductCategory.HOME_UPGRADE + and not can_request_home_upgrade() + ): + local_purchase_finished.emit( + "", false, "RV upgrades require a newer server.", + product_id, category, 0, 0, + ) + return "" if ( category == NetworkShopProtocol.ProductCategory.DECOR and not can_request_decor_purchase() @@ -318,11 +350,7 @@ func _request_purchase( ) return "" var request_id: String = _new_id("shop") - var shop_id: StringName = ( - DECOR_SHOP_ID - if category == NetworkShopProtocol.ProductCategory.DECOR - else FISHING_SHOP_ID - ) + var shop_id: StringName = _shop_id_for_category(category) var request: Dictionary = { "request_id": request_id, "session_id": _session.get_session_id(), @@ -402,9 +430,7 @@ func _handle_purchase_request(peer_id: int, data: Dictionary) -> void: if not _is_shop_available_for_peer(peer_id, requested_shop_id): var avatar: Player = _spawn_service.get_avatar(peer_id) var requested_interaction: FishingShopInteraction = ( - _decor_interaction - if requested_shop_id == DECOR_SHOP_ID - else _interaction + _interaction_for_shop(requested_shop_id) ) var message: String = ( "The shop is unavailable." @@ -416,16 +442,22 @@ func _handle_purchase_request(peer_id: int, data: Dictionary) -> void: var result: Dictionary = _build_authoritative_result(peer_id, data) if ( bool(result.get("accepted", false)) - and int(result.get("category", -1)) - == NetworkShopProtocol.ProductCategory.DECOR and _network_home != null ): - _network_home.authorize_decor_purchase( - peer_id, - StringName(str(result["product_id"])), - int(result["resulting_state"]), - str(result["result_id"]), - ) + match int(result.get("category", -1)): + NetworkShopProtocol.ProductCategory.DECOR: + _network_home.authorize_decor_purchase( + peer_id, + StringName(str(result["product_id"])), + int(result["resulting_state"]), + str(result["result_id"]), + ) + NetworkShopProtocol.ProductCategory.HOME_UPGRADE: + _network_home.authorize_home_upgrade( + peer_id, + int(result["resulting_state"]), + str(result["result_id"]), + ) _pending_by_peer[peer_id] = request_id _record_and_send(peer_id, result) @@ -448,14 +480,19 @@ func _build_authoritative_result( ) if authoritative_count >= 0: current_state = authoritative_count + elif ( + category == NetworkShopProtocol.ProductCategory.HOME_UPGRADE + and _network_home != null + ): + var authoritative_tier: int = ( + _network_home.get_authoritative_home_tier(peer_id) + ) + if authoritative_tier >= 0: + current_state = authoritative_tier var cost: int = -1 var resulting_state: int = current_state var rejection: String = "" - var expected_shop_id: StringName = ( - DECOR_SHOP_ID - if category == NetworkShopProtocol.ProductCategory.DECOR - else FISHING_SHOP_ID - ) + var expected_shop_id: StringName = _shop_id_for_category(category) if StringName(str(request["shop_id"])) != expected_shop_id: rejection = "The shop is unavailable." elif quantity < 1: @@ -569,18 +606,14 @@ func _build_authoritative_result( ] ) resulting_state = current_state + 1 - NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE: + NetworkShopProtocol.ProductCategory.HOME_UPGRADE: if ( - product_id != COOLER_PRODUCT_ID - or current_state >= PlayerCoolerCapacity.MAX_LEVEL + product_id != HOME_UPGRADE_PRODUCT_ID + or current_state >= PlayerHomeState.MAX_TIER ): rejection = "Upgrade is already at maximum." else: - cost = ( - PlayerCoolerCapacity.EXPANSION_COSTS[ - current_state - ] - ) + cost = PlayerHomeState.HOME_UPGRADE_COSTS[current_state] resulting_state = current_state + 1 NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE: if ( @@ -874,10 +907,12 @@ func _validate_local_result(data: Dictionary) -> String: return "Purchase could not be completed." if _upgrades.get_next_barrier_power_cost() != cost: return "Purchase could not be completed." - NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE: - if _cooler_capacity.get_level() != expected_state: - return "Purchase could not be completed." - if _cooler_capacity.get_next_cost() != cost: + NetworkShopProtocol.ProductCategory.HOME_UPGRADE: + if ( + product_id != HOME_UPGRADE_PRODUCT_ID + or _home_state.get_tier() != expected_state + or _home_state.get_next_upgrade_cost() != cost + ): return "Purchase could not be completed." NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE: if ( @@ -947,8 +982,11 @@ func _apply_local_product(data: Dictionary) -> bool: return _upgrades.purchase_reel_speed(_wallet) NetworkShopProtocol.ProductCategory.BARRIER_POWER_UPGRADE: return _upgrades.purchase_barrier_power(_wallet) - NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE: - return _cooler_capacity.purchase(_wallet) + NetworkShopProtocol.ProductCategory.HOME_UPGRADE: + return ( + _wallet.debit(int(data["total_cost"])) + and _home_state.upgrade_to_next_tier() + ) NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE: return ( _inventory_layout != null @@ -1061,6 +1099,9 @@ func _handle_acknowledgement( _network_home.finalize_decor_purchase( peer_id, result_id, applied ) + _network_home.finalize_home_upgrade( + peer_id, result_id, applied + ) _acknowledged_results[result_id] = true _bound_dictionary(_acknowledged_results) if _pending_by_peer.get(peer_id, "") == request_id: @@ -1071,11 +1112,7 @@ func _is_shop_available_for_peer( peer_id: int, shop_id: StringName, ) -> bool: - var interaction: FishingShopInteraction = ( - _decor_interaction - if shop_id == DECOR_SHOP_ID - else _interaction - ) + var interaction: FishingShopInteraction = _interaction_for_shop(shop_id) if ( _session == null or not _session.is_host() @@ -1097,6 +1134,24 @@ func _is_shop_available_for_peer( ) +func _shop_id_for_category(category: int) -> StringName: + match category: + NetworkShopProtocol.ProductCategory.DECOR: + return DECOR_SHOP_ID + NetworkShopProtocol.ProductCategory.HOME_UPGRADE: + return RV_UPGRADE_SHOP_ID + return FISHING_SHOP_ID + + +func _interaction_for_shop(shop_id: StringName) -> FishingShopInteraction: + match shop_id: + DECOR_SHOP_ID: + return _decor_interaction + RV_UPGRADE_SHOP_ID: + return _rv_upgrade_interaction + return _interaction + + func _on_peer_removed(peer_id: int) -> void: _request_ledgers.erase(peer_id) _pending_by_peer.erase(peer_id) diff --git a/player/player.gd b/player/player.gd index e36f92b..78dac3d 100644 --- a/player/player.gd +++ b/player/player.gd @@ -90,6 +90,7 @@ const CATCH_SHOWCASE_INPUT_OWNER: StringName = &"catch_showcase" # safe IDs so newer clients can extend it, but Player only presents actions # explicitly approved by this catalog. const NETWORK_ANIMATION_ACTION_IDS: Array[StringName] = [ + CHARACTER_WALKING_ANIMATION, CHARACTER_CASTING_ANIMATION, CHARACTER_NET_DRAW_ANIMATION, CHARACTER_NET_STRIKE_ANIMATION, @@ -436,6 +437,11 @@ var _rv_previous_camera_environment: Environment @export var maximum_zoom: float = 8.0 @export var zoom_step: float = 0.75 @export var zoom_smoothing: float = 12.0 +@export_range(0.0, 1.0, 0.01) var fishing_reel_zoom_amount: float = 0.22 +@export_range(0.0, 1.5, 0.01) var fishing_barrier_break_zoom: float = 0.38 +@export_range(0.05, 1.0, 0.01) var fishing_break_zoom_decay: float = 0.34 +@export_range(0.0, 0.2, 0.005) var fishing_barrier_hit_shake: float = 0.018 +@export_range(0.0, 0.3, 0.005) var fishing_barrier_break_shake: float = 0.045 @export_range(0.1, 12.0, 0.1) var controller_zoom_speed: float = 4.0 @export_range(0.0, 1.0, 0.01) var controller_trigger_threshold: float = 0.55 @export_range(1.0, 40.0, 0.5) var free_camera_speed: float = 10.0 @@ -497,6 +503,12 @@ var _remote_recovery_presentation_active: bool = false var _remote_recovery_visual_origin: Vector3 var _remote_recovery_elapsed: float = 0.0 var _target_zoom: float = 5.0 +var _fishing_reel_camera_active: bool = false +var _fishing_break_zoom_offset: float = 0.0 +var _fishing_camera_shake_remaining: float = 0.0 +var _fishing_camera_shake_duration: float = 0.0 +var _fishing_camera_shake_strength: float = 0.0 +var _fishing_camera_shake_phase: float = 0.0 var _showcase_rod_visibility: bool = true var _showcase_net_visibility: bool = false var _showcase_shovel_visibility: bool = false @@ -1162,6 +1174,7 @@ func _process(delta: float) -> void: ) if not local_control_enabled: return + _update_fishing_camera_effects(delta) if _free_camera_active: if _is_camera_input_enabled(): _rotate_free_camera( @@ -1190,13 +1203,68 @@ func _process(delta: float) -> void: ) var zoom_weight: float = 1.0 - exp(-zoom_smoothing * delta) + var fishing_zoom_offset: float = ( + fishing_reel_zoom_amount + if _fishing_reel_camera_active + else 0.0 + ) + _fishing_break_zoom_offset + var effective_target_zoom: float = clampf( + _target_zoom - fishing_zoom_offset, + 1.25 if _rv_interior_camera_mode else minimum_zoom, + 16.0 if _rv_interior_camera_mode else maximum_zoom, + ) _spring_arm.spring_length = lerpf( _spring_arm.spring_length, - _target_zoom, + effective_target_zoom, zoom_weight ) +func set_fishing_reel_camera_active(active: bool) -> void: + _fishing_reel_camera_active = active + + +func play_fishing_barrier_camera_feedback(barrier_broken: bool) -> void: + if not local_control_enabled or _free_camera_active: + return + _fishing_camera_shake_strength = ( + fishing_barrier_break_shake + if barrier_broken + else fishing_barrier_hit_shake + ) + _fishing_camera_shake_duration = 0.20 if barrier_broken else 0.10 + _fishing_camera_shake_remaining = _fishing_camera_shake_duration + if barrier_broken: + _fishing_break_zoom_offset = fishing_barrier_break_zoom + + +func _update_fishing_camera_effects(delta: float) -> void: + _fishing_break_zoom_offset = move_toward( + _fishing_break_zoom_offset, + 0.0, + ( + fishing_barrier_break_zoom + / maxf(fishing_break_zoom_decay, 0.05) + ) * delta, + ) + if _fishing_camera_shake_remaining <= 0.0: + _camera.h_offset = 0.0 + _camera.v_offset = 0.0 + return + _fishing_camera_shake_remaining = maxf( + _fishing_camera_shake_remaining - delta, + 0.0, + ) + _fishing_camera_shake_phase += delta * 92.0 + var decay: float = ( + _fishing_camera_shake_remaining + / maxf(_fishing_camera_shake_duration, 0.001) + ) + var strength: float = _fishing_camera_shake_strength * decay + _camera.h_offset = sin(_fishing_camera_shake_phase) * strength + _camera.v_offset = cos(_fishing_camera_shake_phase * 1.31) * strength * 0.7 + + func _update_blink(delta: float) -> void: if _fighting_visual_active: return @@ -3052,6 +3120,19 @@ func set_camera_active(active: bool) -> void: _camera.current = active +func face_world_direction(direction: Vector3) -> void: + var horizontal_direction := Vector3(direction.x, 0.0, direction.z) + if horizontal_direction.is_zero_approx() or _visuals == null: + return + horizontal_direction = horizontal_direction.normalized() + var target_world_yaw: float = atan2( + -horizontal_direction.x, + -horizontal_direction.z, + ) + _visuals.rotation.y = target_world_yaw - global_rotation.y + _network_target_visual_yaw = _visuals.rotation.y + + func apply_camera_settings( new_mouse_sensitivity: float, new_controller_sensitivity: float, diff --git a/progression/player_cooler_capacity.gd b/progression/player_cooler_capacity.gd index b8c62be..bbd0b87 100644 --- a/progression/player_cooler_capacity.gd +++ b/progression/player_cooler_capacity.gd @@ -2,62 +2,77 @@ class_name PlayerCoolerCapacity extends Node const PlayerWalletType = preload("res://economy/player_wallet.gd") +const PlayerHomeStateType = preload("res://homes/player_home_state.gd") signal capacity_changed(level: int, capacity: int) -## Kept under the historical class name so existing saves and network product -## identifiers migrate without losing their purchased level. This progression -## now controls the player's private storage box rather than carried catches. +## Compatibility adapter for saves and systems that still refer to the old +## cooler-capacity object. Storage is now derived exclusively from the player's +## home tier; this object is not independently purchasable. const CAPACITIES: Array[int] = [9, 18, 27, 36, 45, 54, 63, 72] const EXPANSION_COSTS: Array[int] = [75, 175, 400, 850, 1500, 2500, 4000] const MAX_LEVEL: int = 7 const MAX_CAPACITY: int = 72 -var _capacity_level: int = 0 +var _home_state: PlayerHomeStateType +var _legacy_capacity_level: int = 0 + + +func bind_home_state(home_state: PlayerHomeStateType) -> void: + if _home_state == home_state: + return + if ( + _home_state != null + and _home_state.changed.is_connected(_on_home_changed) + ): + _home_state.changed.disconnect(_on_home_changed) + _home_state = home_state + if ( + _home_state != null + and not _home_state.changed.is_connected(_on_home_changed) + ): + _home_state.changed.connect(_on_home_changed) + _on_home_changed() func get_level() -> int: - return _capacity_level + return _legacy_capacity_level func get_capacity() -> int: - return CAPACITIES[_capacity_level] + if _home_state != null: + # A new home upgrade grants its authored capacity. Older saves retain any + # separately purchased storage level so reducing the first RV tier cannot + # hide or discard items that were already placed in later slots. + return maxi( + _home_state.get_storage_capacity(), + CAPACITIES[clampi(_legacy_capacity_level, 0, MAX_LEVEL)], + ) + return CAPACITIES[clampi(_legacy_capacity_level, 0, MAX_LEVEL)] func get_next_capacity() -> int: - if _capacity_level >= MAX_LEVEL: - return -1 - return CAPACITIES[_capacity_level + 1] + return -1 func get_next_cost() -> int: - if _capacity_level >= MAX_LEVEL: - return -1 - return EXPANSION_COSTS[_capacity_level] + return -1 -func can_purchase(wallet: PlayerWalletType) -> bool: - var cost: int = get_next_cost() - return wallet != null and cost >= 0 and wallet.can_afford(cost) +func can_purchase(_wallet: PlayerWalletType) -> bool: + return false -func purchase(wallet: PlayerWalletType) -> bool: - if not can_purchase(wallet): - return false - var cost: int = get_next_cost() - if not wallet.debit(cost): - return false - _capacity_level += 1 - capacity_changed.emit(_capacity_level, get_capacity()) - return true +func purchase(_wallet: PlayerWalletType) -> bool: + return false func restore_level(level: int) -> bool: var validated: int = clampi(level, 0, MAX_LEVEL) - var changed: bool = _capacity_level != validated - _capacity_level = validated + var changed: bool = _legacy_capacity_level != validated + _legacy_capacity_level = validated if changed: - capacity_changed.emit(_capacity_level, get_capacity()) + capacity_changed.emit(get_level(), get_capacity()) return true @@ -66,4 +81,8 @@ func reset_to_defaults() -> void: func to_save_data() -> Dictionary: - return {"capacity_level": _capacity_level} + return {"capacity_level": get_level()} + + +func _on_home_changed() -> void: + capacity_changed.emit(get_level(), get_capacity()) diff --git a/save/player_save_manager.gd b/save/player_save_manager.gd index 56fd49c..c41f861 100644 --- a/save/player_save_manager.gd +++ b/save/player_save_manager.gd @@ -338,6 +338,11 @@ func load_player_data() -> bool: snapshot.reel_speed_level, snapshot.barrier_power_level ) + # Home tier is now the authority for private-storage capacity, so restore it + # before the compatibility capacity adapter and inventory layout. + var home_restored: bool = _home_state.restore_from_save_data( + snapshot.home_data + ) var cooler_restored: bool = _cooler_capacity.restore_level( snapshot.cooler_capacity_level ) @@ -368,9 +373,6 @@ func load_player_data() -> bool: snapshot.world_weather_seconds_remaining, ) var jobs_restored: bool = _jobs.restore_from_save_data(snapshot.jobs_data) - var home_restored: bool = _home_state.restore_from_save_data( - snapshot.home_data - ) _is_restoring = false if ( not inventory_restored @@ -1324,6 +1326,26 @@ func _build_load_snapshot(save_data: Dictionary) -> LoadSnapshot: PlayerCoolerCapacityType.MAX_LEVEL, "cooler.capacity_level" ) + # Before homes had upgrade tiers, storage was purchased separately. Preserve + # those saves by granting the starter RV to anybody who owned at least one + # legacy expansion. PlayerCoolerCapacity also retains the purchased legacy + # capacity so entries beyond the new RV's first 18 slots remain accessible. + if ( + snapshot.cooler_capacity_level > 0 + and int(snapshot.home_data.get("tier", 0)) + == PlayerHomeStateType.STARTER_TIER + ): + var migrated_home: Dictionary = home_data.duplicate(true) + migrated_home["tier"] = PlayerHomeStateType.STARTER_RV_TIER + migrated_home["exterior_id"] = String( + PlayerHomeStateType.STARTER_RV_EXTERIOR_ID + ) + var sanitized_migrated_home := ( + PlayerHomeStateType.sanitize_save_data(migrated_home) + ) + if sanitized_migrated_home.is_empty(): + return null + snapshot.home_data = sanitized_migrated_home snapshot.art_unlock_mask = _read_integer( art_data.get("unlock_mask"), 0, diff --git a/tests/economy_regression_validation.gd b/tests/economy_regression_validation.gd index ff82495..0728d82 100644 --- a/tests/economy_regression_validation.gd +++ b/tests/economy_regression_validation.gd @@ -53,7 +53,7 @@ func _run() -> void: ) assert(player != null) assert(catalog != null and catalog.candidates.size() == 316) - assert(LogbookCatalog.ordered_species(catalog.candidates).size() == 313) + assert(LogbookCatalog.ordered_species(catalog.candidates).size() == 314) assert(sale_service != null) assert(shop_service != null) assert(session != null and session.is_host()) @@ -82,7 +82,7 @@ func _run() -> void: main, player, catalog, sale_service, reservations ) _test_host_backpack_purchase(player, shop_service) - _test_host_storage_purchase(player, shop_service) + await _test_host_home_upgrade(main, player, shop_service) assert(not sale_service.is_local_sale_pending()) assert(not shop_service.is_local_purchase_pending()) @@ -175,7 +175,6 @@ func _run_multiplayer_client() -> void: assert(player.inventory_layout.restore_backpack_level( PlayerInventoryLayout.MAX_BACKPACK_LEVEL )) - assert(player.cooler_capacity.restore_level(PlayerCoolerCapacity.MAX_LEVEL)) player.inventory.set_inventory_layout(null) var catch_ids: Array[StringName] = [] for fish: FishData in catalog.candidates: @@ -202,7 +201,6 @@ func _run_multiplayer_client() -> void: assert(not player.inventory.contains_catch_id(catch_id)) assert(not sale_service.is_local_sale_pending()) assert(player.inventory_layout.restore_backpack_level(0)) - assert(player.cooler_capacity.restore_level(0)) var interaction := main.get("_shop_interaction") as FishingShopInteraction player.global_position = interaction.global_position @@ -567,27 +565,49 @@ func _test_host_backpack_purchase( assert(layout.get_next_backpack_cost() == -1) -func _test_host_storage_purchase( +func _test_host_home_upgrade( + main: Node, player: Player, shop_service: NetworkShopService, ) -> void: + var interaction := main.get( + "_rv_upgrade_shop_interaction" + ) as RVUpgradeInteraction + var home_state := main.get("_home_state") as PlayerHomeState var capacity := player.cooler_capacity + assert(interaction != null and home_state != null) + player.global_position = interaction.global_position + for _frame: int in 4: + await physics_frame + assert(interaction.is_avatar_in_range(player)) + assert(home_state.get_tier() == PlayerHomeState.STARTER_TIER) + assert( + interaction.get_dialogue_text(home_state.get_tier()) + == RVUpgradeInteraction.TENT_DIALOGUE_TEXT + ) assert(capacity.get_capacity() == 9) - var total_cost: int = 0 - for cost: int in PlayerCoolerCapacity.EXPANSION_COSTS: - total_cost += cost - if player.wallet.get_balance() < total_cost: - assert(player.wallet.credit(total_cost - player.wallet.get_balance())) + var upgrade_cost: int = home_state.get_next_upgrade_cost() + assert(upgrade_cost == PlayerHomeState.HOME_UPGRADE_COSTS.front()) + assert(upgrade_cost == 50) + if player.wallet.get_balance() < upgrade_cost: + assert(player.wallet.credit( + upgrade_cost - player.wallet.get_balance() + )) var balance_before := player.wallet.get_balance() - for expected_capacity: int in [18, 27, 36, 45, 54, 63, 72]: - _shop_result.clear() - assert(not shop_service.request_cooler_capacity_upgrade().is_empty()) - assert( - not _shop_result.is_empty() and bool(_shop_result[1]), - "Cooler purchase failed: %s" % [_shop_result], - ) - assert(capacity.get_capacity() == expected_capacity) - assert(player.wallet.get_balance() == balance_before - total_cost) + _shop_result.clear() + assert(not shop_service.request_home_upgrade().is_empty()) + assert( + not _shop_result.is_empty() and bool(_shop_result[1]), + "Home purchase failed: %s" % [_shop_result], + ) + assert(home_state.get_tier() == PlayerHomeState.STARTER_RV_TIER) + assert( + interaction.get_dialogue_text(home_state.get_tier()) + == RVUpgradeInteraction.RV_DIALOGUE_TEXT + ) + assert(capacity.get_capacity() == 18) + assert(player.wallet.get_balance() == balance_before - upgrade_cost) + assert(home_state.get_next_upgrade_cost() == -1) assert(capacity.get_next_cost() == -1) diff --git a/tests/home_spawn_multiplayer_validation.gd b/tests/home_spawn_multiplayer_validation.gd index 1f16147..2855eb2 100644 --- a/tests/home_spawn_multiplayer_validation.gd +++ b/tests/home_spawn_multiplayer_validation.gd @@ -49,6 +49,7 @@ func _run_host() -> void: host_fingerprint ) assert(_same_door_position(host_avatar.global_position, host_spawn.origin)) + assert(_faces_away_from_home(host_avatar, home_world, host_fingerprint)) assert(network_home.request_enter(host_fingerprint)) await physics_frame host_avatar.global_position = home_world.get_interior_exit_position( @@ -57,6 +58,7 @@ func _run_host() -> void: assert(network_home.request_exit()) await physics_frame assert(_same_door_position(host_avatar.global_position, host_spawn.origin)) + assert(_faces_away_from_home(host_avatar, home_world, host_fingerprint)) var remote_peer_id: int = await _wait_for_remote_peer(session) assert(remote_peer_id > 1) @@ -70,6 +72,9 @@ func _run_host() -> void: assert(_same_door_position( remote_avatar.global_position, remote_spawn.origin )) + assert(_faces_away_from_home( + remote_avatar, home_world, remote_fingerprint + )) var disconnect_deadline: int = Time.get_ticks_msec() + 12000 while ( @@ -118,6 +123,7 @@ func _run_client() -> void: assert(_same_door_position( player.global_position, exterior_spawn.origin )) + assert(_faces_away_from_home(player, home_world, fingerprint)) print("Home spawn multiplayer client validation: PASS") await _cleanup(main, session) @@ -151,6 +157,23 @@ func _wait_for_home( return false +func _faces_away_from_home( + avatar: Player, + home_world: HomeWorldService, + fingerprint: String, +) -> bool: + var exterior_basis: Basis = home_world.get_exterior_transform( + fingerprint + ).basis + var outward_direction := exterior_basis.z + outward_direction.y = 0.0 + if outward_direction.is_zero_approx(): + return false + return avatar.get_facing_direction().dot( + outward_direction.normalized() + ) >= 0.99 + + func _wait_for_remote_peer(session: NetworkSession) -> int: var deadline: int = Time.get_ticks_msec() + 20000 while Time.get_ticks_msec() < deadline: diff --git a/tests/logbook_runtime_validation.gd b/tests/logbook_runtime_validation.gd index 47e795d..e33e551 100644 --- a/tests/logbook_runtime_validation.gd +++ b/tests/logbook_runtime_validation.gd @@ -143,7 +143,7 @@ func _validate_save_round_trip( assert(catalog != null) assert(catalog.candidates.size() == 316) var active_species := LogbookCatalog.ordered_species(catalog.candidates) - assert(active_species.size() == 313) + assert(active_species.size() == 314) # Keep this runtime save fixture within maximum player capacity while the # focused catalog validation exercises every active species individually. var round_trip_species: Array[FishData] = [] @@ -164,12 +164,14 @@ func _validate_save_round_trip( player.inventory_layout.restore_backpack_level( PlayerInventoryLayout.MAX_BACKPACK_LEVEL ) - player.cooler_capacity.restore_level(PlayerCoolerCapacity.MAX_LEVEL) + var home_state := main.get("_home_state") as PlayerHomeState + assert(home_state != null) + assert(home_state.upgrade_to_next_tier()) assert( player.inventory_layout.get_backpack_level() == PlayerInventoryLayout.MAX_BACKPACK_LEVEL ) - assert(player.cooler_capacity.get_level() == PlayerCoolerCapacity.MAX_LEVEL) + assert(player.cooler_capacity.get_capacity() == 18) player.inventory.set_inventory_layout(null) for index: int in 4: _add_test_catch(player, round_trip_species[index]) diff --git a/ui/fishing_danger_vignette.gdshader b/ui/fishing_danger_vignette.gdshader new file mode 100644 index 0000000..8eee3df --- /dev/null +++ b/ui/fishing_danger_vignette.gdshader @@ -0,0 +1,10 @@ +shader_type canvas_item; + +uniform float intensity : hint_range(0.0, 1.0) = 0.0; + +void fragment() { + vec2 centered = UV * 2.0 - 1.0; + centered.x *= 0.56; + float edge = smoothstep(0.42, 1.02, length(centered)); + COLOR = vec4(0.16, 0.018, 0.025, edge * intensity * 0.72); +} diff --git a/ui/fishing_danger_vignette.gdshader.uid b/ui/fishing_danger_vignette.gdshader.uid new file mode 100644 index 0000000..578ec8b --- /dev/null +++ b/ui/fishing_danger_vignette.gdshader.uid @@ -0,0 +1 @@ +uid://c1qcj3m4b10x4 diff --git a/ui/fishing_shop.gd b/ui/fishing_shop.gd index 234a1c1..7cc8fa8 100644 --- a/ui/fishing_shop.gd +++ b/ui/fishing_shop.gd @@ -15,9 +15,6 @@ const PlayerFishingUpgradesType = preload( "res://progression/player_fishing_upgrades.gd" ) const PlayerType = preload("res://player/player.gd") -const PlayerCoolerCapacityType = preload( - "res://progression/player_cooler_capacity.gd" -) const PlayerArtUnlocksType = preload( "res://progression/player_art_unlocks.gd" ) @@ -154,9 +151,6 @@ const ROD_PRICE_ICON_SIZE: float = 22.0 @onready var _barrier_price_bubble: PanelContainer = %BarrierPriceBubble @onready var _barrier_purchase: Button = %BarrierPurchase @onready var _supplies_list: VBoxContainer = %SuppliesList -@onready var _cooler_cost: CurrencyAmount = %CoolerCost -@onready var _cooler_price_bubble: PanelContainer = %CoolerPriceBubble -@onready var _cooler_purchase: Button = %CoolerPurchase @onready var _backpack_cost: CurrencyAmount = %BackpackCost @onready var _backpack_price_bubble: PanelContainer = %BackpackPriceBubble @onready var _backpack_purchase: Button = %BackpackPurchase @@ -172,7 +166,6 @@ var _inventory: FishInventory var _hotbar: PlayerHotbar var _inventory_layout: PlayerInventoryLayout var _item_catalog: ItemCatalogType -var _cooler_capacity: PlayerCoolerCapacityType var _art_unlocks: PlayerArtUnlocksType var _network_shop: NetworkShopService var _network_sale: NetworkSaleService @@ -202,7 +195,6 @@ func _ready() -> void: %CloseButton.pressed.connect(close_shop) _reel_purchase.pressed.connect(_purchase_reel_speed) _barrier_purchase.pressed.connect(_purchase_barrier_power) - _cooler_purchase.pressed.connect(_purchase_cooler_capacity) _backpack_purchase.pressed.connect(_purchase_backpack_capacity) @@ -353,7 +345,6 @@ func _focus_shop_section() -> void: for upgrade_button: Button in [ _reel_purchase, _barrier_purchase, - _cooler_purchase, _backpack_purchase, ]: if not upgrade_button.disabled: @@ -509,7 +500,6 @@ func _apply_shop_styles() -> void: for panel: PanelContainer in [ _reel_price_bubble, _barrier_price_bubble, - _cooler_price_bubble, _backpack_price_bubble, ]: var price_style := UtilityPageStyleType.rounded_style( @@ -526,7 +516,6 @@ func _apply_shop_styles() -> void: for price: CurrencyAmount in [ _reel_cost, _barrier_cost, - _cooler_cost, _backpack_cost, ]: var amount_label := price.get_amount_label() @@ -538,7 +527,6 @@ func _apply_shop_styles() -> void: %CloseButton, _reel_purchase, _barrier_purchase, - _cooler_purchase, _backpack_purchase, ]: UtilityPageStyleType.apply_ocean_button(button) @@ -559,7 +547,6 @@ func setup( hotbar: PlayerHotbar, inventory_layout: PlayerInventoryLayout, item_catalog: ItemCatalogType, - cooler_capacity: PlayerCoolerCapacityType, art_unlocks: PlayerArtUnlocksType, network_shop: NetworkShopService, network_sale: NetworkSaleService, @@ -576,7 +563,6 @@ func setup( _hotbar = hotbar _inventory_layout = inventory_layout _item_catalog = item_catalog - _cooler_capacity = cooler_capacity _art_unlocks = art_unlocks _network_shop = network_shop _network_sale = network_sale @@ -612,10 +598,6 @@ func setup( _upgrades.upgrades_changed.connect(_on_upgrades_changed) if not _bag.contents_changed.is_connected(_on_bag_changed): _bag.contents_changed.connect(_on_bag_changed) - if not _cooler_capacity.capacity_changed.is_connected( - _on_cooler_capacity_changed - ): - _cooler_capacity.capacity_changed.connect(_on_cooler_capacity_changed) if not _inventory_layout.backpack_capacity_changed.is_connected( _on_backpack_capacity_changed ): @@ -836,7 +818,6 @@ func _refresh_all() -> void: _refresh_wallet() _refresh_upgrades() _refresh_supplies() - _refresh_cooler_capacity() _refresh_backpack_capacity() @@ -1587,41 +1568,6 @@ func _add_supply_icon_tile( return tile_host -func _refresh_cooler_capacity() -> void: - if _cooler_capacity == null: - return - var level: int = _cooler_capacity.get_level() - var cost: int = _cooler_capacity.get_next_cost() - var next_capacity: int = _cooler_capacity.get_next_capacity() - _cooler_purchase.disabled = ( - cost < 0 - or _transaction_in_progress - or _closing - or _network_shop == null - or not _network_shop.can_request_purchase() - or not _cooler_capacity.can_purchase(_wallet) - ) - var cooler_effect: String - if cost < 0: - cooler_effect = "%d slots · maximum level" % ( - _cooler_capacity.get_capacity() - ) - _cooler_price_bubble.hide() - else: - _cooler_price_bubble.show() - cooler_effect = "%d → %d slots" % [ - _cooler_capacity.get_capacity(), - next_capacity, - ] - _cooler_cost.set_amount(cost) - _cooler_purchase.tooltip_text = _upgrade_tooltip( - "storage capacity", - level, - cooler_effect, - ) - _cooler_purchase.accessibility_name = _cooler_purchase.tooltip_text - - func _refresh_backpack_capacity() -> void: if _inventory_layout == null: return @@ -1723,23 +1669,6 @@ func _purchase_art_upgrade(product_id: StringName) -> void: _network_shop.request_art_upgrade(product_id) -func _purchase_cooler_capacity() -> void: - if _transaction_in_progress or not _is_transaction_context_valid(): - _set_feedback("unable to complete purchase.") - return - var cost: int = _cooler_capacity.get_next_cost() - if cost < 0: - _set_feedback("Upgrade is already at maximum.") - return - if not _wallet.can_afford(cost): - _set_feedback("Insufficient funds.") - return - if _network_shop == null: - _set_feedback("Purchase could not be completed.") - return - _network_shop.request_cooler_capacity_upgrade() - - func _purchase_backpack_capacity() -> void: if _transaction_in_progress or not _is_transaction_context_valid(): _set_feedback("unable to complete purchase.") @@ -1860,7 +1789,6 @@ func _on_wallet_changed(_balance: int, _delta: int) -> void: _refresh_wallet() _refresh_upgrades() _refresh_supplies() - _refresh_cooler_capacity() _refresh_backpack_capacity() @@ -1875,10 +1803,6 @@ func _on_bag_changed() -> void: _refresh_supplies() -func _on_cooler_capacity_changed(_level: int, _capacity: int) -> void: - _refresh_cooler_capacity() - - func _on_backpack_capacity_changed(_level: int, _capacity: int) -> void: _refresh_backpack_capacity() diff --git a/ui/fishing_shop.tscn b/ui/fishing_shop.tscn index 70ccec1..66fcbd9 100644 --- a/ui/fishing_shop.tscn +++ b/ui/fishing_shop.tscn @@ -257,35 +257,6 @@ layout_mode = 2 amount = 100 icon_size = 24.0 -[node name="CoolerTile" type="Control" parent="ShopPanel/Margin/Layout/Body/Upgrades/UpgradeScroll/UpgradeGrid"] -custom_minimum_size = Vector2(144, 168) -layout_mode = 2 -mouse_filter = 2 - -[node name="CoolerPurchase" type="Button" parent="ShopPanel/Margin/Layout/Body/Upgrades/UpgradeScroll/UpgradeGrid/CoolerTile"] -unique_name_in_owner = true -offset_right = 144.0 -offset_bottom = 144.0 -tooltip_text = "storage capacity" -icon = ExtResource("7_close") -expand_icon = true -icon_max_width = 92 - -[node name="CoolerPriceBubble" type="PanelContainer" parent="ShopPanel/Margin/Layout/Body/Upgrades/UpgradeScroll/UpgradeGrid/CoolerTile"] -unique_name_in_owner = true -z_index = 2 -offset_left = 22.0 -offset_top = 128.0 -offset_right = 122.0 -offset_bottom = 160.0 -mouse_filter = 2 - -[node name="CoolerCost" parent="ShopPanel/Margin/Layout/Body/Upgrades/UpgradeScroll/UpgradeGrid/CoolerTile/CoolerPriceBubble" instance=ExtResource("8_currency")] -unique_name_in_owner = true -layout_mode = 2 -amount = 75 -icon_size = 24.0 - [node name="BackpackTile" type="Control" parent="ShopPanel/Margin/Layout/Body/Upgrades/UpgradeScroll/UpgradeGrid"] custom_minimum_size = Vector2(144, 168) layout_mode = 2 diff --git a/ui/game_ui.gd b/ui/game_ui.gd index 585efc9..55a07eb 100644 --- a/ui/game_ui.gd +++ b/ui/game_ui.gd @@ -21,6 +21,7 @@ const PauseMenuType = preload("res://ui/pause_menu.gd") const NetworkSessionType = preload("res://network/network_session.gd") const FishingShopType = preload("res://ui/fishing_shop.gd") const DecorShopType = preload("res://ui/decor_shop.gd") +const RVUpgradeShopType = preload("res://ui/rv_upgrade_shop.gd") const SettingsPanelType = preload("res://ui/settings_panel.gd") const PlayerFishingUpgradesType = preload( "res://progression/player_fishing_upgrades.gd" @@ -31,6 +32,9 @@ const ShopInteractionType = preload( const DecorShopInteractionType = preload( "res://world/decor_shop_interaction.gd" ) +const RVUpgradeInteractionType = preload( + "res://world/rv_upgrade_interaction.gd" +) const PlayerStorageType = preload("res://ui/player_storage.gd") const HomeDecorToolbarType = preload("res://ui/home_decor_toolbar.gd") const PlayerStorageInteractionType = preload( @@ -129,6 +133,7 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0 @onready var _barrier_health: Label = %BarrierHealth @onready var _showcase_details: Label = %ShowcaseDetails @onready var _fishing_panel: PanelContainer = %FishingPanel +@onready var _fishing_danger_vignette: ColorRect = %FishingDangerVignette @onready var _experience_panel: PanelContainer = %ExperienceProgressPanel @onready var _experience_level_label: Label = %ExperienceLevelLabel @onready var _experience_award_label: Label = %ExperienceAwardLabel @@ -144,6 +149,8 @@ const SHOP_ANIMALESE_VOICE_ID: String = "natural" const SHOP_ANIMALESE_BASE_PITCH: float = 1.08 const SHOP_SPEECH_CHARACTERS_PER_SECOND: float = 28.0 const SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS: int = 5000 +const FISHING_DANGER_START_GAP: float = 0.15 +const FISHING_DANGER_FULL_GAP: float = 0.025 @onready var _canonical_stage: Control = %CanonicalStage @@ -155,6 +162,7 @@ const SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS: int = 5000 @onready var _hotbar_ui: HotbarUIType = %Hotbar @onready var _fishing_shop: FishingShopType = %FishingShop @onready var _decor_shop: DecorShopType = %DecorShop +@onready var _rv_upgrade_shop: RVUpgradeShopType = %RVUpgradeShop @onready var _player_storage: PlayerStorageType = %PlayerStorage @onready var _home_decor_toolbar: HomeDecorToolbarType = %HomeDecorToolbar @onready var _rv_storage_button: Button = %RVStorageButton @@ -208,6 +216,7 @@ var _player_menu_hotbar_visible: bool = false var _main_shop_buyer: FishBuyerProfileType var _shop_interaction: ShopInteractionType var _decor_shop_interaction: DecorShopInteractionType +var _rv_upgrade_shop_interaction: RVUpgradeInteractionType var _storage_interaction: PlayerStorageInteractionType var _surface_drawing: NetworkSurfaceDrawingService var _surface_drawing_hotbar_selected: bool = false @@ -235,6 +244,12 @@ var _controller_text_entry_is_open: Callable var _controller_text_entry_close: Callable var _restore_chat_keyboard_after_fishing: bool = false var _rv_storage_button_requested_visible: bool = false +var _previous_barrier_health := PackedInt32Array() +var _barrier_feedback_initialized: bool = false +var _fishing_danger_target: float = 0.0 +var _fishing_danger_intensity: float = 0.0 +var _fishing_danger_pulse_time: float = 0.0 +var _catch_track_shake_tween: Tween func _ready() -> void: @@ -363,6 +378,7 @@ func setup( shop_interaction: ShopInteractionType, storage_interaction: PlayerStorageInteractionType, decor_shop_interaction: DecorShopInteractionType, + rv_upgrade_shop_interaction: RVUpgradeInteractionType, item_effects: PlayerItemEffectsType, cooler_capacity: PlayerCoolerCapacityType, network_session: NetworkSessionType, @@ -506,7 +522,6 @@ func setup( hotbar, inventory_layout, item_catalog, - cooler_capacity, art_unlocks, network_shop_service, network_sale_service, @@ -521,6 +536,14 @@ func setup( home_state, network_shop_service, ) + _rv_upgrade_shop.setup( + player, + wallet, + fishing_spot, + rv_upgrade_shop_interaction, + home_state, + network_shop_service, + ) _player_storage.setup( player, fishing_spot, @@ -538,6 +561,8 @@ func setup( _fishing_shop.menu_exit_started.connect(_on_shop_exit_started) _decor_shop.menu_visibility_changed.connect(_on_shop_visibility_changed) _decor_shop.menu_exit_started.connect(_on_shop_exit_started) + _rv_upgrade_shop.menu_visibility_changed.connect(_on_shop_visibility_changed) + _rv_upgrade_shop.menu_exit_started.connect(_on_shop_exit_started) _fishing_shop.sell_fish_requested.connect(_on_shop_sell_fish_requested) _fishing_shop.shop_cooler_return_requested.connect( _on_shop_cooler_return_requested @@ -548,6 +573,7 @@ func setup( _main_shop_buyer = main_shop_buyer _shop_interaction = shop_interaction _decor_shop_interaction = decor_shop_interaction + _rv_upgrade_shop_interaction = rv_upgrade_shop_interaction _storage_interaction = storage_interaction _surface_drawing = surface_drawing if ( @@ -571,13 +597,16 @@ func set_world_interactions( shop_interaction: ShopInteractionType, storage_interaction: PlayerStorageInteractionType, decor_shop_interaction: DecorShopInteractionType, + rv_upgrade_shop_interaction: RVUpgradeInteractionType, ) -> void: _shop_interaction = shop_interaction _storage_interaction = storage_interaction _decor_shop_interaction = decor_shop_interaction + _rv_upgrade_shop_interaction = rv_upgrade_shop_interaction _fishing_shop.set_world_interaction(shop_interaction) _player_storage.set_world_interaction(storage_interaction) _decor_shop.set_world_interaction(decor_shop_interaction) + _rv_upgrade_shop.set_world_interaction(rv_upgrade_shop_interaction) func _prioritize_surface_drawing_pointer_input() -> void: @@ -1539,6 +1568,13 @@ func _process(delta: float) -> void: _update_virtual_mouse(delta) _update_controller_menu_scroll(delta) _update_experience_bubble_position() + _update_fishing_danger_vignette(delta) + _try_start_shop_npc_speech() + if _player != null: + _player.set_fishing_reel_camera_active( + _fishing_spot != null + and _fishing_spot.is_reel_input_active() + ) func _update_controller_menu_scroll(delta: float) -> void: @@ -1793,6 +1829,7 @@ func set_gameplay_ui_enabled(enabled: bool) -> void: close_player_menu_for_session_end() _fishing_shop.close_for_session_end() _decor_shop.close_for_session_end() + _rv_upgrade_shop.close_for_session_end() _player_storage.close_for_session_end() _fishing_panel.visible = false _shop_prompt.hide() @@ -1933,6 +1970,10 @@ func get_decor_shop() -> DecorShopType: return _decor_shop +func get_rv_upgrade_shop() -> RVUpgradeShopType: + return _rv_upgrade_shop + + func get_player_storage() -> PlayerStorageType: return _player_storage @@ -2027,8 +2068,19 @@ func set_shop_prompt_visible( _position_shop_prompt(world_anchor) -func set_shop_npc_player_in_range(in_range: bool) -> void: - if _shop_npc_player_in_range == in_range: +func set_shop_npc_player_in_range( + in_range: bool, + dialogue_text: String = "", +) -> void: + var dialogue_changed: bool = ( + not dialogue_text.is_empty() + and _shop_prompt_message.text != dialogue_text + ) + if dialogue_changed: + _shop_prompt_message.text = dialogue_text + _shop_prompt_message.visible_characters = -1 + _shop_npc_spoken_for_current_visit = false + if _shop_npc_player_in_range == in_range and not dialogue_changed: return _shop_npc_player_in_range = in_range if not in_range: @@ -2044,10 +2096,10 @@ func _try_start_shop_npc_speech() -> void: or not _gameplay_ui_enabled ): return - _shop_npc_spoken_for_current_visit = true var now_msec: int = Time.get_ticks_msec() if now_msec < _shop_npc_next_speech_msec: return + _shop_npc_spoken_for_current_visit = true _shop_npc_next_speech_msec = ( now_msec + SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS ) @@ -2310,6 +2362,12 @@ func _on_catch_display_changed( and _fishing_spot != null and _fishing_spot.is_fighting() ) + _update_fishing_feedback( + progress, + chase_progress, + barrier_health, + encounter_visible, + ) _green_catch_progress.value = progress * 100.0 _red_chase_progress.value = maxf(chase_progress, 0.0) * 100.0 _catch_track.visible = encounter_visible @@ -2346,6 +2404,93 @@ func _on_catch_display_changed( _refresh_fishing_panel_visibility() +func _update_fishing_feedback( + progress: float, + chase_progress: float, + barrier_health: PackedInt32Array, + encounter_visible: bool, +) -> void: + if not encounter_visible: + _previous_barrier_health.clear() + _barrier_feedback_initialized = false + _fishing_danger_target = 0.0 + return + if _barrier_feedback_initialized: + var comparison_count: int = mini( + _previous_barrier_health.size(), + barrier_health.size(), + ) + var barrier_hit: bool = false + var barrier_broken: bool = false + for barrier_index: int in range(comparison_count): + if ( + barrier_health[barrier_index] + >= _previous_barrier_health[barrier_index] + ): + continue + barrier_hit = true + barrier_broken = ( + barrier_broken + or barrier_health[barrier_index] <= 0 + ) + if barrier_hit: + _play_barrier_feedback(barrier_broken) + _previous_barrier_health = barrier_health.duplicate() + _barrier_feedback_initialized = true + var chase_gap: float = progress - maxf(chase_progress, 0.0) + _fishing_danger_target = clampf( + inverse_lerp( + FISHING_DANGER_START_GAP, + FISHING_DANGER_FULL_GAP, + chase_gap, + ), + 0.0, + 1.0, + ) + + +func _play_barrier_feedback(barrier_broken: bool) -> void: + if _player != null: + _player.play_fishing_barrier_camera_feedback(barrier_broken) + if _catch_track_shake_tween != null: + _catch_track_shake_tween.kill() + _catch_track.rotation = 0.0 + var tilt: float = 0.018 if barrier_broken else 0.008 + var beat: float = 0.038 if barrier_broken else 0.028 + _catch_track_shake_tween = create_tween() + _catch_track_shake_tween.tween_property( + _catch_track, "rotation", -tilt, beat + ) + _catch_track_shake_tween.tween_property( + _catch_track, "rotation", tilt, beat + ) + _catch_track_shake_tween.tween_property( + _catch_track, "rotation", -tilt * 0.45, beat + ) + _catch_track_shake_tween.tween_property( + _catch_track, "rotation", 0.0, beat + ) + + +func _update_fishing_danger_vignette(delta: float) -> void: + _fishing_danger_pulse_time += delta + _fishing_danger_intensity = lerpf( + _fishing_danger_intensity, + _fishing_danger_target, + 1.0 - exp(-8.0 * delta), + ) + var pulse: float = ( + 0.88 + sin(_fishing_danger_pulse_time * 5.5) * 0.12 + ) + var shown_intensity: float = _fishing_danger_intensity * pulse + _fishing_danger_vignette.visible = shown_intensity > 0.01 + var vignette_material := ( + _fishing_danger_vignette.material as ShaderMaterial + ) + if vignette_material != null: + vignette_material.set_shader_parameter("intensity", shown_intensity) + + func _update_barrier_markers( positions: PackedFloat32Array, health: PackedInt32Array, diff --git a/ui/game_ui.tscn b/ui/game_ui.tscn index c219c84..c5dea31 100644 --- a/ui/game_ui.tscn +++ b/ui/game_ui.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=3] +[gd_scene load_steps=27 format=3] [ext_resource type="Script" path="res://ui/game_ui.gd" id="1_ui"] [ext_resource type="PackedScene" path="res://ui/player_menu.tscn" id="2_menu"] @@ -17,6 +17,11 @@ [ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_confirmation_page.tscn" id="15_social_prompt"] [ext_resource type="PackedScene" path="res://ui/decor_shop.tscn" id="16_decor_shop"] [ext_resource type="PackedScene" path="res://ui/home_decor_toolbar.tscn" id="17_decor_toolbar"] +[ext_resource type="PackedScene" path="res://ui/rv_upgrade_shop.tscn" id="18_rv_upgrade_shop"] +[ext_resource type="Shader" path="res://ui/fishing_danger_vignette.gdshader" id="19_fishing_vignette"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_fishing_vignette"] +shader = ExtResource("19_fishing_vignette") [sub_resource type="StyleBoxFlat" id="StyleBox_chase_background"] bg_color = Color(0.032, 0.118, 0.15, 1) @@ -86,6 +91,20 @@ grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 +[node name="FishingDangerVignette" type="ColorRect" parent="UIRoot/CanonicalStage/GameplayTransientHUD"] +unique_name_in_owner = true +visible = false +z_index = 50 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +material = SubResource("ShaderMaterial_fishing_vignette") +color = Color(1, 1, 1, 1) + [node name="ActiveBaitIndicator" type="Control" parent="UIRoot/CanonicalStage/GameplayTransientHUD"] unique_name_in_owner = true z_index = 54 @@ -312,6 +331,7 @@ offset_right = 420.0 offset_bottom = -124.0 grow_horizontal = 2 grow_vertical = 0 +pivot_offset = Vector2(420, 18) mouse_filter = 2 [node name="GreenCatchProgress" type="ProgressBar" parent="UIRoot/CanonicalStage/GameplayTransientHUD/CatchTrack"] @@ -440,7 +460,7 @@ theme_override_constants/margin_bottom = 8 unique_name_in_owner = true layout_mode = 2 theme_override_font_sizes/font_size = 18 -text = "Hey, if you've got any fish I've got cash! OwO" +text = "Listen, you may suck at fishing but I've got some things that might help." horizontal_alignment = 1 vertical_alignment = 1 autowrap_mode = 2 @@ -477,6 +497,9 @@ unique_name_in_owner = true [node name="DecorShop" parent="UIRoot/CanonicalStage" instance=ExtResource("16_decor_shop")] unique_name_in_owner = true +[node name="RVUpgradeShop" parent="UIRoot/CanonicalStage" instance=ExtResource("18_rv_upgrade_shop")] +unique_name_in_owner = true + [node name="HomeDecorToolbar" parent="UIRoot/CanonicalStage" instance=ExtResource("17_decor_toolbar")] unique_name_in_owner = true diff --git a/ui/home_decor_toolbar.gd b/ui/home_decor_toolbar.gd index 6f73219..50ae444 100644 --- a/ui/home_decor_toolbar.gd +++ b/ui/home_decor_toolbar.gd @@ -10,7 +10,10 @@ var _mode_button: Button var _selection_label: Label var _rotate_button: Button var _store_button: Button +var _clear_button: Button var _mode: PlayerHomeState.PlacementMode = PlayerHomeState.PlacementMode.GRID +var _interactive: bool = true +var _selection_active: bool = false func _ready() -> void: @@ -22,31 +25,33 @@ func set_active(active: bool) -> void: if visible == active: return visible = active - if active and _mode_button != null: - _mode_button.call_deferred("grab_focus") + + +func set_interactive(interactive: bool) -> void: + _interactive = interactive + _refresh_button_interactivity() func set_mode(mode: PlayerHomeState.PlacementMode) -> void: _mode = mode if _mode_button != null: _mode_button.text = ( - "placement: grid" + "grid" if mode == PlayerHomeState.PlacementMode.GRID - else "placement: free" + else "free" ) + _mode_button.tooltip_text = "placement mode: %s" % _mode_button.text func set_selection(instance_id: String, display_name: String = "") -> void: var selected: bool = not instance_id.is_empty() + _selection_active = selected if _selection_label != null: _selection_label.text = ( "selected: %s" % display_name - if selected else "click decor to select; drag to move" + if selected else "use held decor to place; click or drag to edit" ) - if _rotate_button != null: - _rotate_button.disabled = not selected - if _store_button != null: - _store_button.disabled = not selected + _refresh_button_interactivity() func report_status(message: String) -> void: @@ -55,65 +60,92 @@ func report_status(message: String) -> void: func _build_ui() -> void: - custom_minimum_size = Vector2(330.0, 0.0) - position = Vector2(925.0, 540.0) - z_index = 58 + set_anchors_preset(Control.PRESET_TOP_RIGHT) + offset_left = -500.0 + offset_top = 0.0 + offset_right = 0.0 + offset_bottom = 106.0 + custom_minimum_size = Vector2(500.0, 0.0) + z_index = 85 mouse_filter = Control.MOUSE_FILTER_STOP - add_theme_stylebox_override( - "panel", - UtilityPageStyle.rounded_style( - Color(UtilityPageStyle.OCEAN_PANEL_DEEP, 0.96), 16 - ), - ) + var panel_style: StyleBoxFlat = UtilityPageStyle.panel_style() + panel_style.set_corner_radius_all(10) + panel_style.content_margin_left = 6.0 + panel_style.content_margin_top = 6.0 + panel_style.content_margin_right = 6.0 + panel_style.content_margin_bottom = 6.0 + add_theme_stylebox_override("panel", panel_style) var margin := MarginContainer.new() for side: StringName in [ &"margin_left", &"margin_top", &"margin_right", &"margin_bottom", ]: - margin.add_theme_constant_override(side, 12) + margin.add_theme_constant_override(side, 6) add_child(margin) var layout := VBoxContainer.new() - layout.add_theme_constant_override("separation", 8) + layout.add_theme_constant_override("separation", 5) margin.add_child(layout) - var title := Label.new() - title.text = "RV decor" - title.add_theme_font_size_override("font_size", 24) - layout.add_child(title) - _selection_label = Label.new() - _selection_label.text = "click decor to select; drag to move" - _selection_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - _selection_label.add_theme_font_size_override("font_size", 17) - layout.add_child(_selection_label) var row := HBoxContainer.new() - row.add_theme_constant_override("separation", 8) + row.add_theme_constant_override("separation", 5) layout.add_child(row) - _mode_button = Button.new() - _mode_button.text = "placement: grid" - _mode_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL - UtilityPageStyle.apply_ocean_button(_mode_button) + var title := Label.new() + title.text = "decor" + title.custom_minimum_size = Vector2(70.0, 46.0) + title.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + title.add_theme_font_size_override("font_size", 19) + row.add_child(title) + _mode_button = _add_tool_button(row, "grid", "switch placement mode", 82.0) _mode_button.pressed.connect(_toggle_mode) - row.add_child(_mode_button) - _rotate_button = Button.new() - _rotate_button.text = "rotate" - _rotate_button.disabled = true - UtilityPageStyle.apply_ocean_button(_rotate_button) + _rotate_button = _add_tool_button(row, "rotate", "rotate selected decor", 92.0) _rotate_button.pressed.connect(rotate_requested.emit) - row.add_child(_rotate_button) - var action_row := HBoxContainer.new() - action_row.add_theme_constant_override("separation", 8) - layout.add_child(action_row) - _store_button = Button.new() - _store_button.text = "pack up" - _store_button.disabled = true - _store_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL - UtilityPageStyle.apply_ocean_button(_store_button) + _store_button = _add_tool_button(row, "pack", "pack selected decor", 82.0) _store_button.pressed.connect(store_requested.emit) - action_row.add_child(_store_button) - var cancel_button := Button.new() - cancel_button.text = "clear selection" - cancel_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL - UtilityPageStyle.apply_ocean_button(cancel_button) - cancel_button.pressed.connect(cancel_requested.emit) - action_row.add_child(cancel_button) + _clear_button = _add_tool_button(row, "clear", "clear selection", 82.0) + _clear_button.pressed.connect(cancel_requested.emit) + _selection_label = Label.new() + _selection_label.text = "use held decor to place; click or drag to edit" + _selection_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _selection_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _selection_label.add_theme_font_size_override("font_size", 15) + layout.add_child(_selection_label) + _refresh_button_interactivity() + + +func _add_tool_button( + parent: Container, + button_text: String, + button_tooltip: String, + minimum_width: float, +) -> Button: + var button := Button.new() + button.text = button_text + button.tooltip_text = button_tooltip + button.accessibility_name = button_tooltip + button.custom_minimum_size = Vector2(minimum_width, 46.0) + button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + UtilityPageStyle.apply_ocean_button(button) + for style_name: StringName in [ + &"normal", &"hover", &"pressed", &"focus", &"disabled", + ]: + var existing: StyleBox = button.get_theme_stylebox(style_name) + var rounded := existing.duplicate() as StyleBoxFlat + if rounded == null: + continue + rounded.set_corner_radius_all(20) + button.add_theme_stylebox_override(style_name, rounded) + parent.add_child(button) + return button + + +func _refresh_button_interactivity() -> void: + if _mode_button != null: + _mode_button.disabled = not _interactive + if _rotate_button != null: + _rotate_button.disabled = not _interactive or not _selection_active + if _store_button != null: + _store_button.disabled = not _interactive or not _selection_active + if _clear_button != null: + _clear_button.disabled = not _interactive or not _selection_active func _toggle_mode() -> void: diff --git a/ui/player_menu.gd b/ui/player_menu.gd index 9b15913..95263f5 100644 --- a/ui/player_menu.gd +++ b/ui/player_menu.gd @@ -2575,7 +2575,10 @@ func _on_tackle_button_gui_input( call_deferred("_release_pointer_focus", button) if ( mouse_event == null - or mouse_event.button_index != MOUSE_BUTTON_RIGHT + or mouse_event.button_index not in [ + MOUSE_BUTTON_LEFT, + MOUSE_BUTTON_RIGHT, + ] or not mouse_event.pressed ): return diff --git a/ui/player_storage.gd b/ui/player_storage.gd index 83817c5..e5369a4 100644 --- a/ui/player_storage.gd +++ b/ui/player_storage.gd @@ -105,7 +105,7 @@ func _open_storage( ): return false _home_access = home_access - _title.text = "RV storage" if home_access else "private storage" + _title.text = "home storage" if home_access else "private storage" _decorate_button.visible = home_access and allow_decorating _prior_movement_enabled = _player.is_movement_enabled() _prior_camera_enabled = _player.is_camera_input_enabled() @@ -290,8 +290,8 @@ func _build_ui() -> void: _title.size_flags_horizontal = Control.SIZE_EXPAND_FILL header.add_child(_title) _decorate_button = Button.new() - _decorate_button.text = "decorate RV" - _decorate_button.tooltip_text = "Place decor inside your RV" + _decorate_button.text = "decorate home" + _decorate_button.tooltip_text = "Place decor inside your home" _decorate_button.custom_minimum_size = Vector2(160.0, 48.0) UtilityPageStyle.apply_ocean_button(_decorate_button) _decorate_button.hide() diff --git a/ui/rv_upgrade_shop.gd b/ui/rv_upgrade_shop.gd new file mode 100644 index 0000000..11c0a4d --- /dev/null +++ b/ui/rv_upgrade_shop.gd @@ -0,0 +1,330 @@ +class_name RVUpgradeShop +extends Control + +const INPUT_OWNER: StringName = &"rv_upgrade_shop" +const UtilityPageStyleType = preload("res://ui/utility_page_style.gd") +const CurrencyPresentationType = preload("res://ui/currency_presentation.gd") + +signal menu_visibility_changed(is_open: bool) +signal menu_exit_started + +var _player: Player +var _wallet: PlayerWallet +var _fishing_spot: FishingSpot +var _interaction: RVUpgradeInteraction +var _home_state: PlayerHomeState +var _network_shop: NetworkShopService +var _wallet_amount: CurrencyAmount +var _price_amount: CurrencyAmount +var _home_label: Label +var _storage_label: Label +var _feedback: Label +var _upgrade_button: Button +var _close_button: Button +var _transaction_pending: bool = false +var _prior_movement_enabled: bool = true +var _prior_camera_enabled: bool = true +var _prior_mouse_mode: Input.MouseMode = Input.MOUSE_MODE_VISIBLE + + +func _ready() -> void: + UtilityPageStyleType.apply_page(self) + _build_ui() + hide() + + +func setup( + player: Player, + wallet: PlayerWallet, + fishing_spot: FishingSpot, + interaction: RVUpgradeInteraction, + home_state: PlayerHomeState, + network_shop: NetworkShopService, +) -> void: + _player = player + _wallet = wallet + _fishing_spot = fishing_spot + _interaction = interaction + _home_state = home_state + _network_shop = network_shop + if not _wallet.balance_changed.is_connected(_on_wallet_changed): + _wallet.balance_changed.connect(_on_wallet_changed) + if not _home_state.changed.is_connected(_refresh): + _home_state.changed.connect(_refresh) + if ( + _network_shop != null + and not _network_shop.local_purchase_pending.is_connected( + _on_purchase_pending + ) + ): + _network_shop.local_purchase_pending.connect(_on_purchase_pending) + _network_shop.local_purchase_finished.connect(_on_purchase_finished) + _refresh() + + +func set_world_interaction(interaction: RVUpgradeInteraction) -> void: + _interaction = interaction + + +func open_shop() -> bool: + if ( + visible + or _player == null + or _wallet == null + or _fishing_spot == null + or _interaction == null + or not _interaction.is_local_player_in_range() + or not _fishing_spot.can_open_fishing_shop() + ): + return false + _prior_movement_enabled = _player.is_movement_enabled() + _prior_camera_enabled = _player.is_camera_input_enabled() + _player.set_movement_enabled(false) + _player.set_camera_input_enabled(false) + _prior_mouse_mode = _restorable_mouse_mode(Input.mouse_mode) + _fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, true) + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + _transaction_pending = ( + _network_shop != null + and _network_shop.is_local_purchase_pending() + ) + _feedback.text = "" + _refresh() + show() + _upgrade_button.call_deferred("grab_focus") + menu_visibility_changed.emit(true) + return true + + +func close_shop(restore_controls: bool = true) -> void: + if not visible: + return + menu_exit_started.emit() + get_viewport().gui_release_focus() + hide() + if _fishing_spot != null: + _fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, false) + if restore_controls and _player != null: + _player.set_movement_enabled(_prior_movement_enabled) + _player.set_camera_input_enabled(_prior_camera_enabled) + Input.mouse_mode = _prior_mouse_mode + menu_visibility_changed.emit(false) + + +func consume_escape() -> bool: + if not visible: + return false + close_shop() + return true + + +func close_for_range_exit() -> void: + close_shop() + + +func close_for_water_recovery() -> void: + close_shop(false) + + +func close_for_session_end() -> void: + close_shop(false) + + +func _unhandled_input(event: InputEvent) -> void: + if not visible or not event.is_action_pressed("ui_cancel"): + return + close_shop() + get_viewport().set_input_as_handled() + + +func _purchase_upgrade() -> void: + if _network_shop == null or _transaction_pending: + return + var request_id: String = _network_shop.request_home_upgrade() + if request_id.is_empty(): + _refresh() + + +func _on_purchase_pending(_request_id: String) -> void: + _transaction_pending = true + _feedback.text = "upgrading…" + _refresh() + + +func _on_purchase_finished( + _request_id: String, + accepted: bool, + message: String, + product_id: StringName, + category: int, + _quantity: int, + _total_cost: int, +) -> void: + if ( + category != NetworkShopProtocol.ProductCategory.HOME_UPGRADE + or product_id != NetworkShopService.HOME_UPGRADE_PRODUCT_ID + ): + return + _transaction_pending = false + _feedback.text = "starter RV unlocked" if accepted else message.to_lower() + _refresh() + + +func _on_wallet_changed(_balance: int, _delta: int) -> void: + _refresh() + + +func _refresh() -> void: + if _wallet_amount == null: + return + var balance: int = _wallet.get_balance() if _wallet != null else 0 + var tier: int = _home_state.get_tier() if _home_state != null else 0 + var current_capacity: int = ( + _home_state.get_storage_capacity() if _home_state != null else 9 + ) + var next_capacity: int = ( + _home_state.get_next_storage_capacity() if _home_state != null else -1 + ) + var cost: int = ( + _home_state.get_next_upgrade_cost() if _home_state != null else -1 + ) + _wallet_amount.set_amount(balance) + _price_amount.set_amount(maxi(cost, 0)) + if tier >= PlayerHomeState.MAX_TIER: + _home_label.text = "starter RV" + _storage_label.text = "storage · %d slots" % current_capacity + _upgrade_button.text = "unlocked" + _upgrade_button.disabled = true + _price_amount.visible = false + else: + _home_label.text = "tent → starter RV" + _storage_label.text = "storage · %d → %d slots" % [ + current_capacity, next_capacity, + ] + _upgrade_button.text = "upgrade" + _upgrade_button.disabled = ( + _transaction_pending + or _wallet == null + or not _wallet.can_afford(cost) + or _network_shop == null + or not _network_shop.can_request_home_upgrade() + ) + _price_amount.visible = true + + +func _restorable_mouse_mode(mouse_mode: Input.MouseMode) -> Input.MouseMode: + return ( + Input.MOUSE_MODE_VISIBLE + if mouse_mode == Input.MOUSE_MODE_CAPTURED + else mouse_mode + ) + + +func _build_ui() -> void: + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + z_index = 83 + mouse_filter = Control.MOUSE_FILTER_STOP + var blocker := ColorRect.new() + blocker.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + blocker.color = Color(0.02, 0.08, 0.10, 0.55) + blocker.mouse_filter = Control.MOUSE_FILTER_STOP + add_child(blocker) + + var panel := PanelContainer.new() + panel.set_anchors_preset(Control.PRESET_CENTER) + panel.position = Vector2(-390.0, -225.0) + panel.size = Vector2(780.0, 450.0) + panel.add_theme_stylebox_override( + "panel", + UtilityPageStyleType.rounded_style( + UtilityPageStyleType.OCEAN_PANEL_DEEP, 24 + ), + ) + add_child(panel) + var margin := MarginContainer.new() + for side: StringName in [ + &"margin_left", &"margin_top", &"margin_right", &"margin_bottom", + ]: + margin.add_theme_constant_override(side, 28) + panel.add_child(margin) + var layout := VBoxContainer.new() + layout.add_theme_constant_override("separation", 18) + margin.add_child(layout) + + var header := HBoxContainer.new() + header.add_theme_constant_override("separation", 12) + layout.add_child(header) + var title := Label.new() + title.text = "home upgrades" + title.add_theme_font_size_override("font_size", 38) + title.size_flags_horizontal = Control.SIZE_EXPAND_FILL + header.add_child(title) + _wallet_amount = CurrencyPresentationType.instantiate_amount(0, 24.0) + header.add_child(_wallet_amount) + + var offer := PanelContainer.new() + offer.size_flags_vertical = Control.SIZE_EXPAND_FILL + offer.add_theme_stylebox_override( + "panel", + UtilityPageStyleType.rounded_style( + UtilityPageStyleType.OCEAN_FIELD, 18 + ), + ) + layout.add_child(offer) + var offer_margin := MarginContainer.new() + for side: StringName in [ + &"margin_left", &"margin_top", &"margin_right", &"margin_bottom", + ]: + offer_margin.add_theme_constant_override(side, 28) + offer.add_child(offer_margin) + var details := VBoxContainer.new() + details.alignment = BoxContainer.ALIGNMENT_CENTER + details.add_theme_constant_override("separation", 14) + offer_margin.add_child(details) + _home_label = Label.new() + _home_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _home_label.add_theme_font_size_override("font_size", 34) + details.add_child(_home_label) + var description := Label.new() + description.text = ( + "A weatherproof home with a larger interior and built-in storage." + ) + description.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + description.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + description.add_theme_font_size_override("font_size", 20) + details.add_child(description) + _storage_label = Label.new() + _storage_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _storage_label.add_theme_font_size_override("font_size", 22) + details.add_child(_storage_label) + var purchase_row := HBoxContainer.new() + purchase_row.alignment = BoxContainer.ALIGNMENT_CENTER + purchase_row.add_theme_constant_override("separation", 10) + details.add_child(purchase_row) + _upgrade_button = Button.new() + _upgrade_button.custom_minimum_size = Vector2(220.0, 60.0) + UtilityPageStyleType.apply_ocean_button(_upgrade_button) + _upgrade_button.pressed.connect(_purchase_upgrade) + purchase_row.add_child(_upgrade_button) + _price_amount = CurrencyPresentationType.instantiate_amount(0, 24.0) + purchase_row.add_child(_price_amount) + + var footer := HBoxContainer.new() + footer.add_theme_constant_override("separation", 12) + layout.add_child(footer) + _feedback = Label.new() + _feedback.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _feedback.add_theme_font_size_override("font_size", 18) + footer.add_child(_feedback) + _close_button = Button.new() + _close_button.text = "close" + _close_button.custom_minimum_size = Vector2(150.0, 50.0) + UtilityPageStyleType.apply_ocean_button(_close_button) + _close_button.pressed.connect(close_shop) + footer.add_child(_close_button) + _upgrade_button.focus_neighbor_bottom = _upgrade_button.get_path_to( + _close_button + ) + _close_button.focus_neighbor_top = _close_button.get_path_to( + _upgrade_button + ) diff --git a/ui/rv_upgrade_shop.gd.uid b/ui/rv_upgrade_shop.gd.uid new file mode 100644 index 0000000..ddd043e --- /dev/null +++ b/ui/rv_upgrade_shop.gd.uid @@ -0,0 +1 @@ +uid://b5pnsuph7fxrd diff --git a/ui/rv_upgrade_shop.tscn b/ui/rv_upgrade_shop.tscn new file mode 100644 index 0000000..22abf58 --- /dev/null +++ b/ui/rv_upgrade_shop.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://ui/rv_upgrade_shop.gd" id="1_script"] + +[node name="RVUpgradeShop" type="Control"] +unique_name_in_owner = true +visible = false +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_script") diff --git a/world/decor_shop_interaction.gd b/world/decor_shop_interaction.gd index 049bfbe..a325134 100644 --- a/world/decor_shop_interaction.gd +++ b/world/decor_shop_interaction.gd @@ -1,2 +1,10 @@ class_name DecorShopInteraction extends FishingShopInteraction + +const DECOR_DIALOGUE_TEXT: String = ( + "You gonna decorate that hot box or what? I've got some new decor in, take a look." +) + + +func get_dialogue_text(_home_tier: int = -1) -> String: + return DECOR_DIALOGUE_TEXT diff --git a/world/fishing_shop_interaction.gd b/world/fishing_shop_interaction.gd index d912eca..9628ee6 100644 --- a/world/fishing_shop_interaction.gd +++ b/world/fishing_shop_interaction.gd @@ -3,6 +3,10 @@ extends Area3D signal local_player_range_changed(in_range: bool) +const DIALOGUE_TEXT: String = ( + "Listen, you may suck at fishing but I've got some things that might help." +) + @export_node_path("Node3D") var look_character_path: NodePath = ^"../Shopkeeper" var _local_player: Player @@ -37,6 +41,10 @@ func is_avatar_in_range(avatar: Player) -> bool: ) +func get_dialogue_text(_home_tier: int = -1) -> String: + return DIALOGUE_TEXT + + func get_prompt_anchor_position() -> Vector3: if _look_character != null: return _look_character.get_head_anchor_position() diff --git a/world/generation/generated_world_region.gd b/world/generation/generated_world_region.gd index 4e15251..61484fd 100644 --- a/world/generation/generated_world_region.gd +++ b/world/generation/generated_world_region.gd @@ -12,6 +12,9 @@ const PlayerStorageInteractionType = preload( const DecorShopInteractionType = preload( "res://world/decor_shop_interaction.gd" ) +const RVUpgradeInteractionType = preload( + "res://world/rv_upgrade_interaction.gd" +) const PrecipitationOcclusionType = preload( "res://world/environment/precipitation_occlusion.gd" ) @@ -52,6 +55,8 @@ const WATER_RECOVERY_FOOTPRINT_RADIUS := 0.6 const WATER_RECOVERY_INSET_STEP := 0.25 const WATER_RECOVERY_MAXIMUM_INSET := 1.5 const WATER_RECOVERY_SEARCH_EXPANSIONS: Array[float] = [1.5, 4.0, 12.0] +const HOME_GROUND_HEIGHT_TOLERANCE := 0.5 +const HOME_ELEVATION_HEIGHT_TOLERANCE := 0.6 const PROP_SURFACE_SAMPLE_DIRECTIONS: Array[Vector2] = [ Vector2(1.0, 0.0), Vector2(0.70710678, 0.70710678), @@ -86,9 +91,13 @@ const PROCEDURAL_PROP_GROUPS: Array[StringName] = [ @onready var _decor_shop: DecorShopInteractionType = ( $Interactables/DecorShopWorld/InteractionArea ) +@onready var _rv_upgrade_shop: RVUpgradeInteractionType = ( + $Interactables/RVUpgradeShopWorld/InteractionArea +) @onready var _shop_root: Node3D = %FishingShopWorld @onready var _storage_root: Node3D = %PlayerStorageBox @onready var _decor_shop_root: Node3D = %DecorShopWorld +@onready var _rv_upgrade_shop_root: Node3D = %RVUpgradeShopWorld @onready var _decorations: Node3D = %Decorations @onready var _tree_anchors: GatherableAnchorSet3D = %ReachableTreeTrunks @onready var _diggable_beach: DiggableArea3D = %DiggableBeach @@ -104,6 +113,7 @@ var _placed_prop_groups: Array[StringName] = [] var _placed_group_coordinates: Dictionary[StringName, Array] = {} var _biome_assignments: Dictionary[Vector2i, StringName] = {} var _water_recovery_triangles_by_coordinate: Dictionary[Vector2i, Array] = {} +var _home_accessible_elevations_by_coordinate: Dictionary[Vector2i, Array] = {} func _ready() -> void: @@ -159,6 +169,10 @@ func get_decor_shop() -> DecorShopInteractionType: return _decor_shop +func get_rv_upgrade_shop() -> RVUpgradeInteractionType: + return _rv_upgrade_shop + + func get_saltwater_shoreline_mesh() -> MeshInstance3D: return _shoreline_reference @@ -184,6 +198,7 @@ func get_spawn_surface_triangles( material_names: Array[StringName], minimum_global_y: float, minimum_up_dot: float = 0.6, + maximum_global_y: float = 100.0, ) -> Array[PackedVector3Array]: var triangles: Array[PackedVector3Array] = [] if material_names.is_empty(): @@ -204,10 +219,27 @@ func get_spawn_surface_triangles( mesh.surface_get_arrays(surface_index), minimum_global_y, minimum_up_dot, + maximum_global_y, ) return triangles +func is_home_exterior_position_accessible(position: Vector3) -> bool: + var local_position := _generator.to_local(position) + if local_position.y <= HOME_GROUND_HEIGHT_TOLERANCE: + return true + var coordinate := _generator.coordinate_for_local_position(local_position) + for value: Variant in _home_accessible_elevations_by_coordinate.get( + coordinate, + [], + ): + if absf(local_position.y - float(value)) <= ( + HOME_ELEVATION_HEIGHT_TOLERANCE + ): + return true + return false + + func get_water_recovery_position( entry_position: Vector3, fallback_position: Vector3, @@ -242,6 +274,7 @@ func get_water_recovery_position( func _on_generation_completed(summary: Dictionary) -> void: _diggable_beach.invalidate_surface_cache() var records: Array[Dictionary] = _generator.placement_records() + _cache_home_accessible_elevations(records) _assign_biomes(records, summary) var spawn_position := Vector3.ZERO _clear_children(_decorations) @@ -388,6 +421,97 @@ func _on_generation_completed(summary: Dictionary) -> void: world_generated.emit(_current_seed, summary) +func _cache_home_accessible_elevations( + records: Array[Dictionary], +) -> void: + _home_accessible_elevations_by_coordinate.clear() + var records_by_coordinate: Dictionary[Vector2i, Dictionary] = {} + var elevation_tiers: Dictionary[int, bool] = {} + for record: Dictionary in records: + var coordinate: Vector2i = record.get( + "coordinate", + Vector2i(-1, -1), + ) + records_by_coordinate[coordinate] = record + for tier: int in _elevation_tiers_for_tags( + record.get("tags", PackedStringArray()) + ): + elevation_tiers[tier] = true + var visited: Dictionary[String, bool] = {} + for tier: int in elevation_tiers: + var elevation_tag := "elevation_%d" % tier + for coordinate: Vector2i in records_by_coordinate: + var visit_key := _home_elevation_visit_key(coordinate, tier) + if visited.has(visit_key): + continue + var record: Dictionary = records_by_coordinate[coordinate] + var tags: PackedStringArray = record.get( + "tags", + PackedStringArray(), + ) + if elevation_tag not in tags: + continue + var component: Array[Vector2i] = [] + var pending: Array[Vector2i] = [coordinate] + var has_ramp := false + while not pending.is_empty(): + var current: Vector2i = pending.pop_back() + var current_key := _home_elevation_visit_key(current, tier) + if visited.has(current_key): + continue + var current_record: Dictionary = records_by_coordinate.get( + current, + {}, + ) + var current_tags: PackedStringArray = current_record.get( + "tags", + PackedStringArray(), + ) + if elevation_tag not in current_tags: + continue + visited[current_key] = true + component.append(current) + has_ramp = has_ramp or "ramp" in current_tags + for offset: Vector2i in [ + Vector2i.LEFT, + Vector2i.RIGHT, + Vector2i.UP, + Vector2i.DOWN, + ]: + pending.append(current + offset) + if not has_ramp: + continue + var surface_height := ( + float(tier - 1) * _generator.elevated_cliff_level_height + ) + for component_coordinate: Vector2i in component: + var heights: Array = ( + _home_accessible_elevations_by_coordinate.get( + component_coordinate, + [], + ) + ) + heights.append(surface_height) + _home_accessible_elevations_by_coordinate[ + component_coordinate + ] = heights + + +func _elevation_tiers_for_tags(tags: PackedStringArray) -> Array[int]: + var tiers: Array[int] = [] + for tag_value: String in tags: + if not tag_value.begins_with("elevation_"): + continue + var suffix := tag_value.trim_prefix("elevation_") + if suffix.is_valid_int(): + tiers.append(suffix.to_int()) + return tiers + + +func _home_elevation_visit_key(coordinate: Vector2i, tier: int) -> String: + return "%d:%d:%d" % [tier, coordinate.x, coordinate.y] + + func _mark_precipitation_occluders() -> void: for prop: Node in _decorations.get_children(): var prop_group := prop.get_meta(&"terrain_prop_group", &"") as StringName @@ -441,6 +565,8 @@ func _place_spawn_amenities(center: Vector3) -> void: _storage_root.rotation.y = PI * 0.5 _decor_shop_root.position = center + Vector3(-2.4, 0.0, 1.2) _decor_shop_root.rotation.y = PI * 0.5 + _rv_upgrade_shop_root.position = center + Vector3(-2.35, 0.0, -1.35) + _rv_upgrade_shop_root.rotation.y = PI func _configure_static_water() -> void: @@ -1304,6 +1430,7 @@ func _terrain_surface_triangles_by_coordinate( mesh_instance.mesh.surface_get_arrays(surface_index), -INF, 0.35, + 100.0, ) if triangles.is_empty(): continue @@ -1651,6 +1778,7 @@ func _append_surface_triangles( arrays: Array, minimum_global_y: float, minimum_up_dot: float, + maximum_global_y: float, ) -> void: if arrays.size() <= Mesh.ARRAY_INDEX: return @@ -1660,10 +1788,28 @@ func _append_surface_triangles( return if indices.is_empty(): for index: int in range(0, vertices.size() - 2, 3): - _append_triangle(result, mesh_instance, vertices[index], vertices[index + 1], vertices[index + 2], minimum_global_y, minimum_up_dot) + _append_triangle( + result, + mesh_instance, + vertices[index], + vertices[index + 1], + vertices[index + 2], + minimum_global_y, + minimum_up_dot, + maximum_global_y, + ) return for index: int in range(0, indices.size() - 2, 3): - _append_triangle(result, mesh_instance, vertices[indices[index]], vertices[indices[index + 1]], vertices[indices[index + 2]], minimum_global_y, minimum_up_dot) + _append_triangle( + result, + mesh_instance, + vertices[indices[index]], + vertices[indices[index + 1]], + vertices[indices[index + 2]], + minimum_global_y, + minimum_up_dot, + maximum_global_y, + ) func _append_triangle( @@ -1674,11 +1820,15 @@ func _append_triangle( local_c: Vector3, minimum_global_y: float, minimum_up_dot: float, + maximum_global_y: float, ) -> void: var a := mesh_instance.to_global(local_a) var b := mesh_instance.to_global(local_b) var c := mesh_instance.to_global(local_c) - if minf(a.y, minf(b.y, c.y)) <= minimum_global_y: + if ( + maxf(a.y, maxf(b.y, c.y)) <= minimum_global_y + or minf(a.y, minf(b.y, c.y)) >= maximum_global_y + ): return var cross := (b - a).cross(c - a) if cross.length_squared() <= 0.0000001: diff --git a/world/generation/generated_world_region.tscn b/world/generation/generated_world_region.tscn index 04602e1..c996b88 100644 --- a/world/generation/generated_world_region.tscn +++ b/world/generation/generated_world_region.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=15 format=3] +[gd_scene load_steps=16 format=3] [ext_resource type="Script" path="res://world/generation/generated_world_region.gd" id="1_region"] [ext_resource type="Script" path="res://world/generation/terrain_chunk_generator.gd" id="2_generator"] @@ -14,6 +14,7 @@ [ext_resource type="Resource" path="res://world/generation/props/terrain_prop_catalog.tres" id="12_prop_catalog"] [ext_resource type="Resource" path="res://world/generation/biomes/terrain_biome_catalog.tres" id="13_biome_catalog"] [ext_resource type="PackedScene" path="res://world/interactables/decor_shop_world.tscn" id="14_decor_shop"] +[ext_resource type="PackedScene" path="res://world/interactables/rv_upgrade_shop_world.tscn" id="15_rv_upgrade"] [node name="GeneratedWorldRegion" type="Node3D"] script = ExtResource("1_region") @@ -102,6 +103,9 @@ unique_name_in_owner = true [node name="DecorShopWorld" parent="Interactables" instance=ExtResource("14_decor_shop")] unique_name_in_owner = true +[node name="RVUpgradeShopWorld" parent="Interactables" instance=ExtResource("15_rv_upgrade")] +unique_name_in_owner = true + [node name="Decorations" type="Node3D" parent="."] unique_name_in_owner = true diff --git a/world/generation/terrain_chunk_generator.gd b/world/generation/terrain_chunk_generator.gd index 49bf693..64a8bd2 100644 --- a/world/generation/terrain_chunk_generator.gd +++ b/world/generation/terrain_chunk_generator.gd @@ -4414,6 +4414,19 @@ func chunk_position(coordinate: Vector2i) -> Vector3: ) +func coordinate_for_local_position(position: Vector3) -> Vector2i: + if catalog == null or catalog.chunk_size <= 0.0: + return Vector2i(-1, -1) + var half_grid := Vector2( + float(grid_size.x - 1) * 0.5, + float(grid_size.y - 1) * 0.5, + ) + return Vector2i( + roundi(position.x / catalog.chunk_size + half_grid.x), + roundi(position.z / catalog.chunk_size + half_grid.y), + ) + + func get_generated_chunks_root() -> Node3D: return _generated_chunks diff --git a/world/interactables/decor_shop_world.tscn b/world/interactables/decor_shop_world.tscn index 6b735e2..7f94ec4 100644 --- a/world/interactables/decor_shop_world.tscn +++ b/world/interactables/decor_shop_world.tscn @@ -6,19 +6,19 @@ [sub_resource type="SphereShape3D" id="InteractionShape"] resource_local_to_scene = true -radius = 3.0 +radius = 2.1 [node name="DecorShopWorld" type="Node3D"] [node name="Shopkeeper" parent="." instance=ExtResource("2_character")] script = ExtResource("3_display") species_id = "round" -fur_color_id = "orange" -ears_id = "pointy_short" -tail_id = "cat" -eyes_id = "simple_shine" -nose_id = "dog_round" -mouth_id = "three" +fur_color_id = "brown" +ears_id = "bear" +tail_id = "bear" +eyes_id = "tired" +nose_id = "triangle_pink" +mouth_id = "simple_smile" head_look_enabled = true [node name="AnimationPlayer" parent="Shopkeeper"] diff --git a/world/interactables/fishing_shop_world.tscn b/world/interactables/fishing_shop_world.tscn index 760f3b6..040b558 100644 --- a/world/interactables/fishing_shop_world.tscn +++ b/world/interactables/fishing_shop_world.tscn @@ -6,7 +6,7 @@ [sub_resource type="SphereShape3D" id="InteractionShape"] resource_local_to_scene = true -radius = 3.0 +radius = 2.1 [node name="FishingShopWorld" type="Node3D"] diff --git a/world/interactables/rv_upgrade_shop_world.tscn b/world/interactables/rv_upgrade_shop_world.tscn new file mode 100644 index 0000000..9fd0ed2 --- /dev/null +++ b/world/interactables/rv_upgrade_shop_world.tscn @@ -0,0 +1,36 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Script" path="res://world/rv_upgrade_interaction.gd" id="1_shop"] +[ext_resource type="PackedScene" path="res://art/exported/characters/base/straywild_base_character.glb" id="2_character"] +[ext_resource type="Script" path="res://world/world_character_display.gd" id="3_display"] + +[sub_resource type="SphereShape3D" id="InteractionShape"] +resource_local_to_scene = true +radius = 2.1 + +[node name="RVUpgradeShopWorld" type="Node3D"] + +[node name="Shopkeeper" parent="." instance=ExtResource("2_character")] +script = ExtResource("3_display") +species_id = "pointy" +fur_color_id = "teal" +ears_id = "pointy_long" +tail_id = "fox" +eyes_id = "interested" +nose_id = "triangle_small" +mouth_id = "cheeky_smile" +head_look_enabled = true + +[node name="AnimationPlayer" parent="Shopkeeper"] +autoplay = "idle" + +[node name="InteractionArea" type="Area3D" parent="."] +unique_name_in_owner = true +position = Vector3(0, 1, -0.3) +collision_layer = 0 +collision_mask = 2 +script = ExtResource("1_shop") + +[node name="InteractionShape" type="CollisionShape3D" parent="InteractionArea"] +shape = SubResource("InteractionShape") +vertical_icon_alignment = 1 diff --git a/world/regions/starter_island_region.gd b/world/regions/starter_island_region.gd index b418292..c690e4b 100644 --- a/world/regions/starter_island_region.gd +++ b/world/regions/starter_island_region.gd @@ -11,6 +11,9 @@ const PlayerStorageInteractionType = preload( const DecorShopInteractionType = preload( "res://world/decor_shop_interaction.gd" ) +const RVUpgradeInteractionType = preload( + "res://world/rv_upgrade_interaction.gd" +) const FOLIAGE_WIND_SHADER: Shader = preload( "res://world/materials/foliage_wind.gdshader" ) @@ -56,6 +59,10 @@ var player_storage_path: NodePath = ( var decor_shop_path: NodePath = ( ^"Interactables/DecorShopWorld/InteractionArea" ) +@export_node_path("Area3D") +var rv_upgrade_shop_path: NodePath = ( + ^"Interactables/RVUpgradeShopWorld/InteractionArea" +) @export_group("Terrain Collision") # The imported GLB is the collision authority. Rebuild once per region load so # newly authored terrain and props cannot retain a stale saved fallback shape. @@ -95,6 +102,10 @@ func get_decor_shop() -> DecorShopInteractionType: return get_node_or_null(decor_shop_path) as DecorShopInteractionType +func get_rv_upgrade_shop() -> RVUpgradeInteractionType: + return get_node_or_null(rv_upgrade_shop_path) as RVUpgradeInteractionType + + func get_saltwater_shoreline_mesh() -> MeshInstance3D: return get_node_or_null(^"ShorelineRibbons/Ocean") as MeshInstance3D @@ -150,6 +161,7 @@ func get_spawn_surface_triangles( material_names: Array[StringName], minimum_global_y: float, minimum_up_dot: float = 0.6, + maximum_global_y: float = 100.0, ) -> Array[PackedVector3Array]: var triangles: Array[PackedVector3Array] = [] if material_names.is_empty(): @@ -188,6 +200,7 @@ func get_spawn_surface_triangles( vertices[vertex_index + 2], minimum_global_y, minimum_up_dot, + maximum_global_y, ) else: for index_offset: int in range(0, indices.size() - 2, 3): @@ -199,6 +212,7 @@ func get_spawn_surface_triangles( vertices[indices[index_offset + 2]], minimum_global_y, minimum_up_dot, + maximum_global_y, ) return triangles @@ -211,14 +225,14 @@ func _append_spawn_triangle( local_c: Vector3, minimum_global_y: float, minimum_up_dot: float, + maximum_global_y: float, ) -> void: var a: Vector3 = mesh_instance.to_global(local_a) var b: Vector3 = mesh_instance.to_global(local_b) var c: Vector3 = mesh_instance.to_global(local_c) if ( - a.y <= minimum_global_y - or b.y <= minimum_global_y - or c.y <= minimum_global_y + maxf(a.y, maxf(b.y, c.y)) <= minimum_global_y + or minf(a.y, minf(b.y, c.y)) >= maximum_global_y ): return var cross: Vector3 = (b - a).cross(c - a) diff --git a/world/regions/starter_island_region.tscn b/world/regions/starter_island_region.tscn index 9b95dfa..7682491 100644 --- a/world/regions/starter_island_region.tscn +++ b/world/regions/starter_island_region.tscn @@ -19,6 +19,7 @@ [ext_resource type="Script" path="res://world/digging/diggable_area_3d.gd" id="23_diggable_area"] [ext_resource type="Script" path="res://world/gathering/gatherable_anchor_set_3d.gd" id="24_gatherable_anchors"] [ext_resource type="PackedScene" path="res://world/interactables/decor_shop_world.tscn" id="25_decor_shop"] +[ext_resource type="PackedScene" path="res://world/interactables/rv_upgrade_shop_world.tscn" id="26_rv_upgrade"] [sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_4e4k5"] data = PackedVector3Array(10.033899, 3.3913999, 3.3446, 13.3786, 3.3913999, 0, 13.3786, 3.3913999, 3.3446, 10.033899, 3.3913999, 3.3446, 10.033899, 3.3913999, 0, 13.3786, 3.3913999, 0, 6.6893, 3.3913999, 3.3446, 10.033899, 3.3913999, 0, 10.033899, 3.3913999, 3.3446, 6.6893, 3.3913999, 3.3446, 6.6893, 3.3913999, 0, 10.033899, 3.3913999, 0, 6.6893, 3.3913999, 0, 10.033899, 3.3913999, -3.3446, 10.033899, 3.3913999, 0, 6.6893, 3.3913999, 6.6893, 6.6893, 3.3913999, 3.3446, 10.033899, 3.3913999, 3.3446, 6.6893, 3.3913999, 6.6893, 10.033899, 3.3913999, 3.3446, 10.033899, 3.3913999, 6.6893, 3.3446, 3.3913999, 3.3446, 6.6893, 3.3913999, 0, 6.6893, 3.3913999, 3.3446, 6.6893, 3.3913999, 10.033899, 6.6893, 3.3913999, 6.6893, 10.033899, 3.3913999, 6.6893, 6.6893, 3.3913999, 10.033899, 10.033899, 3.3913999, 6.6893, 10.033899, 3.3913999, 10.033899, 3.3446, 3.3913999, 6.6893, 6.6893, 3.3913999, 3.3446, 6.6893, 3.3913999, 6.6893, 3.3446, 3.3913999, 6.6893, 3.3446, 3.3913999, 3.3446, 6.6893, 3.3913999, 3.3446, 3.3446, 3.3913999, 10.033899, 6.6893, 3.3913999, 6.6893, 6.6893, 3.3913999, 10.033899, 3.3446, 3.3913999, 10.033899, 3.3446, 3.3913999, 6.6893, 6.6893, 3.3913999, 6.6893, 0, 3.3913999, 6.6893, 3.3446, 3.3913999, 3.3446, 3.3446, 3.3913999, 6.6893, 0, 3.3913999, 6.6893, 0, 3.3913999, 3.3446, 3.3446, 3.3913999, 3.3446, 0, 3.3913999, 10.033899, 0, 3.3913999, 6.6893, 3.3446, 3.3913999, 6.6893, 0, 3.3913999, 10.033899, 3.3446, 3.3913999, 6.6893, 3.3446, 3.3913999, 10.033899, -3.3446, 3.3913999, 13.3786, -3.3446, 3.3913999, 10.033899, 0, 3.3913999, 10.033899, -3.3446, 3.3913999, 13.3786, 0, 3.3913999, 10.033899, 0, 3.3913999, 13.3786, 0, 3.3913999, 13.3786, 0, 3.3913999, 10.033899, 3.3446, 3.3913999, 10.033899, 0, 3.3913999, 13.3786, 3.3446, 3.3913999, 10.033899, 3.3446, 3.3913999, 13.3786, 3.3446, 3.3913999, 13.3786, 3.3446, 3.3913999, 10.033899, 6.6893, 3.3913999, 10.033899, 3.3446, 3.3913999, 13.3786, 6.6893, 3.3913999, 10.033899, 6.6893, 3.3913999, 13.3786, 3.9148, 3.3913999, 16.514599, 3.3446, 3.3913999, 13.3786, 6.6893, 3.3913999, 13.3786, 3.3446, 3.3913999, 13.3786, 3.9148, 3.3913999, 16.514599, 3.6399, 3.3913999, 16.2405, 3.9148, 3.3913999, 16.514599, 6.6893, 3.3913999, 13.3786, 6.6893, 3.3913999, 16.7232, 6.6893, 3.3913999, 16.7232, 6.6949, 3.3913999, 18.9914, 6.6893, 3.3913999, 18.9861, 6.6949, 3.3913999, 18.9914, 6.6893, 3.3913999, 16.7232, 10.3743, 3.3913999, 16.7232, 6.6949, 3.3913999, 18.9914, 10.3743, 3.3913999, 16.7232, 9.1275, 3.3913999, 18.830599, 10.033899, 3.3913999, -10.033899, 13.3786, 3.3913999, -13.3786, 13.3786, 3.3913999, -10.033899, 13.3786, 3.3913999, -13.3786, 16.7232, 3.3913999, -10.033899, 13.3786, 3.3913999, -10.033899, 16.7232, 3.3913999, -10.033899, 19.798899, 3.3913999, -13.1096, 19.798899, 3.3913999, -10.033899, 16.7232, 3.3913999, -10.033899, 16.7232, 3.3913999, -13.1096, 19.798899, 3.3913999, -13.1096, 16.7232, 3.3913999, -10.033899, 16.4543, 3.3913999, -13.3786, 16.7232, 3.3913999, -13.1096, 16.7232, 3.3913999, -10.033899, 13.3786, 3.3913999, -13.3786, 16.4543, 3.3913999, -13.3786, 13.3786, 3.3913999, -6.6893, 13.3786, 3.3913999, -10.033899, 16.7232, 3.3913999, -10.033899, 13.3786, 3.3913999, -6.6893, 16.7232, 3.3913999, -10.033899, 16.7232, 3.3913999, -6.6893, 10.033899, 3.3913999, -6.6893, 13.3786, 3.3913999, -10.033899, 13.3786, 3.3913999, -6.6893, 10.033899, 3.3913999, -6.6893, 10.033899, 3.3913999, -10.033899, 13.3786, 3.3913999, -10.033899, 16.4543, 3.3913999, -13.3786, 16.495699, 3.3913999, -16.459, 16.495699, 3.3913999, -13.42, 16.4543, 3.3913999, -13.3786, 12.738999, 3.3913999, -15.894899, 16.495699, 3.3913999, -16.459, 12.738999, 3.3913999, -15.894899, 16.4543, 3.3913999, -13.3786, 13.3786, 3.3913999, -13.3786, 13.3786, 3.3913999, -13.3786, 12.460899, 3.3913999, -16.1674, 12.738999, 3.3913999, -15.894899, 13.3786, 3.3913999, -13.3786, 10.033899, 3.3913999, -16.7232, 12.460899, 3.3913999, -16.1674, 10.033899, 3.3913999, -10.033899, 10.033899, 3.3913999, -13.3786, 13.3786, 3.3913999, -13.3786, 10.033899, 3.3913999, -16.7232, 13.3786, 3.3913999, -13.3786, 10.033899, 3.3913999, -13.3786, 6.6893, 3.3913999, -13.3786, 10.033899, 3.3913999, -16.7232, 10.033899, 3.3913999, -13.3786, 6.6893, 3.3913999, -13.3786, 6.6893, 3.3913999, -16.7232, 10.033899, 3.3913999, -16.7232, 6.6893, 3.3913999, -10.033899, 10.033899, 3.3913999, -13.3786, 10.033899, 3.3913999, -10.033899, 6.6893, 3.3913999, -10.033899, 6.6893, 3.3913999, -13.3786, 10.033899, 3.3913999, -13.3786, 6.6893, 3.3913999, -6.6893, 6.6893, 3.3913999, -10.033899, 10.033899, 3.3913999, -10.033899, 6.6893, 3.3913999, -6.6893, 10.033899, 3.3913999, -10.033899, 10.033899, 3.3913999, -6.6893, 4.0225, 3.3913999, -8.7143, 6.6893, 3.3913999, -13.3786, 6.6893, 3.3913999, -10.033899, 4.6821, 3.3913999, -13.3786, 6.6893, 3.3913999, -16.7232, 6.6893, 3.3913999, -13.3786, 4.0225, 3.3913999, -8.7143, 4.6821, 3.3913999, -13.3786, 6.6893, 3.3913999, -13.3786, 4.6821, 3.3913999, -13.3786, 3.8388, 3.3913999, -16.7232, 6.6893, 3.3913999, -16.7232, 4.6821, 3.3913999, -13.3786, 4.0225, 3.3913999, -8.7143, 4.6821, 3.3913999, -13.3786, 4.6821, 3.3913999, -13.3786, 4.6821, 3.3913999, -13.3786, 4.4131, 3.2091, -13.357699, 4.6821, 3.3913999, -13.3786, 4.4131, 3.2091, -13.357699, 4.4131, 3.2091, -13.357699, 3.3446, 3.3913999, -6.6893, 4.0225, 3.3913999, -8.7143, 6.6893, 3.3913999, -10.033899, 3.3446, 3.3913999, -6.6893, 6.6893, 3.3913999, -10.033899, 6.6893, 3.3913999, -6.6893, 0, 3.3913999, -6.6893, 4.0225, 3.3913999, -8.7143, 3.3446, 3.3913999, -6.6893, 0, 3.3913999, -6.6893, 0, 3.3913999, -8.7143, 4.0225, 3.3913999, -8.7143, 3.3446, 3.3913999, -3.3446, 3.3446, 3.3913999, -6.6893, 6.6893, 3.3913999, -6.6893, 0, 3.3913999, -6.6893, -3.9101999, 3.3913999, -9.8592, 0, 3.3913999, -8.7143, 0, 3.3913999, -8.7143, -3.9101999, 3.3913999, -9.8592, 0, 3.3913999, -8.7143, 0, 3.3913999, -3.3446, 0, 3.3913999, -6.6893, 3.3446, 3.3913999, -6.6893, 0, 3.3913999, -3.3446, 3.3446, 3.3913999, -6.6893, 3.3446, 3.3913999, -3.3446, -3.6378, 3.3913999, -2.0792, 0, 3.3913999, -6.6893, 0, 3.3913999, -3.3446, -2.9566998, 3.3913999, 0, -3.6378, 3.3913999, -2.0792, 0, 3.3913999, -3.3446, -3.6378, 3.3913999, -2.0792, -3.3446, 3.3913999, -6.6893, 0, 3.3913999, -6.6893, -3.9101999, 3.3913999, -9.8592, 0, 3.3913999, -6.6893, -3.3446, 3.3913999, -6.6893, -6.6893, 3.3913999, -3.7326, -3.3446, 3.3913999, -6.6893, -3.6378, 3.3913999, -2.0792, -2.9566998, 3.3913999, 0, 0, 3.3913999, -3.3446, 0, 3.3913999, 0, 0, 3.3913999, 0, 0, 3.3913999, -3.3446, 3.3446, 3.3913999, -3.3446, -2.9566998, 3.3913999, 3.3446, -2.9566998, 3.3913999, 0, 0, 3.3913999, 0, -2.9566998, 3.3913999, 3.3446, 0, 3.3913999, 0, 0, 3.3913999, 3.3446, -6.6893, 3.3913999, -3.7326, -6.6893, 3.3913999, -6.6893, -3.3446, 3.3913999, -6.6893, -6.6893, 3.3913999, -6.6893, -3.9101999, 3.3913999, -9.8592, -3.3446, 3.3913999, -6.6893, -10.033899, 3.3913999, -3.7326, -6.6893, 3.3913999, -6.6893, -6.6893, 3.3913999, -3.7326, 0, 3.3913999, 3.3446, 0, 3.3913999, 0, 3.3446, 3.3913999, 0, 0, 3.3913999, 0, 3.3446, 3.3913999, -3.3446, 3.3446, 3.3913999, 0, 0, 3.3913999, 3.3446, 3.3446, 3.3913999, 0, 3.3446, 3.3913999, 3.3446, 3.3446, 3.3913999, 3.3446, 3.3446, 3.3913999, 0, 6.6893, 3.3913999, 0, 3.3446, 3.3913999, 0, 3.3446, 3.3913999, -3.3446, 6.6893, 3.3913999, -3.3446, 3.3446, 3.3913999, 0, 6.6893, 3.3913999, -3.3446, 6.6893, 3.3913999, 0, 3.3446, 3.3913999, -3.3446, 6.6893, 3.3913999, -6.6893, 6.6893, 3.3913999, -3.3446, 6.6893, 3.3913999, 0, 6.6893, 3.3913999, -3.3446, 10.033899, 3.3913999, -3.3446, 6.6893, 3.3913999, -3.3446, 6.6893, 3.3913999, -6.6893, 10.033899, 3.3913999, -6.6893, 6.6893, 3.3913999, -3.3446, 10.033899, 3.3913999, -6.6893, 10.033899, 3.3913999, -3.3446, -6.6893, 3.3913999, -6.6893, -6.6893, 3.3913999, -10.033899, -3.9101999, 3.3913999, -9.8592, -6.6893, 3.3913999, -10.033899, -3.9101999, 3.3913999, -12.538199, -3.9101999, 3.3913999, -9.8592, -10.033899, 3.3913999, -3.7326, -10.033899, 3.3913999, -6.6893, -6.6893, 3.3913999, -6.6893, -10.033899, 3.3913999, -6.6893, -6.6893, 3.3913999, -10.033899, -6.6893, 3.3913999, -6.6893, -13.3786, 3.3913999, -3.7326, -10.033899, 3.3913999, -6.6893, -10.033899, 3.3913999, -3.7326, -6.6893, 3.3913999, -10.033899, -6.6893, 3.3913999, -12.538199, -3.9101999, 3.3913999, -12.538199, -13.3786, 3.3913999, -3.7326, -13.3786, 3.3913999, -6.6893, -10.033899, 3.3913999, -6.6893, -16.191599, 3.3913999, -3.0971, -13.3786, 3.3913999, -6.6893, -13.3786, 3.3913999, -3.7326, -10.033899, 3.3913999, -6.6893, -10.033899, 3.3913999, -10.033899, -6.6893, 3.3913999, -10.033899, -13.3786, 3.3913999, -6.6893, -10.033899, 3.3913999, -10.033899, -10.033899, 3.3913999, -6.6893, -16.191599, 3.3913999, -3.0971, -16.7232, 3.3913999, -6.6893, -13.3786, 3.3913999, -6.6893, -13.3786, 3.3913999, -6.6893, -13.3786, 3.3913999, -10.033899, -10.033899, 3.3913999, -10.033899, -19.7545, 3.3913999, -2.7851999, -16.7232, 3.3913999, -6.6893, -16.191599, 3.3913999, -3.0971, -19.7545, 3.3913999, -2.7851999, -19.280699, 3.3913999, -6.6893, -16.7232, 3.3913999, -6.6893, -17.1112, 3.3913999, 0, -19.7545, 3.3913999, -2.7851999, -16.191599, 3.3913999, -3.0971, -17.1112, 3.3913999, 0, -19.9511, 3.3913999, -2.5834, -19.7545, 3.3913999, -2.7851999, -19.9511, 3.3913999, -2.5834, -17.1112, 3.3913999, 0, -20.0679, 3.3913999, 0, -20.0679, 3.3913999, 3.3446, -20.0679, 3.3913999, 0, -17.1112, 3.3913999, 0, -20.0679, 3.3913999, 3.3446, -17.1112, 3.3913999, 0, -17.1112, 3.3913999, 3.3044999, -13.3786, 3.3913999, -10.033899, -10.699599, 3.3913999, -13.175799, -10.033899, 3.3913999, -10.033899, -10.699599, 3.3913999, -13.175799, -6.6893, 3.3913999, -10.033899, -10.033899, 3.3913999, -10.033899, -13.3786, 3.3913999, -10.033899, -13.3786, 3.3913999, -13.3786, -10.699599, 3.3913999, -13.175799, -6.6893, 3.3913999, -10.033899, -10.699599, 3.3913999, -13.175799, -6.6893, 3.3913999, -12.538199, -13.3786, 3.3913999, -13.3786, -10.699599, 3.3913999, -15.835, -10.699599, 3.3913999, -13.175799, -13.3786, 3.3913999, -13.3786, -13.3786, 3.3913999, -15.4154, -10.699599, 3.3913999, -15.835, -6.6893, 3.3913999, -12.538199, -10.699599, 3.3913999, -13.175799, -6.6893, 3.3913999, -12.538199, -6.6893, 3.3913999, -12.538199, -6.6893, 3.3913999, -12.538199, -6.6893, 3.175, -12.867, -6.6893, 3.3913999, -12.538199, -6.6893, 3.175, -12.867, -6.6893, 3.175, -12.867, -20.0679, 3.3913999, 6.6893, -20.0679, 3.3913999, 3.3446, -17.1112, 3.3913999, 3.3044999, -22.5541, 3.3913999, 9.2058, -22.3151, 3.3913999, 6.6893, -20.0679, 3.3913999, 6.6893, -22.5541, 3.3913999, 9.2058, -20.0679, 3.3913999, 6.6893, -20.0679, 3.3913999, 9.167399, -20.0679, 3.3913999, 9.167399, -20.0679, 3.3913999, 6.6893, -16.7232, 3.3913999, 6.6893, -20.0679, 3.3913999, 6.6893, -17.1112, 3.3913999, 3.3044999, -16.7232, 3.3913999, 6.6893, -20.0679, 3.3913999, 9.167399, -16.7232, 3.3913999, 6.6893, -16.285099, 3.3913999, 9.5865, -16.7232, 3.3913999, 6.6893, -16.053999, 3.3913999, 9.8082, -16.285099, 3.3913999, 9.5865, -16.053999, 3.3913999, 9.8082, -16.7232, 3.3913999, 6.6893, -13.1355, 3.3913999, 6.7549996, -17.1112, 3.3913999, 3.3044999, -13.1355, 3.3913999, 6.7549996, -16.7232, 3.3913999, 6.6893, -16.053999, 3.3913999, 9.8082, -13.1355, 3.3913999, 6.7549996, -13.3786, 3.3913999, 10.033899, -13.1355, 3.3913999, 6.7549996, -17.1112, 3.3913999, 3.3044999, -14.877199, 3.3913999, 4.6657, -14.877199, 3.3913999, 4.6657, -17.1112, 3.3913999, 3.3044999, -15.582299, 3.3913999, 4.0366, -13.1355, 3.3913999, 6.7549996, -14.877199, 3.3913999, 4.6657, -14.0948, 3.3913999, 5.5073, -13.3786, 3.3913999, 10.033899, -13.1355, 3.3913999, 6.7549996, -10.033899, 3.3913999, 7.0772, -13.3786, 3.3913999, 10.033899, -10.033899, 3.3913999, 7.0772, -10.033899, 3.3913999, 10.033899, -10.033899, 3.3913999, 10.033899, -10.033899, 3.3913999, 7.0772, -6.6893, 3.3913999, 7.0772, -10.033899, 3.3913999, 10.033899, -6.6893, 3.3913999, 7.0772, -6.6893, 3.3913999, 10.033899, -10.033899, 3.0033998, 6.6893, -13.1355, 3.3913999, 6.7549996, -12.747499, 3.0033998, 6.3671, -10.033899, 3.0033998, 6.6893, -10.033899, 3.3913999, 7.0772, -13.1355, 3.3913999, 6.7549996, -2.5674999, 2.4164, 7.6215, -6.6893, 3.3913999, 7.0772, -6.6893, 3.0033998, 6.6893, -2.5674999, 2.4164, 7.6215, -2.1794999, 2.8042998, 8.009399, -6.6893, 3.3913999, 7.0772, -12.747499, 3.0033998, 6.3671, -14.0948, 3.3913999, 5.5073, -13.6942, 3.0033998, 5.1798, -12.747499, 3.0033998, 6.3671, -13.1355, 3.3913999, 6.7549996, -14.0948, 3.3913999, 5.5073, -6.6893, 3.0033998, 6.6893, -10.033899, 3.3913999, 7.0772, -10.033899, 3.0033998, 6.6893, -6.6893, 3.0033998, 6.6893, -6.6893, 3.3913999, 7.0772, -10.033899, 3.3913999, 7.0772, -16.7232, 3.0033998, 0, -16.191599, 3.3913999, -3.0971, -15.8036995, 3.0033998, -2.7091, -16.7232, 3.0033998, 0, -17.1112, 3.3913999, 0, -16.191599, 3.3913999, -3.0971, -13.3786, 3.3913999, -3.7326, -15.8036995, 3.0033998, -2.7091, -16.191599, 3.3913999, -3.0971, -13.3786, 3.3913999, -3.7326, -13.3786, 3.0033998, -3.3446, -15.8036995, 3.0033998, -2.7091, -2.9566998, 3.3913999, 0, -4.0257998, 3.0033998, -1.6911999, -3.6378, 3.3913999, -2.0792, -2.9566998, 3.3913999, 0, -3.3446, 3.0033998, 0, -4.0257998, 3.0033998, -1.6911999, -3.6378, 3.3913999, -2.0792, -6.6893, 3.0033998, -3.3446, -6.6893, 3.3913999, -3.7326, -3.6378, 3.3913999, -2.0792, -4.0257998, 3.0033998, -1.6911999, -6.6893, 3.0033998, -3.3446, -10.033899, 3.3913999, -3.7326, -13.3786, 3.0033998, -3.3446, -13.3786, 3.3913999, -3.7326, -10.033899, 3.3913999, -3.7326, -10.033899, 3.0033998, -3.3446, -13.3786, 3.0033998, -3.3446, -6.6893, 3.3913999, -3.7326, -10.033899, 3.0033998, -3.3446, -10.033899, 3.3913999, -3.7326, -6.6893, 3.3913999, -3.7326, -6.6893, 3.0033998, -3.3446, -10.033899, 3.0033998, -3.3446, -16.7232, 3.0033998, 2.9166, -17.1112, 3.3913999, 0, -16.7232, 3.0033998, 0, -16.7232, 3.0033998, 2.9166, -17.1112, 3.3913999, 3.3044999, -17.1112, 3.3913999, 0, -14.4892, 3.0033998, 4.2778, -15.582299, 3.3913999, 4.0366, -15.372, 3.0033998, 3.6132998, -14.4892, 3.0033998, 4.2778, -14.877199, 3.3913999, 4.6657, -15.582299, 3.3913999, 4.0366, -2.9566998, 3.3913999, 3.3446, -3.3446, 3.0033998, 0, -2.9566998, 3.3913999, 0, -2.9566998, 3.3913999, 3.3446, -3.3446, 3.0033998, 3.3446, -3.3446, 3.0033998, 0, -2.1794999, 2.8042998, 8.009399, -2.1397, 3.0033998, 5.1795, -1.7832999, 3.3913999, 5.2162, -2.1794999, 2.8042998, 8.009399, -2.5674999, 2.4164, 7.6215, -2.1397, 3.0033998, 5.1795, -6.6893, 3.3913999, 10.033899, -2.1794999, 2.8042998, 8.009399, -3.3446, 3.3913999, 10.033899, -6.6893, 3.3913999, 10.033899, -6.6893, 3.3913999, 7.0772, -2.1794999, 2.8042998, 8.009399, -1.7832999, 3.3913999, 5.2162, 0, 3.3913999, 6.6893, -2.1794999, 2.8042998, 8.009399, 0, 3.3913999, 6.6893, -1.7832999, 3.3913999, 5.2162, -2.9566998, 3.3913999, 3.3446, 0, 3.3913999, 6.6893, -2.9566998, 3.3913999, 3.3446, 0, 3.3913999, 3.3446, -3.3446, 3.3913999, 10.033899, 0, 3.3913999, 6.6893, 0, 3.3913999, 10.033899, -3.3446, 3.3913999, 10.033899, -2.1794999, 2.8042998, 8.009399, 0, 3.3913999, 6.6893, -2.1397, 3.0033998, 5.1795, -2.9566998, 3.3913999, 3.3446, -1.7832999, 3.3913999, 5.2162, -2.1397, 3.0033998, 5.1795, -3.3446, 3.0033998, 3.3446, -2.9566998, 3.3913999, 3.3446, -14.0948, 3.3913999, 5.5073, -14.4892, 3.0033998, 4.2778, -13.6942, 3.0033998, 5.1798, -14.0948, 3.3913999, 5.5073, -14.877199, 3.3913999, 4.6657, -14.4892, 3.0033998, 4.2778, -15.582299, 3.3913999, 4.0366, -16.7232, 3.0033998, 2.9166, -15.372, 3.0033998, 3.6132998, -15.582299, 3.3913999, 4.0366, -17.1112, 3.3913999, 3.3044999, -16.7232, 3.0033998, 2.9166, 20.198, 3.1490998, -10.033899, 19.798899, 3.3913999, -13.1096, 20.1539, 3.1299, -13.399799, 20.198, 3.1490998, -10.033899, 19.798899, 3.3913999, -10.033899, 19.798899, 3.3913999, -13.1096, 20.1539, 3.1299, -13.399799, 16.7232, 3.3913999, -13.1096, 16.8204, 3.138, -13.447599, 20.1539, 3.1299, -13.399799, 19.798899, 3.3913999, -13.1096, 16.7232, 3.3913999, -13.1096, 16.756899, 3.1650999, -16.7286, 12.738999, 3.3913999, -15.894899, 12.7471, 3.1766999, -16.1988, 16.756899, 3.1650999, -16.7286, 16.495699, 3.3913999, -16.459, 12.738999, 3.3913999, -15.894899, 16.8051, 3.1778, -13.479, 16.495699, 3.3913999, -16.459, 16.756899, 3.1650999, -16.7286, 16.8051, 3.1778, -13.479, 16.495699, 3.3913999, -13.42, 16.495699, 3.3913999, -16.459, 16.4543, 3.3913999, -13.3786, 16.8204, 3.138, -13.447599, 16.7232, 3.3913999, -13.1096, 16.8204, 3.138, -13.447599, 16.4543, 3.3913999, -13.3786, 16.495699, 3.3913999, -13.42, 16.8204, 3.138, -13.447599, 16.495699, 3.3913999, -13.42, 16.8051, 3.1778, -13.479, 10.033899, 3.0523999, -19.0294, 6.6893, 3.2782998, -18.727999, 6.6893, 3.0440998, -19.036999, 10.033899, 3.0523999, -19.0294, 10.033899, 3.2784998, -18.6997, 6.6893, 3.2782998, -18.727999, 12.723599, 2.9213, -19.2902, 10.033899, 3.2784998, -18.6997, 10.033899, 3.0523999, -19.0294, 12.723599, 2.9213, -19.2902, 12.446099, 3.1699998, -18.9401, 10.033899, 3.2784998, -18.6997, 12.446099, 3.1699998, -18.9401, 12.747, 3.1771, -16.1991, 12.460899, 3.3913999, -16.1674, 12.446099, 3.1699998, -18.9401, 12.723599, 2.9213, -19.2902, 12.747, 3.1771, -16.1991, 12.460899, 3.3913999, -16.1674, 10.033899, 3.2784998, -18.6997, 12.446099, 3.1699998, -18.9401, 10.033899, 3.3913999, -16.7232, 10.033899, 3.2784998, -18.6997, 12.460899, 3.3913999, -16.1674, 10.033899, 3.3913999, -16.7232, 12.460899, 3.3913999, -16.1674, 12.460899, 3.3913999, -16.1674, 6.6893, 3.3913999, -16.7232, 10.033899, 3.2784998, -18.6997, 10.033899, 3.3913999, -16.7232, 6.6893, 3.3913999, -16.7232, 6.6893, 3.2782998, -18.727999, 10.033899, 3.2784998, -18.6997, 12.738999, 3.3913999, -15.894899, 12.747, 3.1771, -16.1991, 12.7471, 3.1766999, -16.1988, 12.738999, 3.3913999, -15.894899, 12.460899, 3.3913999, -16.1674, 12.747, 3.1771, -16.1991, 12.460899, 3.3913999, -16.1674, 12.738999, 3.3913999, -15.894899, 12.460899, 3.3913999, -16.1674, 3.8388, 3.3913999, -16.7232, 4.4783998, 3.1067, -18.2665, 4.6443, 3.2897, -17.9799, 3.8388, 3.3913999, -16.7232, 3.5895, 3.2033, -16.7232, 4.4783998, 3.1067, -18.2665, 4.6821, 3.3913999, -13.3786, 3.5895, 3.2033, -16.7232, 3.8388, 3.3913999, -16.7232, 4.6821, 3.3913999, -13.3786, 4.4131, 3.2091, -13.357699, 3.5895, 3.2033, -16.7232, 6.6640997, 3.0702, -19.018099, 4.6443, 3.2897, -17.9799, 4.4783998, 3.1067, -18.2665, 6.6640997, 3.0702, -19.018099, 6.6705, 3.2772, -18.741, 4.6443, 3.2897, -17.9799, 4.6443, 3.2897, -17.9799, 6.6893, 3.3913999, -16.7232, 3.8388, 3.3913999, -16.7232, 6.6893, 3.3913999, -16.7232, 4.6443, 3.2897, -17.9799, 6.6705, 3.2772, -18.741, 6.6893, 3.3913999, -16.7232, 6.6705, 3.2772, -18.741, 6.6893, 3.2782998, -18.727999, 6.6893, 3.2782998, -18.727999, 6.6640997, 3.0702, -19.018099, 6.6893, 3.0440998, -19.036999, 6.6893, 3.2782998, -18.727999, 6.6705, 3.2772, -18.741, 6.6640997, 3.0702, -19.018099, 3.7529, 3.1712, -9.0494995, 0, 3.3913999, -8.7143, 0, 3.179, -9.0652, 3.7529, 3.1712, -9.0494995, 4.0225, 3.3913999, -8.7143, 0, 3.3913999, -8.7143, 4.0225, 3.3913999, -8.7143, 4.4131, 3.2091, -13.357699, 4.6821, 3.3913999, -13.3786, 4.0225, 3.3913999, -8.7143, 3.7529, 3.1712, -9.0494995, 4.4131, 3.2091, -13.357699, -3.6538, 3.1585999, -12.813399, -6.6893, 3.3913999, -12.538199, -6.6893, 3.175, -12.867, -3.6538, 3.1585999, -12.813399, -3.9101999, 3.3913999, -12.538199, -6.6893, 3.3913999, -12.538199, -3.6076, 3.1676, -10.0696, -3.9101999, 3.3913999, -12.538199, -3.6538, 3.1585999, -12.813399, -3.6076, 3.1676, -10.0696, -3.9101999, 3.3913999, -9.8592, -3.9101999, 3.3913999, -12.538199, -0.0081, 3.1864998, -9.063499, -3.9101999, 3.3913999, -9.8592, -3.6076, 3.1676, -10.0696, -0.0081, 3.1864998, -9.063499, 0, 3.3913999, -8.7143, -3.9101999, 3.3913999, -9.8592, 0, 3.3913999, -8.7143, -0.0081, 3.1864998, -9.063499, 0, 3.179, -9.0652, 0, 3.3913999, -8.7143, 0, 3.3913999, -8.7143, -0.0081, 3.1864998, -9.063499, -10.4043, 3.1608999, -13.4295, -10.699599, 3.3913999, -15.835, -10.4319, 3.1557999, -16.1556, -10.4043, 3.1608999, -13.4295, -10.699599, 3.3913999, -13.175799, -10.699599, 3.3913999, -15.835, -10.4319, 3.1557999, -16.1556, -13.3786, 3.3913999, -15.4154, -13.3786, 3.1771998, -15.7625, -10.4319, 3.1557999, -16.1556, -10.699599, 3.3913999, -15.835, -13.3786, 3.3913999, -15.4154, -10.699599, 3.3913999, -13.175799, -6.6893, 3.175, -12.867, -6.6893, 3.3913999, -12.538199, -10.699599, 3.3913999, -13.175799, -10.4043, 3.1608999, -13.4295, -6.6893, 3.175, -12.867, -16.130499, 3.6227, -13.623799, -16.0243, 3.3509998, -15.752, -15.7941, 3.5591, -15.4641, -16.130499, 3.6227, -13.623799, -16.3753, 3.4225, -13.6277, -16.0243, 3.3509998, -15.752, -13.3911, 3.1892, -15.757, -15.7941, 3.5591, -15.4641, -16.0243, 3.3509998, -15.752, -13.3911, 3.1892, -15.757, -13.396, 3.3925, -15.4333, -15.7941, 3.5591, -15.4641, -15.7941, 3.5591, -15.4641, -13.3786, 3.3913999, -13.3786, -16.130499, 3.6227, -13.623799, -13.3786, 3.3913999, -13.3786, -15.7941, 3.5591, -15.4641, -13.396, 3.3925, -15.4333, -13.3786, 3.3913999, -13.3786, -13.396, 3.3925, -15.4333, -13.3786, 3.3913999, -15.4154, -13.3786, 3.3913999, -15.4154, -13.3911, 3.1892, -15.757, -13.3786, 3.1771998, -15.7625, -13.3786, 3.3913999, -15.4154, -13.396, 3.3925, -15.4333, -13.3911, 3.1892, -15.757, -16.3753, 3.4225, -13.6277, -16.1241, 3.3832998, -9.5097, -16.4131, 3.1706, -9.788899, -16.3753, 3.4225, -13.6277, -16.130499, 3.6227, -13.623799, -16.1241, 3.3832998, -9.5097, -16.7232, 3.3913999, -6.6893, -13.3786, 3.3913999, -10.033899, -13.3786, 3.3913999, -6.6893, -16.7232, 3.3913999, -6.6893, -16.1241, 3.3832998, -9.5097, -13.3786, 3.3913999, -10.033899, -16.1241, 3.3832998, -9.5097, -13.3786, 3.3913999, -13.3786, -13.3786, 3.3913999, -10.033899, -16.1241, 3.3832998, -9.5097, -16.130499, 3.6227, -13.623799, -13.3786, 3.3913999, -13.3786, -16.130499, 3.6227, -13.623799, -16.1241, 3.3832998, -9.5097, -16.130499, 3.6227, -13.623799, -16.130499, 3.6227, -13.623799, -16.3753, 3.4225, -13.6277, -16.3753, 3.4225, -13.6277, -16.130499, 3.6227, -13.623799, -16.130499, 3.6227, -13.623799, -16.3753, 3.4225, -13.6277, -19.7545, 3.3913999, -2.7851999, -19.515, 3.2122, -6.6893, -19.280699, 3.3913999, -6.6893, -19.7545, 3.3913999, -2.7851999, -19.9489, 3.2063, -2.8082, -19.515, 3.2122, -6.6893, -19.280699, 3.3913999, -6.6893, -19.6161, 3.2075999, -9.7116995, -19.3965, 3.3909, -9.5092, -19.280699, 3.3913999, -6.6893, -19.515, 3.2122, -6.6893, -19.6161, 3.2075999, -9.7116995, -19.280699, 3.3913999, -6.6893, -16.1241, 3.3832998, -9.5097, -16.7232, 3.3913999, -6.6893, -19.280699, 3.3913999, -6.6893, -19.3965, 3.3909, -9.5092, -16.1241, 3.3832998, -9.5097, -16.1241, 3.3832998, -9.5097, -19.6237, 3.1655998, -9.757899, -16.4131, 3.1706, -9.788899, -19.6237, 3.1655998, -9.757899, -16.1241, 3.3832998, -9.5097, -19.3965, 3.3909, -9.5092, -19.6237, 3.1655998, -9.757899, -19.3965, 3.3909, -9.5092, -19.6161, 3.2075999, -9.7116995, -22.8657, 3.4937, 3.3613, -23.3676, 3.4459999, 0.1372, -23.170399, 3.6251, 0.122999996, -22.8657, 3.4937, 3.3613, -23.0809, 3.3083, 3.3615, -23.3676, 3.4459999, 0.1372, -23.170399, 3.6251, 0.122999996, -23.390299, 3.3349998, -2.6938999, -23.192099, 3.5300999, -2.4668999, -23.170399, 3.6251, 0.122999996, -23.3676, 3.4459999, 0.1372, -23.390299, 3.3349998, -2.6938999, -23.192099, 3.5300999, -2.4668999, -19.9489, 3.2063, -2.8082, -19.9511, 3.3913999, -2.5834, -23.192099, 3.5300999, -2.4668999, -23.390299, 3.3349998, -2.6938999, -19.9489, 3.2063, -2.8082, -23.192099, 3.5300999, -2.4668999, -20.0679, 3.3913999, 0, -23.170399, 3.6251, 0.122999996, -20.0679, 3.3913999, 0, -23.192099, 3.5300999, -2.4668999, -19.9511, 3.3913999, -2.5834, -19.9511, 3.3913999, -2.5834, -23.192099, 3.5300999, -2.4668999, -19.9511, 3.3913999, -2.5834, -22.8657, 3.4937, 3.3613, -20.0679, 3.3913999, 0, -20.0679, 3.3913999, 3.3446, -22.8657, 3.4937, 3.3613, -23.170399, 3.6251, 0.122999996, -20.0679, 3.3913999, 0, -19.7545, 3.3913999, -2.7851999, -19.9489, 3.2063, -2.8082, -19.9489, 3.2063, -2.8082, -19.7545, 3.3913999, -2.7851999, -19.9511, 3.3913999, -2.5834, -19.9489, 3.2063, -2.8082, -19.9511, 3.3913999, -2.5834, -19.7545, 3.3913999, -2.7851999, -19.9511, 3.3913999, -2.5834, -23.0777, 3.3197, 3.3734, -22.3151, 3.3913999, 6.6893, -22.563799, 3.2219, 6.6893, -23.0777, 3.3197, 3.3734, -22.8764, 3.4937, 3.3741, -22.3151, 3.3913999, 6.6893, -22.8764, 3.4937, 3.3741, -20.0679, 3.3913999, 6.6893, -22.3151, 3.3913999, 6.6893, -20.0679, 3.3913999, 6.6893, -22.8764, 3.4937, 3.3741, -22.8657, 3.4937, 3.3613, -20.0679, 3.3913999, 6.6893, -22.8657, 3.4937, 3.3613, -20.0679, 3.3913999, 3.3446, -22.8657, 3.4937, 3.3613, -23.0777, 3.3197, 3.3734, -23.0809, 3.3083, 3.3615, -22.8657, 3.4937, 3.3613, -22.8764, 3.4937, 3.3741, -23.0777, 3.3197, 3.3734, -16.285099, 3.3913999, 9.5865, -20.0679, 3.1943, 9.407499, -20.0679, 3.3913999, 9.167399, -16.285099, 3.3913999, 9.5865, -16.2818, 3.1913998, 9.8056, -20.0679, 3.1943, 9.407499, -22.791399, 3.2124999, 9.4432, -20.0679, 3.3913999, 9.167399, -20.0679, 3.1943, 9.407499, -22.791399, 3.2124999, 9.4432, -22.5541, 3.3913999, 9.2058, -20.0679, 3.3913999, 9.167399, -22.5541, 3.3913999, 9.2058, -22.563799, 3.2219, 6.6893, -22.3151, 3.3913999, 6.6893, -22.5541, 3.3913999, 9.2058, -22.791399, 3.2124999, 9.4432, -22.563799, 3.2219, 6.6893, -22.791399, 3.2124999, 9.4432, -22.5541, 3.3913999, 9.2058, -22.791399, 3.2124999, 9.4432, -13.3786, 3.3922, 12.571899, -16.076399, 3.04, 12.735, -15.847199, 3.2614, 12.4973, -13.3786, 3.3922, 12.571899, -13.3786, 3.194, 12.8089, -16.076399, 3.04, 12.735, -15.847199, 3.2614, 12.4973, -16.2818, 3.1913998, 9.8056, -16.053999, 3.3913999, 9.8082, -15.847199, 3.2614, 12.4973, -16.076399, 3.04, 12.735, -16.2818, 3.1913998, 9.8056, -15.847199, 3.2614, 12.4973, -13.3786, 3.3913999, 10.033899, -13.3786, 3.3922, 12.571899, -15.847199, 3.2614, 12.4973, -16.053999, 3.3913999, 9.8082, -13.3786, 3.3913999, 10.033899, -16.053999, 3.3913999, 9.8082, -15.847199, 3.2614, 12.4973, -16.053999, 3.3913999, 9.8082, -16.285099, 3.3913999, 9.5865, -16.2818, 3.1913998, 9.8056, -16.2818, 3.1913998, 9.8056, -16.285099, 3.3913999, 9.5865, -16.053999, 3.3913999, 9.8082, -16.2818, 3.1913998, 9.8056, -16.053999, 3.3913999, 9.8082, -16.285099, 3.3913999, 9.5865, -16.053999, 3.3913999, 9.8082, -5.9742, 3.3994, 12.8817, -10.033899, 2.9384, 12.4537, -10.033899, 3.2142, 12.1061, -5.9742, 3.3994, 12.8817, -6.2748, 3.126, 13.122, -10.033899, 2.9384, 12.4537, -10.033899, 3.2142, 12.1061, -13.3786, 3.194, 12.8089, -13.3786, 3.3922, 12.571899, -10.033899, 3.2142, 12.1061, -10.033899, 2.9384, 12.4537, -13.3786, 3.194, 12.8089, -10.033899, 3.2142, 12.1061, -6.6893, 3.3913999, 10.033899, -5.9742, 3.3994, 12.8817, -10.033899, 3.2142, 12.1061, -10.033899, 3.3913999, 10.033899, -6.6893, 3.3913999, 10.033899, -13.3786, 3.3922, 12.571899, -10.033899, 3.3913999, 10.033899, -10.033899, 3.2142, 12.1061, -13.3786, 3.3922, 12.571899, -13.3786, 3.3913999, 10.033899, -10.033899, 3.3913999, 10.033899, -13.3786, 3.3913999, 10.033899, -13.3786, 3.3922, 12.571899, -13.3786, 3.3922, 12.571899, -5.9742, 3.3994, 12.8817, -3.3446, 3.3913999, 10.033899, -3.3446, 3.3913999, 13.3786, -5.9742, 3.3994, 12.8817, -6.6893, 3.3913999, 10.033899, -3.3446, 3.3913999, 10.033899, -13.3786, 3.3922, 12.571899, -13.3786, 3.194, 12.8089, -13.3786, 3.194, 12.8089, -13.3786, 3.3922, 12.571899, -13.3786, 3.3922, 12.571899, -13.3786, 3.194, 12.8089, 3.6399, 3.3913999, 16.2405, 0, 2.9636998, 16.0179, 0, 3.2243998, 15.7093, 3.6399, 3.3913999, 16.2405, 3.6425998, 3.1413999, 16.5127, 0, 2.9636998, 16.0179, 0, 3.2243998, 15.7093, -3.3446, 3.1497998, 15.914599, -3.3446, 3.3913999, 15.6011, 0, 3.2243998, 15.7093, 0, 2.9636998, 16.0179, -3.3446, 3.1497998, 15.914599, -6.2558, 3.1427999, 16.4098, -3.3446, 3.3913999, 15.6011, -3.3446, 3.1497998, 15.914599, -6.2558, 3.1427999, 16.4098, -5.9737997, 3.392, 16.087599, -3.3446, 3.3913999, 15.6011, -3.3446, 3.3913999, 15.6011, 0, 3.3913999, 13.3786, 0, 3.2243998, 15.7093, -3.3446, 3.3913999, 15.6011, -3.3446, 3.3913999, 13.3786, 0, 3.3913999, 13.3786, 0, 3.2243998, 15.7093, 3.3446, 3.3913999, 13.3786, 3.6399, 3.3913999, 16.2405, 0, 3.2243998, 15.7093, 0, 3.3913999, 13.3786, 3.3446, 3.3913999, 13.3786, -5.9737997, 3.392, 16.087599, -3.3446, 3.3913999, 13.3786, -3.3446, 3.3913999, 15.6011, -5.9737997, 3.392, 16.087599, -5.9742, 3.3994, 12.8817, -3.3446, 3.3913999, 13.3786, -6.2748, 3.1260998, 16.4145, -5.9737997, 3.392, 16.087599, -6.2558, 3.1427999, 16.4098, -5.9737997, 3.392, 16.087599, -6.2748, 3.1260998, 16.4145, -6.2748, 3.126, 13.122, -5.9737997, 3.392, 16.087599, -6.2748, 3.126, 13.122, -5.9742, 3.3994, 12.8817, 6.6893, 3.3913999, 18.9861, 3.9266999, 3.5967, 19.6223, 4.1273, 3.7335, 19.3804, 6.6893, 3.3913999, 18.9861, 6.6893, 3.2050998, 19.228699, 3.9266999, 3.5967, 19.6223, 4.1273, 3.7335, 19.3804, 3.6536, 3.2078998, 16.5669, 3.8651, 3.3981998, 16.5647, 4.1273, 3.7335, 19.3804, 3.9266999, 3.5967, 19.6223, 3.6536, 3.2078998, 16.5669, 3.8651, 3.3981998, 16.5647, 6.6893, 3.3913999, 18.9861, 4.1273, 3.7335, 19.3804, 6.6893, 3.3913999, 18.9861, 3.8651, 3.3981998, 16.5647, 3.9148, 3.3913999, 16.514599, 6.6893, 3.3913999, 18.9861, 3.9148, 3.3913999, 16.514599, 6.6893, 3.3913999, 16.7232, 3.9148, 3.3913999, 16.514599, 3.6425998, 3.1413999, 16.5127, 3.6399, 3.3913999, 16.2405, 3.6425998, 3.1413999, 16.5127, 3.9148, 3.3913999, 16.514599, 3.8651, 3.3981998, 16.5647, 3.6425998, 3.1413999, 16.5127, 3.8651, 3.3981998, 16.5647, 3.6536, 3.2078998, 16.5669, 9.3066, 3.2186, 19.0653, 10.3743, 3.3913999, 16.7232, 10.5913, 3.1985998, 16.7232, 9.3066, 3.2186, 19.0653, 9.1275, 3.3913999, 18.830599, 10.3743, 3.3913999, 16.7232, 9.1275, 3.3913999, 18.830599, 6.6991997, 3.2148, 19.2255, 6.6949, 3.3913999, 18.9914, 9.1275, 3.3913999, 18.830599, 9.3066, 3.2186, 19.0653, 6.6991997, 3.2148, 19.2255, 6.6893, 3.3913999, 18.9861, 6.6991997, 3.2148, 19.2255, 6.6893, 3.2050998, 19.228699, 6.6893, 3.3913999, 18.9861, 6.6949, 3.3913999, 18.9914, 6.6991997, 3.2148, 19.2255, 9.8131, 3.3546, 13.1979, 10.5893, 3.2117, 16.7106, 10.403999, 3.3911998, 16.6938, 9.8131, 3.3546, 13.1979, 10.0546, 3.1885, 13.4071, 10.5893, 3.2117, 16.7106, 6.6893, 3.3913999, 13.3786, 10.3743, 3.3913999, 16.7232, 6.6893, 3.3913999, 16.7232, 10.3743, 3.3913999, 16.7232, 6.6893, 3.3913999, 13.3786, 9.8131, 3.3546, 13.1979, 10.3743, 3.3913999, 16.7232, 9.8131, 3.3546, 13.1979, 10.403999, 3.3911998, 16.6938, 6.6893, 3.3913999, 13.3786, 10.033899, 3.3913999, 10.033899, 9.8131, 3.3546, 13.1979, 6.6893, 3.3913999, 13.3786, 6.6893, 3.3913999, 10.033899, 10.033899, 3.3913999, 10.033899, 10.3743, 3.3913999, 16.7232, 10.5893, 3.2117, 16.7106, 10.5913, 3.1985998, 16.7232, 10.3743, 3.3913999, 16.7232, 10.403999, 3.3911998, 16.6938, 10.5893, 3.2117, 16.7106, 13.1839, 3.2744, 6.6893, 13.5511, 3.1797, 6.6893, 13.4036, 3.0749998, 6.6893, 13.1839, 3.2744, 6.6893, 13.3786, 3.2744, 6.496, 13.5511, 3.1797, 6.6893, 12.9758, 3.2036, 10.033899, 13.1839, 3.2744, 6.6893, 13.4036, 3.0749998, 6.6893, 12.9758, 3.2036, 10.033899, 12.7325, 3.3913999, 10.033899, 13.1839, 3.2744, 6.6893, 13.2631, 3.5611, 13.4043, 12.7325, 3.3913999, 10.033899, 12.9758, 3.2036, 10.033899, 13.2631, 3.5611, 13.4043, 13.025499, 3.6999, 13.1985, 12.7325, 3.3913999, 10.033899, 10.033899, 3.3913999, 10.033899, 13.1839, 3.2744, 6.6893, 12.7325, 3.3913999, 10.033899, 10.033899, 3.3913999, 10.033899, 10.033899, 3.3913999, 6.6893, 13.1839, 3.2744, 6.6893, 9.8131, 3.3546, 13.1979, 12.7325, 3.3913999, 10.033899, 13.025499, 3.6999, 13.1985, 9.8131, 3.3546, 13.1979, 10.033899, 3.3913999, 10.033899, 12.7325, 3.3913999, 10.033899, 10.033899, 3.3913999, 3.3446, 13.1839, 3.2744, 6.6893, 10.033899, 3.3913999, 6.6893, 13.1839, 3.2744, 6.6893, 10.033899, 3.3913999, 3.3446, 13.3786, 3.3913999, 3.3446, 13.1839, 3.2744, 6.6893, 13.3786, 3.3913999, 3.3446, 13.3786, 3.2744, 6.496, 13.025499, 3.6999, 13.1985, 10.0546, 3.1885, 13.4071, 9.8131, 3.3546, 13.1979, 13.025499, 3.6999, 13.1985, 13.2631, 3.5611, 13.4043, 10.0546, 3.1885, 13.4071, 13.2631, 3.5611, 13.4043, 13.2631, 3.5611, 13.4043, 13.025499, 3.6999, 13.1985, 14.0489, 3.0042, -3.3446, 13.1206, 3.3028998, -3.3446, 13.3786, 3.3028998, -3.6027, 14.0489, 3.0042, -3.3446, 13.3786, 3.3028998, -3.0865998, 13.1206, 3.3028998, -3.3446, 16.7232, 3.1513, -3.602, 14.0489, 3.0042, -3.3446, 13.3786, 3.3028998, -3.6027, 16.7232, 3.1513, -3.602, 16.7127, 2.8734, -3.3446, 14.0489, 3.0042, -3.3446, 13.3786, 3.3028998, -3.6027, 16.7232, 3.3913999, -6.6893, 16.7232, 3.1513, -3.602, 13.3786, 3.3028998, -3.6027, 13.3786, 3.3913999, -6.6893, 16.7232, 3.3913999, -6.6893, 10.033899, 3.3913999, -6.6893, 13.1206, 3.3028998, -3.3446, 10.033899, 3.3913999, -3.3446, 13.1206, 3.3028998, -3.3446, 10.033899, 3.3913999, -6.6893, 13.3786, 3.3913999, -6.6893, 13.1206, 3.3028998, -3.3446, 13.3786, 3.3913999, -6.6893, 13.3786, 3.3028998, -3.6027, 20.0679, 0, 0, 14.0489, 3.0042, -3.3446, 20.961199, 0, -3.3446, 20.0679, 0, 3.3446, 14.0489, 3.0042, -3.3446, 20.0679, 0, 0, 14.0489, 3.0042, -3.3446, 13.3786, 3.3913999, 0, 13.3786, 3.3028998, -3.0865998, 14.0489, 3.0042, -3.3446, 13.3786, 3.2744, 6.496, 13.3786, 3.3913999, 0, 14.0489, 3.0042, -3.3446, 20.0679, 0, 3.3446, 13.3786, 3.2744, 6.496, 13.3786, 3.3913999, 0, 13.3786, 3.2744, 6.496, 13.3786, 3.3913999, 3.3446, 13.3786, 3.2744, 6.496, 20.0679, 0, 3.3446, 16.7232, 1.5715, 6.6893, 16.7232, 1.5715, 6.6893, 20.0679, 0, 3.3446, 20.0679, -0.124199994, 6.6893, 13.3786, 3.2744, 6.496, 16.7232, 1.5715, 6.6893, 13.5511, 3.1797, 6.6893, 10.033899, 3.3913999, -3.3446, 13.3786, 3.3913999, 0, 10.033899, 3.3913999, 0, 13.3786, 3.3913999, 0, 10.033899, 3.3913999, -3.3446, 13.1206, 3.3028998, -3.3446, 13.3786, 3.3913999, 0, 13.1206, 3.3028998, -3.3446, 13.3786, 3.3028998, -3.0865998, 19.831999, 3.3902998, -10.0008, 20.147, 3.0588999, -6.6893, 19.8322, 3.2891998, -6.6893, 19.831999, 3.3902998, -10.0008, 20.1796, 3.182, -9.995999, 20.147, 3.0588999, -6.6893, 19.8322, 3.2891998, -6.6893, 20.1349, 2.7974, -3.3783998, 19.8322, 3.0491, -3.602, 19.8322, 3.2891998, -6.6893, 20.147, 3.0588999, -6.6893, 20.1349, 2.7974, -3.3783998, 16.7232, 3.1513, -3.602, 19.8322, 3.2891998, -6.6893, 19.8322, 3.0491, -3.602, 16.7232, 3.1513, -3.602, 16.7232, 3.3913999, -6.6893, 19.8322, 3.2891998, -6.6893, 16.7232, 3.3913999, -10.033899, 19.8322, 3.2891998, -6.6893, 16.7232, 3.3913999, -6.6893, 19.8322, 3.2891998, -6.6893, 16.7232, 3.3913999, -10.033899, 19.798899, 3.3913999, -10.033899, 19.8322, 3.2891998, -6.6893, 19.798899, 3.3913999, -10.033899, 19.831999, 3.3902998, -10.0008, 20.198, 3.1490998, -10.033899, 19.831999, 3.3902998, -10.0008, 19.798899, 3.3913999, -10.033899, 20.198, 3.1490998, -10.033899, 20.1796, 3.182, -9.995999, 19.831999, 3.3902998, -10.0008, 20.144999, 2.7605999, -3.3446, 19.8322, 3.0491, -3.602, 20.1349, 2.7974, -3.3783998, 19.8322, 3.0491, -3.602, 20.144999, 2.7605999, -3.3446, 16.7127, 2.8734, -3.3446, 19.8322, 3.0491, -3.602, 16.7127, 2.8734, -3.3446, 16.7232, 3.1513, -3.602, 15.0508995, 0, 6.6893, 16.7232, 1.5715, 6.6893, 16.7232, 0, 6.6893, 16.7232, 0, 6.6893, 16.7232, 1.5715, 6.6893, 20.0679, -0.124199994, 6.6893, 15.0508995, 0, 6.6893, 13.5511, 3.1797, 6.6893, 16.7232, 1.5715, 6.6893, 15.0508995, 0, 6.6893, 13.4036, 3.0749998, 6.6893, 13.5511, 3.1797, 6.6893, 13.4036, 3.0749998, 6.6893, 15.0508995, 0, 6.6893, 13.8046, 0, 6.6893, -16.7232, 0.6137, 0, -15.7546, 0.6137, 3.5372, -16.7232, 0.6137, 2.9166, -15.7546, 0.6137, 3.5372, -16.7232, 0.6137, 0, -13.3786, 0.6137, 0, -16.7232, 0.6137, 0, -15.8036995, 0.6137, -2.7091, -13.3786, 0.6137, -3.3446, -16.7232, 0.6137, 0, -13.3786, 0.6137, -3.3446, -13.3786, 0.6137, 0, -13.3786, 0.6137, 0, -13.3786, 0.6137, -3.3446, -10.033899, 0.6137, -3.3446, -15.7546, 0.6137, 3.5372, -13.3786, 0.6137, 0, -14.4892, 0.6137, 4.2778, -13.3786, 0.6137, 0, -10.033899, 0.6137, -3.3446, -10.033899, 0.6137, 0, -14.4892, 0.6137, 4.2778, -13.3786, 0.6137, 0, -10.033899, 0.6137, 0, -10.033899, 0.6137, 0, -10.033899, 0.6137, -3.3446, -6.6893, 0.6137, -3.3446, -10.033899, 0.6137, 0, -6.6893, 0.6137, -3.3446, -6.6893, 0.6137, 0, -6.6893, 0.6137, 0, -6.6893, 0.6137, -3.3446, -4.0257998, 0.6137, -1.6911999, -6.6893, 0.6137, 0, -4.0257998, 0.6137, -1.6911999, -3.3446, 0.6137, 0, -10.033899, 0.6137, 3.3446, -10.033899, 0.6137, 0, -6.6893, 0.6137, 0, -14.4892, 0.6137, 4.2778, -10.033899, 0.6137, 0, -10.033899, 0.6137, 3.3446, -6.6893, 0.6137, 3.3446, -6.6893, 0.6137, 0, -3.3446, 0.6137, 0, -10.033899, 0.6137, 3.3446, -6.6893, 0.6137, 0, -6.6893, 0.6137, 3.3446, -6.6893, 0.6137, 3.3446, -3.3446, 0.6137, 0, -3.3446, 0.6137, 3.3446, -10.033899, 0.6137, 6.6893, -14.4892, 0.6137, 4.2778, -10.033899, 0.6137, 3.3446, -10.033899, 0.6137, 6.6893, -10.033899, 0.6137, 3.3446, -6.6893, 0.6137, 3.3446, -10.033899, 0.6137, 6.6893, -6.6893, 0.6137, 3.3446, -6.6893, 0.6137, 6.6893, -10.033899, 0.6137, 6.6893, -13.677099, 0.6137, 5.2616, -14.4892, 0.6137, 4.2778, -13.677099, 0.6137, 5.2616, -10.033899, 0.6137, 6.6893, -12.747499, 0.6137, 6.3671, -6.6893, 0.6137, 3.3446, -2.5674999, 0.0266, 7.6215, -6.6893, 0.6137, 6.6893, -2.5674999, 0.0266, 7.6215, -6.6893, 0.6137, 3.3446, -3.3446, 0.6137, 3.3446, -2.5674999, 0.0266, 7.6215, -3.3446, 0.6137, 3.3446, -2.1193, 0.6137, 5.2736998, -16.7232, 3.0033998, 2.9166, -15.7546, 0.6137, 3.5372, -15.372, 3.0033998, 3.6132998, -16.7232, 3.0033998, 2.9166, -16.7232, 0.6137, 2.9166, -15.7546, 0.6137, 3.5372, -14.4892, 3.0033998, 4.2778, -13.677099, 0.6137, 5.2616, -13.6942, 3.0033998, 5.1798, -14.4892, 3.0033998, 4.2778, -14.4892, 0.6137, 4.2778, -13.677099, 0.6137, 5.2616, -15.8036995, 3.0033998, -2.7091, -16.7232, 0.6137, 0, -16.7232, 3.0033998, 0, -15.8036995, 3.0033998, -2.7091, -15.8036995, 0.6137, -2.7091, -16.7232, 0.6137, 0, -16.7232, 3.0033998, 0, -16.7232, 0.6137, 2.9166, -16.7232, 3.0033998, 2.9166, -16.7232, 3.0033998, 0, -16.7232, 0.6137, 0, -16.7232, 0.6137, 2.9166, -3.3446, 3.0033998, 0, -4.0257998, 0.6137, -1.6911999, -4.0257998, 3.0033998, -1.6911999, -3.3446, 3.0033998, 0, -3.3446, 0.6137, 0, -4.0257998, 0.6137, -1.6911999, -3.3446, 3.0033998, 3.3446, -3.3446, 0.6137, 0, -3.3446, 3.0033998, 0, -3.3446, 3.0033998, 3.3446, -3.3446, 0.6137, 3.3446, -3.3446, 0.6137, 0, -12.747499, 3.0033998, 6.3671, -10.033899, 0.6137, 6.6893, -10.033899, 3.0033998, 6.6893, -12.747499, 3.0033998, 6.3671, -12.747499, 0.6137, 6.3671, -10.033899, 0.6137, 6.6893, -10.033899, 3.0033998, -3.3446, -13.3786, 0.6137, -3.3446, -13.3786, 3.0033998, -3.3446, -10.033899, 3.0033998, -3.3446, -10.033899, 0.6137, -3.3446, -13.3786, 0.6137, -3.3446, -6.6893, 3.0033998, -3.3446, -10.033899, 0.6137, -3.3446, -10.033899, 3.0033998, -3.3446, -6.6893, 3.0033998, -3.3446, -6.6893, 0.6137, -3.3446, -10.033899, 0.6137, -3.3446, -13.3786, 3.0033998, -3.3446, -15.8036995, 0.6137, -2.7091, -15.8036995, 3.0033998, -2.7091, -13.3786, 3.0033998, -3.3446, -13.3786, 0.6137, -3.3446, -15.8036995, 0.6137, -2.7091, -4.0257998, 3.0033998, -1.6911999, -6.6893, 0.6137, -3.3446, -6.6893, 3.0033998, -3.3446, -4.0257998, 3.0033998, -1.6911999, -4.0257998, 0.6137, -1.6911999, -6.6893, 0.6137, -3.3446, -6.6893, 3.0033998, 6.6893, -2.5674999, 0.0266, 7.6215, -2.5674999, 2.4164, 7.6215, -6.6893, 3.0033998, 6.6893, -6.6893, 0.6137, 6.6893, -2.5674999, 0.0266, 7.6215, -10.033899, 3.0033998, 6.6893, -6.6893, 0.6137, 6.6893, -6.6893, 3.0033998, 6.6893, -10.033899, 3.0033998, 6.6893, -10.033899, 0.6137, 6.6893, -6.6893, 0.6137, 6.6893, -2.5674999, 2.4164, 7.6215, -2.1193, 0.6137, 5.2736998, -2.1397, 3.0033998, 5.1795, -2.5674999, 2.4164, 7.6215, -2.5674999, 0.0266, 7.6215, -2.1193, 0.6137, 5.2736998, -2.1193, 0.6137, 5.2736998, -3.3446, 3.0033998, 3.3446, -2.1397, 3.0033998, 5.1795, -2.1193, 0.6137, 5.2736998, -3.3446, 0.6137, 3.3446, -3.3446, 3.0033998, 3.3446, -13.677099, 0.6137, 5.2616, -12.747499, 3.0033998, 6.3671, -13.6942, 3.0033998, 5.1798, -13.677099, 0.6137, 5.2616, -12.747499, 0.6137, 6.3671, -12.747499, 3.0033998, 6.3671, -15.7546, 0.6137, 3.5372, -14.4892, 3.0033998, 4.2778, -15.372, 3.0033998, 3.6132998, -15.7546, 0.6137, 3.5372, -14.4892, 0.6137, 4.2778, -14.4892, 3.0033998, 4.2778, 21.1831, 0, -13.6544, 16.8204, 3.138, -13.447599, 18.0241, 0, -14.3019, 21.1831, 0, -13.6544, 20.1539, 3.1299, -13.399799, 16.8204, 3.138, -13.447599, 21.8888, 0, -10.033899, 20.1539, 3.1299, -13.399799, 21.1831, 0, -13.6544, 21.8888, 0, -10.033899, 20.198, 3.1490998, -10.033899, 20.1539, 3.1299, -13.399799, 17.2285, 0, -16.8036, 12.7471, 3.1766999, -16.1988, 13.7014, 0, -17.416399, 17.2285, 0, -16.8036, 16.756899, 3.1650999, -16.7286, 12.7471, 3.1766999, -16.1988, 16.8204, 3.138, -13.447599, 17.2285, 0, -16.8036, 18.0241, 0, -14.3019, 17.2285, 0, -16.8036, 16.8204, 3.138, -13.447599, 16.8051, 3.1778, -13.479, 17.2285, 0, -16.8036, 16.8051, 3.1778, -13.479, 16.756899, 3.1650999, -16.7286, 12.7471, 3.1766999, -16.1988, 13.3786, 0, -20.5992, 13.7014, 0, -17.416399, 13.3786, 0, -20.5992, 12.7471, 3.1766999, -16.1988, 12.747, 3.1771, -16.1991, 13.3786, 0, -20.5992, 12.747, 3.1771, -16.1991, 12.723599, 2.9213, -19.2902, 13.3786, 0, -20.5992, 10.033899, 3.0523999, -19.0294, 10.033899, 0, -20.467, 13.3786, 0, -20.5992, 12.723599, 2.9213, -19.2902, 10.033899, 3.0523999, -19.0294, 10.033899, 0, -20.467, 6.6893, 3.0440998, -19.036999, 6.6893, 0, -20.1318, 10.033899, 0, -20.467, 10.033899, 3.0523999, -19.0294, 6.6893, 3.0440998, -19.036999, 3.0140998, 0, -16.7232, 4.4131, 3.2091, -13.357699, 3.3446, -0.3989, -12.9443, 3.0140998, 0, -16.7232, 3.5895, 3.2033, -16.7232, 4.4131, 3.2091, -13.357699, 6.6893, 3.0440998, -19.036999, 3.3446, 0, -20.5992, 6.6893, 0, -20.1318, 3.3446, 0, -20.5992, 6.6893, 3.0440998, -19.036999, 6.6640997, 3.0702, -19.018099, 3.3446, 0, -20.5992, 6.6640997, 3.0702, -19.018099, 4.4783998, 3.1067, -18.2665, 3.3446, 0, -20.5992, 3.5895, 3.2033, -16.7232, 3.0140998, 0, -16.7232, 3.3446, 0, -20.5992, 4.4783998, 3.1067, -18.2665, 3.5895, 3.2033, -16.7232, 2.8241, 0, -10.4594, 0, 3.179, -9.0652, 0, 0, -10.7654, 2.8241, 0, -10.4594, 3.7529, 3.1712, -9.0494995, 0, 3.179, -9.0652, 3.3446, -0.3989, -12.9443, 3.7529, 3.1712, -9.0494995, 2.8241, 0, -10.4594, 3.3446, -0.3989, -12.9443, 4.4131, 3.2091, -13.357699, 3.7529, 3.1712, -9.0494995, 4.4131, 3.2091, -13.357699, 3.3446, -0.3989, -12.9443, 4.4131, 3.2091, -13.357699, -2.6297, 0, -10.5745, -3.6538, 3.1585999, -12.813399, -3.3446, 0, -13.3786, -2.6297, 0, -10.5745, -3.6076, 3.1676, -10.0696, -3.6538, 3.1585999, -12.813399, -3.3446, 0, -13.3786, -6.6893, 3.175, -12.867, -6.6893, 0, -14.2637, -3.3446, 0, -13.3786, -3.6538, 3.1585999, -12.813399, -6.6893, 3.175, -12.867, 0, 3.179, -9.0652, -2.6297, 0, -10.5745, 0, 0, -10.7654, -2.6297, 0, -10.5745, 0, 3.179, -9.0652, -0.0081, 3.1864998, -9.063499, -2.6297, 0, -10.5745, -0.0081, 3.1864998, -9.063499, -3.6076, 3.1676, -10.0696, -6.6893, 0, -14.2637, -10.4043, 3.1608999, -13.4295, -9.6168995, 0, -14.127899, -6.6893, 0, -14.2637, -6.6893, 3.175, -12.867, -10.4043, 3.1608999, -13.4295, -6.6893, 3.175, -12.867, -6.6893, 0, -14.2637, -6.6893, 3.175, -12.867, -9.6168995, 0, -14.127899, -10.4319, 3.1557999, -16.1556, -10.033899, 0, -16.7232, -9.6168995, 0, -14.127899, -10.4043, 3.1608999, -13.4295, -10.4319, 3.1557999, -16.1556, -10.033899, 0, -16.7232, -13.3786, 3.1771998, -15.7625, -13.3786, 0, -17.3364, -10.033899, 0, -16.7232, -10.4319, 3.1557999, -16.1556, -13.3786, 3.1771998, -15.7625, -16.7232, 0, -16.7232, -16.3753, 3.4225, -13.6277, -16.7232, 0, -13.3786, -16.7232, 0, -16.7232, -16.0243, 3.3509998, -15.752, -16.3753, 3.4225, -13.6277, -13.3786, 3.1771998, -15.7625, -16.7232, 0, -16.7232, -13.3786, 0, -17.3364, -16.7232, 0, -16.7232, -13.3786, 3.1771998, -15.7625, -13.3911, 3.1892, -15.757, -16.7232, 0, -16.7232, -13.3911, 3.1892, -15.757, -16.0243, 3.3509998, -15.752, -17.275, 0, -10.5169, -19.6237, 3.1655998, -9.757899, -20.0679, 0, -10.033899, -17.275, 0, -10.5169, -16.4131, 3.1706, -9.788899, -19.6237, 3.1655998, -9.757899, -16.7232, 0, -13.3786, -16.4131, 3.1706, -9.788899, -17.275, 0, -10.5169, -16.7232, 0, -13.3786, -16.3753, 3.4225, -13.6277, -16.4131, 3.1706, -9.788899, -16.3753, 3.4225, -13.6277, -16.7232, 0, -13.3786, -16.3753, 3.4225, -13.6277, -20.3764, 0, -6.6893, -19.9489, 3.2063, -2.8082, -20.0679, -0.3484, -3.5669, -20.3764, 0, -6.6893, -19.515, 3.2122, -6.6893, -19.9489, 3.2063, -2.8082, -19.6237, 3.1655998, -9.757899, -20.3764, 0, -6.6893, -20.0679, 0, -10.033899, -20.3764, 0, -6.6893, -19.6237, 3.1655998, -9.757899, -19.6161, 3.2075999, -9.7116995, -20.3764, 0, -6.6893, -19.6161, 3.2075999, -9.7116995, -19.515, 3.2122, -6.6893, -23.412498, -0.2913, 0.26119998, -23.0809, 3.3083, 3.3615, -23.412498, 0, 3.3446, -23.412498, -0.2913, 0.26119998, -23.3676, 3.4459999, 0.1372, -23.0809, 3.3083, 3.3615, -23.412498, 0, -3.3446, -23.3676, 3.4459999, 0.1372, -23.412498, -0.2913, 0.26119998, -23.412498, 0, -3.3446, -23.390299, 3.3349998, -2.6938999, -23.3676, 3.4459999, 0.1372, -20.0679, -0.3484, -3.5669, -23.390299, 3.3349998, -2.6938999, -23.412498, 0, -3.3446, -20.0679, -0.3484, -3.5669, -19.9489, 3.2063, -2.8082, -23.390299, 3.3349998, -2.6938999, -19.9489, 3.2063, -2.8082, -20.0679, -0.3484, -3.5669, -19.9489, 3.2063, -2.8082, -23.0809, 3.3083, 3.3615, -23.8078, 0, 6.6893, -23.412498, 0, 3.3446, -23.8078, 0, 6.6893, -23.0809, 3.3083, 3.3615, -23.0777, 3.3197, 3.3734, -23.8078, 0, 6.6893, -23.0777, 3.3197, 3.3734, -22.563799, 3.2219, 6.6893, -23.8078, 0, 6.6893, -22.791399, 3.2124999, 9.4432, -23.412498, 0, 10.033899, -23.8078, 0, 6.6893, -22.563799, 3.2219, 6.6893, -22.791399, 3.2124999, 9.4432, -23.412498, 0, 10.033899, -20.0679, 3.1943, 9.407499, -20.0679, 0, 10.033899, -23.412498, 0, 10.033899, -22.791399, 3.2124999, 9.4432, -20.0679, 3.1943, 9.407499, -22.791399, 3.2124999, 9.4432, -23.412498, 0, 10.033899, -22.791399, 3.2124999, 9.4432, -20.0679, 0, 10.033899, -16.2818, 3.1913998, 9.8056, -16.7232, 0, 10.033899, -20.0679, 0, 10.033899, -20.0679, 3.1943, 9.407499, -16.2818, 3.1913998, 9.8056, -16.7232, 0, 13.3786, -13.3786, 3.194, 12.8089, -13.3786, 0, 13.3786, -16.7232, 0, 13.3786, -16.076399, 3.04, 12.735, -13.3786, 3.194, 12.8089, -16.7232, 0, 10.033899, -16.076399, 3.04, 12.735, -16.7232, 0, 13.3786, -16.7232, 0, 10.033899, -16.2818, 3.1913998, 9.8056, -16.076399, 3.04, 12.735, -16.2818, 3.1913998, 9.8056, -16.7232, 0, 10.033899, -16.2818, 3.1913998, 9.8056, -13.3786, 0, 13.3786, -10.033899, 2.9384, 12.4537, -10.033899, 0, 13.3786, -13.3786, 0, 13.3786, -13.3786, 3.194, 12.8089, -10.033899, 2.9384, 12.4537, -13.3786, 3.194, 12.8089, -13.3786, 0, 13.3786, -13.3786, 3.194, 12.8089, -10.033899, 0, 13.3786, -6.2748, 3.126, 13.122, -6.6893, 0, 13.3786, -10.033899, 0, 13.3786, -10.033899, 2.9384, 12.4537, -6.2748, 3.126, 13.122, -6.6893, 0, 13.3786, -6.2748, 3.1260998, 16.4145, -6.6893, 0, 16.7232, -6.6893, 0, 13.3786, -6.2748, 3.126, 13.122, -6.2748, 3.1260998, 16.4145, -3.3446, 0, 16.7232, 0, 2.9636998, 16.0179, 0, 0, 16.7232, -3.3446, 0, 16.7232, -3.3446, 3.1497998, 15.914599, 0, 2.9636998, 16.0179, 0, 0, 16.7232, 3.6425998, 3.1413999, 16.5127, 3.3446, 0, 16.7232, 0, 0, 16.7232, 0, 2.9636998, 16.0179, 3.6425998, 3.1413999, 16.5127, -6.2748, 3.1260998, 16.4145, -3.3446, 0, 16.7232, -6.6893, 0, 16.7232, -3.3446, 0, 16.7232, -6.2748, 3.1260998, 16.4145, -6.2558, 3.1427999, 16.4098, -3.3446, 0, 16.7232, -6.2558, 3.1427999, 16.4098, -3.3446, 3.1497998, 15.914599, 3.3446, 0, 20.0679, 6.6893, 3.2050998, 19.228699, 6.6893, 0, 20.0679, 3.3446, 0, 20.0679, 3.9266999, 3.5967, 19.6223, 6.6893, 3.2050998, 19.228699, 3.6425998, 3.1413999, 16.5127, 3.3446, 0, 20.0679, 3.3446, 0, 16.7232, 3.3446, 0, 20.0679, 3.6425998, 3.1413999, 16.5127, 3.6536, 3.2078998, 16.5669, 3.3446, 0, 20.0679, 3.6536, 3.2078998, 16.5669, 3.9266999, 3.5967, 19.6223, 6.6893, 3.2050998, 19.228699, 10.572599, 0, 20.0679, 6.6893, 0, 20.0679, 10.572599, 0, 20.0679, 6.6893, 3.2050998, 19.228699, 6.6991997, 3.2148, 19.2255, 10.572599, 0, 20.0679, 6.6991997, 3.2148, 19.2255, 9.3066, 3.2186, 19.0653, 10.572599, 0, 20.0679, 10.5913, 3.1985998, 16.7232, 10.572599, 0, 16.7232, 10.572599, 0, 20.0679, 9.3066, 3.2186, 19.0653, 10.5913, 3.1985998, 16.7232, 10.5913, 3.1985998, 16.7232, 10.572599, 0, 13.918799, 10.572599, 0, 16.7232, 10.572599, 0, 13.918799, 10.5913, 3.1985998, 16.7232, 10.5893, 3.2117, 16.7106, 10.572599, 0, 13.918799, 10.5893, 3.2117, 16.7106, 10.0546, 3.1885, 13.4071, 10.572599, 0, 13.918799, 13.2631, 3.5611, 13.4043, 13.8046, 0, 13.918799, 10.572599, 0, 13.918799, 10.0546, 3.1885, 13.4071, 13.2631, 3.5611, 13.4043, 13.8046, 0, 13.918799, 12.9758, 3.2036, 10.033899, 13.8046, 0, 10.033899, 13.8046, 0, 13.918799, 13.2631, 3.5611, 13.4043, 12.9758, 3.2036, 10.033899, 13.8046, 0, 13.918799, 13.2631, 3.5611, 13.4043, 13.2631, 3.5611, 13.4043, 13.8046, 0, 10.033899, 13.4036, 3.0749998, 6.6893, 13.8046, 0, 6.6893, 13.8046, 0, 10.033899, 12.9758, 3.2036, 10.033899, 13.4036, 3.0749998, 6.6893, 20.961199, 0, -3.3446, 16.7127, 2.8734, -3.3446, 20.144999, 2.7605999, -3.3446, 20.961199, 0, -3.3446, 14.0489, 3.0042, -3.3446, 16.7127, 2.8734, -3.3446, 20.144999, 2.7605999, -3.3446, 21.2349, 0, -6.6893, 20.961199, 0, -3.3446, 21.2349, 0, -6.6893, 20.144999, 2.7605999, -3.3446, 20.1349, 2.7974, -3.3783998, 21.2349, 0, -6.6893, 20.1349, 2.7974, -3.3783998, 20.147, 3.0588999, -6.6893, 20.147, 3.0588999, -6.6893, 21.8888, 0, -10.033899, 21.2349, 0, -6.6893, 21.8888, 0, -10.033899, 20.147, 3.0588999, -6.6893, 20.1796, 3.182, -9.995999, 21.8888, 0, -10.033899, 20.1796, 3.182, -9.995999, 20.198, 3.1490998, -10.033899, 23.412498, 0, -26.7572, 26.7572, -0.2593, -23.412498, 23.412498, 0, -23.412498, 26.7572, -0.2593, -23.412498, 23.412498, 0, -26.7572, 26.7572, -0.2593, -25.084799, 26.7572, -0.2593, -25.084799, 23.412498, 0, -26.7572, 26.7572, -0.2593, -26.7572, 26.7572, -0.2593, -21.7402, 23.412498, 0, -23.412498, 26.7572, -0.2593, -23.412498, 26.7572, -0.2593, -20.0679, 23.412498, 0, -23.412498, 26.7572, -0.2593, -21.7402, 23.412498, 0, -23.412498, 26.7572, -0.2593, -20.0679, 23.412498, 0, -20.0679, 26.7572, -0.2593, -18.3955, 23.412498, 0, -20.0679, 26.7572, -0.2593, -20.0679, 26.7572, -0.2593, -16.7232, 23.412498, 0, -20.0679, 26.7572, -0.2593, -18.3955, 23.412498, 0, -20.0679, 26.7572, -0.2593, -16.7232, 23.412498, 0, -16.7232, 26.7572, -0.2593, -15.0508995, 23.412498, 0, -16.7232, 26.7572, -0.2593, -16.7232, 26.7572, -0.2593, -13.3786, 23.412498, 0, -16.7232, 26.7572, -0.2593, -15.0508995, 23.412498, 0, -16.7232, 26.7572, -0.2593, -13.3786, 23.412498, 0, -13.3786, 26.7572, -0.2593, -11.7063, 23.412498, 0, -13.3786, 26.7572, -0.2593, -13.3786, 26.7572, -0.2593, -10.033899, 23.412498, 0, -13.3786, 26.7572, -0.2593, -11.7063, 23.412498, 0, -13.3786, 26.7572, -0.2593, -10.033899, 23.412498, 0, -10.033899, 26.7572, -0.2593, -8.3616, 23.412498, 0, -10.033899, 26.7572, -0.2593, -10.033899, 26.7572, -0.2593, -6.6893, 23.412498, 0, -10.033899, 26.7572, -0.2593, -8.3616, 23.412498, 0, -10.033899, 26.7572, -0.2593, -6.6893, 23.412498, 0, -6.6893, 26.7572, -0.2593, -5.0169997, 23.412498, 0, -6.6893, 26.7572, -0.2593, -6.6893, 26.7572, -0.2593, -3.3446, 23.412498, 0, -6.6893, 26.7572, -0.2593, -5.0169997, 23.412498, 0, -6.6893, 26.7572, -0.2593, -3.3446, 23.412498, 0, -3.3446, 26.7572, -0.2593, -1.6723, 23.412498, 0, -3.3446, 26.7572, -0.2593, -3.3446, 26.7572, -0.2593, 0, 23.412498, 0, -3.3446, 26.7572, -0.2593, -1.6723, 23.412498, 0, -3.3446, 26.7572, -0.2593, 0, 23.412498, 0, 0, 26.7572, -0.2593, 1.6723, 23.412498, 0, 0, 26.7572, -0.2593, 0, 26.7572, -0.2593, 3.3446, 23.412498, 0, 0, 26.7572, -0.2593, 1.6723, 23.412498, 0, 0, 26.7572, -0.2593, 3.3446, 23.412498, 0, 3.3446, 26.7572, -0.2593, 5.0169997, 23.412498, 0, 3.3446, 26.7572, -0.2593, 3.3446, 26.7572, -0.2593, 6.6893, 23.412498, 0, 3.3446, 26.7572, -0.2593, 5.0169997, 23.412498, 0, 3.3446, 26.7572, -0.2593, 6.6893, 23.412498, 0, 6.6893, 26.7572, -0.2593, 8.3616, 23.412498, 0, 6.6893, 26.7572, -0.2593, 6.6893, 26.7572, -0.2593, 10.033899, 23.412498, 0, 6.6893, 26.7572, -0.2593, 8.3616, 23.412498, 0, 6.6893, 26.7572, -0.2593, 10.033899, 23.412498, 0, 10.033899, 26.7572, -0.2593, 11.7063, 23.412498, 0, 10.033899, 26.7572, -0.2593, 10.033899, 26.7572, -0.2593, 13.3786, 23.412498, 0, 10.033899, 26.7572, -0.2593, 11.7063, 23.412498, 0, 10.033899, 26.7572, -0.2593, 13.3786, 23.412498, 0, 13.3786, 26.7572, -0.2593, 15.0508995, 23.412498, 0, 13.3786, 26.7572, -0.2593, 13.3786, 26.7572, -0.2593, 16.7232, 23.412498, 0, 13.3786, 26.7572, -0.2593, 15.0508995, 23.412498, 0, 13.3786, 26.7572, -0.2593, 16.7232, 23.412498, 0, 16.7232, 26.7572, -0.2593, 18.3955, 23.412498, 0, 16.7232, 26.7572, -0.2593, 16.7232, 26.7572, -0.2593, 20.0679, 23.412498, 0, 16.7232, 26.7572, -0.2593, 18.3955, 23.412498, 0, 16.7232, 26.7572, -0.2593, 20.0679, 23.412498, 0, 20.0679, 26.7572, -0.2593, 21.7402, 23.412498, 0, 20.0679, 26.7572, -0.2593, 20.0679, 26.7572, -0.2593, 23.412498, 23.412498, 0, 20.0679, 26.7572, -0.2593, 21.7402, 23.412498, 0, 20.0679, 26.7572, -0.2593, 23.412498, 23.412498, 0, 23.412498, 26.7572, -0.2593, 25.084799, 23.412498, 0, 23.412498, 26.7572, -0.2593, 23.412498, 26.7572, -0.2593, 26.7572, 23.412498, 0, 23.412498, 26.7572, -0.2593, 25.084799, 23.412498, 0, 23.412498, 26.7572, -0.2593, 26.7572, 23.412498, 0, 26.7572, -3.3446, 0, -23.412498, 0, 0, -26.7572, 0, 0, -23.412498, 0, 0, -23.412498, 0, 0, -26.7572, 3.3446, 0, -26.7572, -3.3446, 0, -23.412498, -3.3446, 0, -26.7572, 0, 0, -26.7572, 0, 0, -23.412498, 3.3446, 0, -26.7572, 3.3446, 0, -23.412498, 3.3446, 0, -23.412498, 3.3446, 0, -26.7572, 6.6893, 0, -26.7572, -3.3446, 0, -20.0679, -3.3446, 0, -23.412498, 0, 0, -23.412498, 3.3446, 0, -23.412498, 6.6893, 0, -26.7572, 6.6893, 0, -23.412498, 6.6893, 0, -23.412498, 6.6893, 0, -26.7572, 10.033899, 0, -26.7572, 0, 0, -20.0679, 0, 0, -23.412498, 3.3446, 0, -23.412498, -3.3446, 0, -20.0679, 0, 0, -23.412498, 0, 0, -20.0679, 3.3446, 0, -20.5992, 3.3446, 0, -23.412498, 6.6893, 0, -23.412498, 0, 0, -20.0679, 3.3446, 0, -23.412498, 3.3446, 0, -20.5992, 3.3446, 0, -20.5992, 6.6893, 0, -23.412498, 6.6893, 0, -20.1318, 6.6893, 0, -23.412498, 10.033899, 0, -26.7572, 10.033899, 0, -23.412498, 6.6893, 0, -20.1318, 6.6893, 0, -23.412498, 10.033899, 0, -23.412498, 10.033899, 0, -23.412498, 10.033899, 0, -26.7572, 13.3786, 0, -26.7572, 6.6893, 0, -20.1318, 10.033899, 0, -23.412498, 10.033899, 0, -20.467, 10.033899, 0, -23.412498, 13.3786, 0, -26.7572, 13.3786, 0, -23.412498, 10.033899, 0, -20.467, 10.033899, 0, -23.412498, 13.3786, 0, -23.412498, 13.3786, 0, -23.412498, 13.3786, 0, -26.7572, 16.7232, 0, -26.7572, 10.033899, 0, -20.467, 13.3786, 0, -23.412498, 13.3786, 0, -20.5992, 13.3786, 0, -23.412498, 16.7232, 0, -26.7572, 16.7232, 0, -23.412498, 13.3786, 0, -20.5992, 13.3786, 0, -23.412498, 16.7232, 0, -23.412498, 16.7232, 0, -23.412498, 16.7232, 0, -26.7572, 20.0679, 0, -26.7572, 13.3786, 0, -20.5992, 16.7232, 0, -23.412498, 16.7232, 0, -20.0679, 13.7014, 0, -17.416399, 13.3786, 0, -20.5992, 16.7232, 0, -20.0679, 13.7014, 0, -17.416399, 16.7232, 0, -20.0679, 17.2285, 0, -16.8036, 16.7232, 0, -23.412498, 20.0679, 0, -26.7572, 20.0679, 0, -23.412498, 16.7232, 0, -20.0679, 16.7232, 0, -23.412498, 20.0679, 0, -23.412498, 20.0679, 0, -23.412498, 20.0679, 0, -26.7572, 23.412498, 0, -26.7572, 20.0679, 0, -23.412498, 23.412498, 0, -26.7572, 23.412498, 0, -23.412498, 16.7232, 0, -20.0679, 20.0679, 0, -23.412498, 20.0679, 0, -20.0679, 20.0679, 0, -20.0679, 20.0679, 0, -23.412498, 23.412498, 0, -23.412498, 17.2285, 0, -16.8036, 16.7232, 0, -20.0679, 20.0679, 0, -20.0679, 20.0679, 0, -20.0679, 23.412498, 0, -23.412498, 23.412498, 0, -20.0679, 17.2285, 0, -16.8036, 20.0679, 0, -20.0679, 20.0679, 0, -16.7232, 20.0679, 0, -16.7232, 20.0679, 0, -20.0679, 23.412498, 0, -20.0679, 18.0241, 0, -14.3019, 17.2285, 0, -16.8036, 20.0679, 0, -16.7232, 20.0679, 0, -16.7232, 23.412498, 0, -20.0679, 23.412498, 0, -16.7232, 18.0241, 0, -14.3019, 20.0679, 0, -16.7232, 21.1831, 0, -13.6544, 21.1831, 0, -13.6544, 20.0679, 0, -16.7232, 23.412498, 0, -16.7232, 21.1831, 0, -13.6544, 23.412498, 0, -16.7232, 23.412498, 0, -13.3786, 21.8888, 0, -10.033899, 21.1831, 0, -13.6544, 23.412498, 0, -13.3786, 21.8888, 0, -10.033899, 23.412498, 0, -13.3786, 23.412498, 0, -10.033899, 21.2349, 0, -6.6893, 21.8888, 0, -10.033899, 23.412498, 0, -10.033899, 21.2349, 0, -6.6893, 23.412498, 0, -10.033899, 23.412498, 0, -6.6893, 20.961199, 0, -3.3446, 21.2349, 0, -6.6893, 23.412498, 0, -6.6893, 20.961199, 0, -3.3446, 23.412498, 0, -6.6893, 23.412498, 0, -3.3446, 20.0679, 0, 0, 20.961199, 0, -3.3446, 23.412498, 0, -3.3446, 20.0679, 0, 0, 23.412498, 0, -3.3446, 23.412498, 0, 0, 20.0679, 0, 3.3446, 20.0679, 0, 0, 23.412498, 0, 0, 20.0679, 0, 3.3446, 23.412498, 0, 0, 23.412498, 0, 3.3446, 10.572599, 0, 16.7232, 13.8046, 0, 13.918799, 13.3786, 0, 16.7232, 10.572599, 0, 16.7232, 10.572599, 0, 13.918799, 13.8046, 0, 13.918799, 10.572599, 0, 20.0679, 10.572599, 0, 16.7232, 13.3786, 0, 16.7232, 13.3786, 0, 16.7232, 13.8046, 0, 13.918799, 15.0508995, 0, 13.3786, 10.572599, 0, 20.0679, 13.3786, 0, 16.7232, 13.3786, 0, 20.0679, 13.8046, 0, 13.918799, 15.0508995, 0, 10.033899, 15.0508995, 0, 13.3786, 13.8046, 0, 13.918799, 13.8046, 0, 10.033899, 15.0508995, 0, 10.033899, 13.8046, 0, 10.033899, 15.0508995, 0, 6.6893, 15.0508995, 0, 10.033899, 13.8046, 0, 10.033899, 13.8046, 0, 6.6893, 15.0508995, 0, 6.6893, 15.0508995, 0, 10.033899, 15.0508995, 0, 6.6893, 16.7232, 0, 6.6893, 15.0508995, 0, 10.033899, 16.7232, 0, 6.6893, 16.7232, 0, 10.033899, 15.0508995, 0, 13.3786, 15.0508995, 0, 10.033899, 16.7232, 0, 10.033899, 13.3786, 0, 16.7232, 15.0508995, 0, 13.3786, 15.0508995, 0, 16.7232, 13.3786, 0, 20.0679, 13.3786, 0, 16.7232, 15.0508995, 0, 16.7232, 15.0508995, 0, 13.3786, 16.7232, 0, 10.033899, 16.7232, 0, 13.3786, 15.0508995, 0, 16.7232, 15.0508995, 0, 13.3786, 16.7232, 0, 13.3786, 16.7232, 0, 13.3786, 16.7232, 0, 10.033899, 20.0679, 0, 10.033899, 16.7232, 0, 13.3786, 20.0679, 0, 10.033899, 20.0679, 0, 13.3786, 20.0679, 0, 13.3786, 20.0679, 0, 10.033899, 23.412498, 0, 10.033899, 20.0679, 0, 13.3786, 23.412498, 0, 10.033899, 23.412498, 0, 13.3786, 16.7232, 0, 16.7232, 16.7232, 0, 13.3786, 20.0679, 0, 13.3786, 15.0508995, 0, 16.7232, 16.7232, 0, 13.3786, 16.7232, 0, 16.7232, 20.0679, 0, 16.7232, 20.0679, 0, 13.3786, 23.412498, 0, 13.3786, 16.7232, 0, 16.7232, 20.0679, 0, 13.3786, 20.0679, 0, 16.7232, 20.0679, 0, 16.7232, 23.412498, 0, 13.3786, 23.412498, 0, 16.7232, 15.0508995, 0, 20.0679, 15.0508995, 0, 16.7232, 16.7232, 0, 16.7232, 13.3786, 0, 20.0679, 15.0508995, 0, 16.7232, 15.0508995, 0, 20.0679, 16.7232, 0, 20.0679, 16.7232, 0, 16.7232, 20.0679, 0, 16.7232, 15.0508995, 0, 20.0679, 16.7232, 0, 16.7232, 16.7232, 0, 20.0679, 20.0679, 0, 20.0679, 20.0679, 0, 16.7232, 23.412498, 0, 16.7232, 16.7232, 0, 20.0679, 20.0679, 0, 16.7232, 20.0679, 0, 20.0679, 20.0679, 0, 20.0679, 23.412498, 0, 16.7232, 23.412498, 0, 20.0679, 20.0679, 0, 23.412498, 20.0679, 0, 20.0679, 23.412498, 0, 20.0679, 20.0679, 0, 23.412498, 23.412498, 0, 20.0679, 23.412498, 0, 23.412498, 20.0679, 0, 26.7572, 20.0679, 0, 23.412498, 23.412498, 0, 23.412498, 20.0679, 0, 26.7572, 23.412498, 0, 23.412498, 23.412498, 0, 26.7572, 16.7232, 0, 26.7572, 20.0679, 0, 23.412498, 20.0679, 0, 26.7572, 16.7232, 0, 23.412498, 20.0679, 0, 20.0679, 20.0679, 0, 23.412498, 16.7232, 0, 26.7572, 16.7232, 0, 23.412498, 20.0679, 0, 23.412498, 16.7232, 0, 23.412498, 16.7232, 0, 20.0679, 20.0679, 0, 20.0679, 15.0508995, 0, 26.7572, 16.7232, 0, 23.412498, 16.7232, 0, 26.7572, 15.0508995, 0, 23.412498, 16.7232, 0, 20.0679, 16.7232, 0, 23.412498, 15.0508995, 0, 26.7572, 15.0508995, 0, 23.412498, 16.7232, 0, 23.412498, 15.0508995, 0, 23.412498, 15.0508995, 0, 20.0679, 16.7232, 0, 20.0679, 13.3786, 0, 26.7572, 15.0508995, 0, 23.412498, 15.0508995, 0, 26.7572, 13.3786, 0, 23.412498, 15.0508995, 0, 20.0679, 15.0508995, 0, 23.412498, 13.3786, 0, 26.7572, 13.3786, 0, 23.412498, 15.0508995, 0, 23.412498, 13.3786, 0, 23.412498, 13.3786, 0, 20.0679, 15.0508995, 0, 20.0679, 10.033899, 0, 26.7572, 13.3786, 0, 23.412498, 13.3786, 0, 26.7572, 10.033899, 0, 23.412498, 13.3786, 0, 20.0679, 13.3786, 0, 23.412498, 10.033899, 0, 26.7572, 10.033899, 0, 23.412498, 13.3786, 0, 23.412498, 10.033899, 0, 23.412498, 10.572599, 0, 20.0679, 13.3786, 0, 20.0679, 6.6893, 0, 26.7572, 10.033899, 0, 23.412498, 10.033899, 0, 26.7572, 6.6893, 0, 23.412498, 10.572599, 0, 20.0679, 10.033899, 0, 23.412498, 6.6893, 0, 26.7572, 6.6893, 0, 23.412498, 10.033899, 0, 23.412498, 6.6893, 0, 23.412498, 6.6893, 0, 20.0679, 10.572599, 0, 20.0679, 3.3446, 0, 26.7572, 6.6893, 0, 23.412498, 6.6893, 0, 26.7572, 3.3446, 0, 23.412498, 6.6893, 0, 20.0679, 6.6893, 0, 23.412498, 3.3446, 0, 26.7572, 3.3446, 0, 23.412498, 6.6893, 0, 23.412498, 3.3446, 0, 23.412498, 3.3446, 0, 20.0679, 6.6893, 0, 20.0679, 0, 0, 26.7572, 3.3446, 0, 23.412498, 3.3446, 0, 26.7572, 0, 0, 26.7572, 0, 0, 23.412498, 3.3446, 0, 23.412498, 0, 0, 23.412498, 3.3446, 0, 20.0679, 3.3446, 0, 23.412498, -3.3446, 0, 26.7572, 0, 0, 23.412498, 0, 0, 26.7572, 0, 0, 23.412498, 0, 0, 20.0679, 3.3446, 0, 20.0679, 0, 0, 20.0679, 3.3446, 0, 16.7232, 3.3446, 0, 20.0679, 0, 0, 20.0679, 0, 0, 16.7232, 3.3446, 0, 16.7232, -3.3446, 0, 26.7572, -3.3446, 0, 23.412498, 0, 0, 23.412498, -3.3446, 0, 23.412498, 0, 0, 20.0679, 0, 0, 23.412498, -6.6893, 0, 26.7572, -3.3446, 0, 23.412498, -3.3446, 0, 26.7572, -3.3446, 0, 20.0679, 0, 0, 16.7232, 0, 0, 20.0679, -3.3446, 0, 23.412498, -3.3446, 0, 20.0679, 0, 0, 20.0679, -3.3446, 0, 20.0679, -3.3446, 0, 16.7232, 0, 0, 16.7232, -6.6893, 0, 26.7572, -6.6893, 0, 23.412498, -3.3446, 0, 23.412498, -6.6893, 0, 23.412498, -3.3446, 0, 20.0679, -3.3446, 0, 23.412498, -10.033899, 0, 26.7572, -6.6893, 0, 23.412498, -6.6893, 0, 26.7572, -6.6893, 0, 20.0679, -3.3446, 0, 16.7232, -3.3446, 0, 20.0679, -6.6893, 0, 23.412498, -6.6893, 0, 20.0679, -3.3446, 0, 20.0679, -6.6893, 0, 20.0679, -6.6893, 0, 16.7232, -3.3446, 0, 16.7232, -10.033899, 0, 26.7572, -10.033899, 0, 23.412498, -6.6893, 0, 23.412498, -10.033899, 0, 23.412498, -6.6893, 0, 20.0679, -6.6893, 0, 23.412498, -13.3786, 0, 26.7572, -10.033899, 0, 23.412498, -10.033899, 0, 26.7572, -10.033899, 0, 20.0679, -6.6893, 0, 16.7232, -6.6893, 0, 20.0679, -10.033899, 0, 23.412498, -10.033899, 0, 20.0679, -6.6893, 0, 20.0679, -13.3786, 0, 26.7572, -13.3786, 0, 23.412498, -10.033899, 0, 23.412498, -13.3786, 0, 23.412498, -10.033899, 0, 20.0679, -10.033899, 0, 23.412498, -16.7232, 0, 26.7572, -13.3786, 0, 23.412498, -13.3786, 0, 26.7572, -10.033899, 0, 20.0679, -10.033899, 0, 16.7232, -6.6893, 0, 16.7232, -10.033899, 0, 16.7232, -6.6893, 0, 13.3786, -6.6893, 0, 16.7232, -10.033899, 0, 16.7232, -10.033899, 0, 13.3786, -6.6893, 0, 13.3786, -13.3786, 0, 20.0679, -10.033899, 0, 16.7232, -10.033899, 0, 20.0679, -13.3786, 0, 23.412498, -13.3786, 0, 20.0679, -10.033899, 0, 20.0679, -13.3786, 0, 16.7232, -10.033899, 0, 13.3786, -10.033899, 0, 16.7232, -13.3786, 0, 20.0679, -13.3786, 0, 16.7232, -10.033899, 0, 16.7232, -13.3786, 0, 16.7232, -13.3786, 0, 13.3786, -10.033899, 0, 13.3786, -16.7232, 0, 26.7572, -16.7232, 0, 23.412498, -13.3786, 0, 23.412498, -16.7232, 0, 23.412498, -13.3786, 0, 20.0679, -13.3786, 0, 23.412498, -20.0679, 0, 26.7572, -16.7232, 0, 23.412498, -16.7232, 0, 26.7572, -16.7232, 0, 20.0679, -13.3786, 0, 16.7232, -13.3786, 0, 20.0679, -16.7232, 0, 23.412498, -16.7232, 0, 20.0679, -13.3786, 0, 20.0679, -16.7232, 0, 16.7232, -13.3786, 0, 13.3786, -13.3786, 0, 16.7232, -16.7232, 0, 20.0679, -16.7232, 0, 16.7232, -13.3786, 0, 16.7232, -16.7232, 0, 16.7232, -16.7232, 0, 13.3786, -13.3786, 0, 13.3786, -20.0679, 0, 26.7572, -20.0679, 0, 23.412498, -16.7232, 0, 23.412498, -20.0679, 0, 23.412498, -16.7232, 0, 20.0679, -16.7232, 0, 23.412498, -23.412498, 0, 26.7572, -20.0679, 0, 23.412498, -20.0679, 0, 26.7572, -20.0679, 0, 20.0679, -16.7232, 0, 16.7232, -16.7232, 0, 20.0679, -20.0679, 0, 23.412498, -20.0679, 0, 20.0679, -16.7232, 0, 20.0679, -23.412498, 0, 26.7572, -23.412498, 0, 23.412498, -20.0679, 0, 23.412498, -23.412498, 0, 23.412498, -20.0679, 0, 20.0679, -20.0679, 0, 23.412498, -26.7572, 0, 26.7572, -23.412498, 0, 23.412498, -23.412498, 0, 26.7572, -26.7572, 0, 26.7572, -26.7572, 0, 23.412498, -23.412498, 0, 23.412498, -26.7572, 0, 23.412498, -23.412498, 0, 20.0679, -23.412498, 0, 23.412498, -23.412498, 0, 23.412498, -23.412498, 0, 20.0679, -20.0679, 0, 20.0679, -26.7572, 0, 23.412498, -26.7572, 0, 20.0679, -23.412498, 0, 20.0679, -20.0679, 0, 20.0679, -20.0679, 0, 16.7232, -16.7232, 0, 16.7232, -23.412498, 0, 20.0679, -20.0679, 0, 16.7232, -20.0679, 0, 20.0679, -20.0679, 0, 16.7232, -16.7232, 0, 13.3786, -16.7232, 0, 16.7232, -26.7572, 0, 20.0679, -23.412498, 0, 16.7232, -23.412498, 0, 20.0679, -23.412498, 0, 20.0679, -23.412498, 0, 16.7232, -20.0679, 0, 16.7232, -26.7572, 0, 20.0679, -26.7572, 0, 16.7232, -23.412498, 0, 16.7232, -20.0679, 0, 16.7232, -20.0679, 0, 13.3786, -16.7232, 0, 13.3786, -23.412498, 0, 16.7232, -20.0679, 0, 13.3786, -20.0679, 0, 16.7232, -20.0679, 0, 13.3786, -16.7232, 0, 10.033899, -16.7232, 0, 13.3786, -20.0679, 0, 13.3786, -20.0679, 0, 10.033899, -16.7232, 0, 10.033899, -23.412498, 0, 16.7232, -23.412498, 0, 13.3786, -20.0679, 0, 13.3786, -23.412498, 0, 13.3786, -20.0679, 0, 10.033899, -20.0679, 0, 13.3786, -26.7572, 0, 16.7232, -23.412498, 0, 13.3786, -23.412498, 0, 16.7232, -23.412498, 0, 13.3786, -23.412498, 0, 10.033899, -20.0679, 0, 10.033899, -26.7572, 0, 16.7232, -26.7572, 0, 13.3786, -23.412498, 0, 13.3786, -26.7572, 0, 13.3786, -23.412498, 0, 10.033899, -23.412498, 0, 13.3786, -26.7572, 0, 13.3786, -26.7572, 0, 10.033899, -23.412498, 0, 10.033899, -26.7572, 0, 10.033899, -23.8078, 0, 6.6893, -23.412498, 0, 10.033899, -26.7572, 0, 10.033899, -26.7572, 0, 6.6893, -23.8078, 0, 6.6893, -26.7572, 0, 6.6893, -23.412498, 0, 3.3446, -23.8078, 0, 6.6893, -26.7572, 0, 6.6893, -26.7572, 0, 3.3446, -23.412498, 0, 3.3446, -16.7232, 0, -23.412498, -13.3786, 0, -26.7572, -13.3786, 0, -23.412498, -13.3786, 0, -23.412498, -13.3786, 0, -26.7572, -10.033899, 0, -26.7572, -16.7232, 0, -23.412498, -16.7232, 0, -26.7572, -13.3786, 0, -26.7572, -13.3786, 0, -23.412498, -10.033899, 0, -26.7572, -10.033899, 0, -23.412498, -10.033899, 0, -23.412498, -10.033899, 0, -26.7572, -6.6893, 0, -26.7572, -16.7232, 0, -20.0679, -16.7232, 0, -23.412498, -13.3786, 0, -23.412498, -10.033899, 0, -23.412498, -6.6893, 0, -26.7572, -6.6893, 0, -23.412498, -6.6893, 0, -23.412498, -6.6893, 0, -26.7572, -3.3446, 0, -26.7572, -6.6893, 0, -23.412498, -3.3446, 0, -26.7572, -3.3446, 0, -23.412498, -13.3786, 0, -20.0679, -13.3786, 0, -23.412498, -10.033899, 0, -23.412498, -16.7232, 0, -20.0679, -13.3786, 0, -23.412498, -13.3786, 0, -20.0679, -10.033899, 0, -20.0679, -10.033899, 0, -23.412498, -6.6893, 0, -23.412498, -13.3786, 0, -20.0679, -10.033899, 0, -23.412498, -10.033899, 0, -20.0679, -6.6893, 0, -20.0679, -6.6893, 0, -23.412498, -3.3446, 0, -23.412498, -10.033899, 0, -20.0679, -6.6893, 0, -23.412498, -6.6893, 0, -20.0679, -6.6893, 0, -20.0679, -3.3446, 0, -23.412498, -3.3446, 0, -20.0679, -13.3786, 0, -17.3364, -13.3786, 0, -20.0679, -10.033899, 0, -20.0679, -13.3786, 0, -17.3364, -10.033899, 0, -20.0679, -10.033899, 0, -16.7232, -10.033899, 0, -16.7232, -10.033899, 0, -20.0679, -6.6893, 0, -20.0679, -16.7232, 0, -16.7232, -13.3786, 0, -20.0679, -13.3786, 0, -17.3364, -16.7232, 0, -16.7232, -16.7232, 0, -20.0679, -13.3786, 0, -20.0679, -10.033899, 0, -16.7232, -6.6893, 0, -20.0679, -6.6893, 0, -16.7232, -6.6893, 0, -16.7232, -6.6893, 0, -20.0679, -3.3446, 0, -20.0679, -9.6168995, 0, -14.127899, -10.033899, 0, -16.7232, -6.6893, 0, -16.7232, -9.6168995, 0, -14.127899, -6.6893, 0, -16.7232, -6.6893, 0, -14.2637, -6.6893, 0, -16.7232, -3.3446, 0, -20.0679, -3.3446, 0, -16.7232, -6.6893, 0, -14.2637, -6.6893, 0, -16.7232, -3.3446, 0, -16.7232, -3.3446, 0, -16.7232, -3.3446, 0, -20.0679, 0, 0, -20.0679, -6.6893, 0, -14.2637, -3.3446, 0, -16.7232, -3.3446, 0, -13.3786, -3.3446, 0, -16.7232, 0, 0, -20.0679, 0, 0, -16.7232, -3.3446, 0, -13.3786, -3.3446, 0, -16.7232, 0, 0, -16.7232, 0, 0, -16.7232, 0, 0, -20.0679, 3.3446, 0, -20.5992, 0, 0, -16.7232, 3.3446, 0, -20.5992, 3.0140998, 0, -16.7232, -3.3446, 0, -13.3786, 0, 0, -16.7232, 0, 0, -13.3786, -2.6297, 0, -10.5745, -3.3446, 0, -13.3786, 0, 0, -13.3786, -2.6297, 0, -10.5745, 0, 0, -13.3786, 0, 0, -10.7654, -20.0679, 0, -16.7232, -16.7232, 0, -20.0679, -16.7232, 0, -16.7232, -20.0679, 0, -16.7232, -20.0679, 0, -20.0679, -16.7232, 0, -20.0679, -20.0679, 0, -20.0679, -16.7232, 0, -23.412498, -16.7232, 0, -20.0679, -20.0679, 0, -13.3786, -20.0679, 0, -16.7232, -16.7232, 0, -16.7232, -20.0679, 0, -13.3786, -16.7232, 0, -16.7232, -16.7232, 0, -13.3786, -23.412498, 0, -16.7232, -20.0679, 0, -20.0679, -20.0679, 0, -16.7232, -20.0679, 0, -10.033899, -20.0679, 0, -13.3786, -16.7232, 0, -13.3786, -20.0679, 0, -10.033899, -16.7232, 0, -13.3786, -17.275, 0, -10.5169, -23.412498, 0, -13.3786, -20.0679, 0, -16.7232, -20.0679, 0, -13.3786, -23.412498, 0, -13.3786, -23.412498, 0, -16.7232, -20.0679, 0, -16.7232, -23.412498, 0, -10.033899, -20.0679, 0, -13.3786, -20.0679, 0, -10.033899, -23.412498, 0, -10.033899, -23.412498, 0, -13.3786, -20.0679, 0, -13.3786, -26.7572, 0, -10.033899, -23.412498, 0, -13.3786, -23.412498, 0, -10.033899, -26.7572, 0, -10.033899, -26.7572, 0, -13.3786, -23.412498, 0, -13.3786, -26.7572, 0, -13.3786, -23.412498, 0, -16.7232, -23.412498, 0, -13.3786, -26.7572, 0, -6.6893, -26.7572, 0, -10.033899, -23.412498, 0, -10.033899, -26.7572, 0, -13.3786, -26.7572, 0, -16.7232, -23.412498, 0, -16.7232, -26.7572, 0, -6.6893, -23.412498, 0, -10.033899, -23.412498, 0, -6.6893, -23.412498, 0, -6.6893, -23.412498, 0, -10.033899, -20.0679, 0, -10.033899, -23.412498, 0, -6.6893, -20.0679, 0, -10.033899, -20.3764, 0, -6.6893, -26.7572, 0, -3.3446, -26.7572, 0, -6.6893, -23.412498, 0, -6.6893, -26.7572, 0, -3.3446, -23.412498, 0, -6.6893, -23.412498, 0, -3.3446, -26.7572, 0, -16.7232, -23.412498, 0, -20.0679, -23.412498, 0, -16.7232, -23.412498, 0, -16.7232, -23.412498, 0, -20.0679, -20.0679, 0, -20.0679, -26.7572, 0, -16.7232, -26.7572, 0, -20.0679, -23.412498, 0, -20.0679, -23.412498, 0, -20.0679, -20.0679, 0, -23.412498, -20.0679, 0, -20.0679, -20.0679, 0, -20.0679, -20.0679, 0, -23.412498, -16.7232, 0, -23.412498, -20.0679, 0, -23.412498, -16.7232, 0, -26.7572, -16.7232, 0, -23.412498, -20.0679, 0, -23.412498, -20.0679, 0, -26.7572, -16.7232, 0, -26.7572, -23.412498, 0, -20.0679, -23.412498, 0, -23.412498, -20.0679, 0, -23.412498, -23.412498, 0, -23.412498, -20.0679, 0, -26.7572, -20.0679, 0, -23.412498, -26.7572, 0, -20.0679, -23.412498, 0, -23.412498, -23.412498, 0, -20.0679, -23.412498, 0, -23.412498, -23.412498, 0, -26.7572, -20.0679, 0, -26.7572, -26.7572, 0, -20.0679, -26.7572, 0, -23.412498, -23.412498, 0, -23.412498, -26.7572, 0, -23.412498, -23.412498, 0, -26.7572, -23.412498, 0, -23.412498, -26.7572, 0, -23.412498, -26.7572, 0, -26.7572, -23.412498, 0, -26.7572, -23.412498, 0, -3.3446, -20.3764, 0, -6.6893, -20.0679, -0.3484, -3.5669, -23.412498, 0, -3.3446, -23.412498, 0, -6.6893, -20.3764, 0, -6.6893, 16.7232, 0, 10.033899, 20.0679, -0.124199994, 6.6893, 20.0679, 0, 10.033899, 16.7232, 0, 10.033899, 16.7232, 0, 6.6893, 20.0679, -0.124199994, 6.6893, 20.0679, 0, 10.033899, 23.412498, 0, 6.6893, 23.412498, 0, 10.033899, 20.0679, 0, 10.033899, 20.0679, -0.124199994, 6.6893, 23.412498, 0, 6.6893, -26.7572, 0, 3.3446, -23.412498, -0.2913, 0.26119998, -23.412498, 0, 3.3446, -26.7572, 0, 3.3446, -26.7572, 0, 0, -23.412498, -0.2913, 0.26119998, -26.7572, 0, 0, -23.412498, 0, -3.3446, -23.412498, -0.2913, 0.26119998, -26.7572, 0, 0, -26.7572, 0, -3.3446, -23.412498, 0, -3.3446, 0, 0, -13.3786, 3.0140998, 0, -16.7232, 3.3446, -0.3989, -12.9443, 0, 0, -13.3786, 0, 0, -16.7232, 3.0140998, 0, -16.7232, 0, 0, -10.7654, 3.3446, -0.3989, -12.9443, 2.8241, 0, -10.4594, 0, 0, -10.7654, 0, 0, -13.3786, 3.3446, -0.3989, -12.9443, 20.0679, -0.124199994, 6.6893, 23.412498, 0, 3.3446, 23.412498, 0, 6.6893, 20.0679, -0.124199994, 6.6893, 20.0679, 0, 3.3446, 23.412498, 0, 3.3446, 51.2184, -3.9413, -15.0508995, 54.072197, -3.9413, -13.3786, 51.2184, -3.9413, -13.3786, 51.2184, -3.9413, -13.3786, 54.072197, -3.9413, -13.3786, 54.072197, -3.9413, -11.7063, 51.2184, -3.9413, -15.0508995, 54.072197, -3.9413, -15.0508995, 54.072197, -3.9413, -13.3786, 51.2184, -3.9413, -13.3786, 54.072197, -3.9413, -11.7063, 51.2184, -3.9413, -11.7063, 51.2184, -3.9413, -11.7063, 54.072197, -3.9413, -11.7063, 54.072197, -3.9413, -10.033899, 48.3645, -3.9413, -15.0508995, 51.2184, -3.9413, -15.0508995, 51.2184, -3.9413, -13.3786, 51.2184, -3.9413, -11.7063, 54.072197, -3.9413, -10.033899, 51.2184, -3.9413, -10.033899, 51.2184, -3.9413, -10.033899, 54.072197, -3.9413, -10.033899, 54.072197, -3.9413, -8.3616, 48.3645, -3.9413, -13.3786, 51.2184, -3.9413, -13.3786, 51.2184, -3.9413, -11.7063, 48.3645, -3.9413, -15.0508995, 51.2184, -3.9413, -13.3786, 48.3645, -3.9413, -13.3786, 48.3645, -3.9413, -11.7063, 51.2184, -3.9413, -11.7063, 51.2184, -3.9413, -10.033899, 48.3645, -3.9413, -13.3786, 51.2184, -3.9413, -11.7063, 48.3645, -3.9413, -11.7063, 51.2184, -3.9413, -10.033899, 54.072197, -3.9413, -8.3616, 51.2184, -3.9413, -8.3616, 51.2184, -3.9413, -8.3616, 54.072197, -3.9413, -8.3616, 54.072197, -3.9413, -6.6893, 48.3645, -3.9413, -11.7063, 51.2184, -3.9413, -10.033899, 48.3645, -3.9413, -10.033899, 48.3645, -3.9413, -10.033899, 51.2184, -3.9413, -10.033899, 51.2184, -3.9413, -8.3616, 45.5107, -3.9413, -13.3786, 48.3645, -3.9413, -13.3786, 48.3645, -3.9413, -11.7063, 45.5107, -3.9413, -11.7063, 48.3645, -3.9413, -11.7063, 48.3645, -3.9413, -10.033899, 45.5107, -3.9413, -13.3786, 48.3645, -3.9413, -11.7063, 45.5107, -3.9413, -11.7063, 51.2184, -3.9413, -8.3616, 54.072197, -3.9413, -6.6893, 51.2184, -3.9413, -6.6893, 51.2184, -3.9413, -6.6893, 54.072197, -3.9413, -6.6893, 54.072197, -3.9413, -5.0169997, 48.3645, -3.9413, -10.033899, 51.2184, -3.9413, -8.3616, 48.3645, -3.9413, -8.3616, 48.3645, -3.9413, -8.3616, 51.2184, -3.9413, -8.3616, 51.2184, -3.9413, -6.6893, 45.5107, -3.9413, -11.7063, 48.3645, -3.9413, -10.033899, 45.5107, -3.9413, -10.033899, 45.5107, -3.9413, -10.033899, 48.3645, -3.9413, -10.033899, 48.3645, -3.9413, -8.3616, 51.2184, -3.9413, -6.6893, 54.072197, -3.9413, -5.0169997, 51.2184, -3.9413, -5.0169997, 51.2184, -3.9413, -5.0169997, 54.072197, -3.9413, -5.0169997, 54.072197, -3.9413, -3.3446, 48.3645, -3.9413, -8.3616, 51.2184, -3.9413, -6.6893, 48.3645, -3.9413, -6.6893, 48.3645, -3.9413, -6.6893, 51.2184, -3.9413, -6.6893, 51.2184, -3.9413, -5.0169997, 45.5107, -3.9413, -10.033899, 48.3645, -3.9413, -8.3616, 45.5107, -3.9413, -8.3616, 45.5107, -3.9413, -8.3616, 48.3645, -3.9413, -8.3616, 48.3645, -3.9413, -6.6893, 51.2184, -3.9413, -5.0169997, 54.072197, -3.9413, -3.3446, 51.2184, -3.9413, -3.3446, 51.2184, -3.9413, -3.3446, 54.072197, -3.9413, -3.3446, 54.072197, -3.9413, -1.6723, 48.3645, -3.9413, -6.6893, 51.2184, -3.9413, -5.0169997, 48.3645, -3.9413, -5.0169997, 48.3645, -3.9413, -5.0169997, 51.2184, -3.9413, -5.0169997, 51.2184, -3.9413, -3.3446, 45.5107, -3.9413, -8.3616, 48.3645, -3.9413, -6.6893, 45.5107, -3.9413, -6.6893, 45.5107, -3.9413, -6.6893, 48.3645, -3.9413, -6.6893, 48.3645, -3.9413, -5.0169997, 51.2184, -3.9413, -3.3446, 54.072197, -3.9413, -1.6723, 51.2184, -3.9413, -1.6723, 51.2184, -3.9413, -1.6723, 54.072197, -3.9413, -1.6723, 54.072197, -3.9413, 0, 48.3645, -3.9413, -5.0169997, 51.2184, -3.9413, -3.3446, 48.3645, -3.9413, -3.3446, 48.3645, -3.9413, -3.3446, 51.2184, -3.9413, -3.3446, 51.2184, -3.9413, -1.6723, 45.5107, -3.9413, -6.6893, 48.3645, -3.9413, -5.0169997, 45.5107, -3.9413, -5.0169997, 45.5107, -3.9413, -5.0169997, 48.3645, -3.9413, -5.0169997, 48.3645, -3.9413, -3.3446, 51.2184, -3.9413, -1.6723, 54.072197, -3.9413, 0, 51.2184, -3.9413, 0, 51.2184, -3.9413, 0, 54.072197, -3.9413, 0, 54.072197, -3.9413, 1.6723, 48.3645, -3.9413, -3.3446, 51.2184, -3.9413, -1.6723, 48.3645, -3.9413, -1.6723, 48.3645, -3.9413, -1.6723, 51.2184, -3.9413, -1.6723, 51.2184, -3.9413, 0, 45.5107, -3.9413, -5.0169997, 48.3645, -3.9413, -3.3446, 45.5107, -3.9413, -3.3446, 45.5107, -3.9413, -3.3446, 48.3645, -3.9413, -3.3446, 48.3645, -3.9413, -1.6723, 51.2184, -3.9413, 0, 54.072197, -3.9413, 1.6723, 51.2184, -3.9413, 1.6723, 51.2184, -3.9413, 1.6723, 54.072197, -3.9413, 1.6723, 54.072197, -3.9413, 3.3446, 48.3645, -3.9413, -1.6723, 51.2184, -3.9413, 0, 48.3645, -3.9413, 0, 48.3645, -3.9413, 0, 51.2184, -3.9413, 0, 51.2184, -3.9413, 1.6723, 45.5107, -3.9413, -3.3446, 48.3645, -3.9413, -1.6723, 45.5107, -3.9413, -1.6723, 45.5107, -3.9413, -1.6723, 48.3645, -3.9413, -1.6723, 48.3645, -3.9413, 0, 51.2184, -3.9413, 1.6723, 54.072197, -3.9413, 3.3446, 51.2184, -3.9413, 3.3446, 51.2184, -3.9413, 3.3446, 54.072197, -3.9413, 3.3446, 54.072197, -3.9413, 5.0169997, 48.3645, -3.9413, 0, 51.2184, -3.9413, 1.6723, 48.3645, -3.9413, 1.6723, 48.3645, -3.9413, 1.6723, 51.2184, -3.9413, 1.6723, 51.2184, -3.9413, 3.3446, 45.5107, -3.9413, -1.6723, 48.3645, -3.9413, 0, 45.5107, -3.9413, 0, 45.5107, -3.9413, 0, 48.3645, -3.9413, 0, 48.3645, -3.9413, 1.6723, 51.2184, -3.9413, 3.3446, 54.072197, -3.9413, 5.0169997, 51.2184, -3.9413, 5.0169997, 51.2184, -3.9413, 5.0169997, 54.072197, -3.9413, 5.0169997, 54.072197, -3.9413, 6.6893, 48.3645, -3.9413, 1.6723, 51.2184, -3.9413, 3.3446, 48.3645, -3.9413, 3.3446, 48.3645, -3.9413, 3.3446, 51.2184, -3.9413, 3.3446, 51.2184, -3.9413, 5.0169997, 45.5107, -3.9413, 0, 48.3645, -3.9413, 1.6723, 45.5107, -3.9413, 1.6723, 45.5107, -3.9413, 1.6723, 48.3645, -3.9413, 1.6723, 48.3645, -3.9413, 3.3446, 51.2184, -3.9413, 5.0169997, 54.072197, -3.9413, 6.6893, 51.2184, -3.9413, 6.6893, 51.2184, -3.9413, 6.6893, 54.072197, -3.9413, 6.6893, 54.072197, -3.9413, 8.3616, 48.3645, -3.9413, 3.3446, 51.2184, -3.9413, 5.0169997, 48.3645, -3.9413, 5.0169997, 48.3645, -3.9413, 5.0169997, 51.2184, -3.9413, 5.0169997, 51.2184, -3.9413, 6.6893, 45.5107, -3.9413, 1.6723, 48.3645, -3.9413, 3.3446, 45.5107, -3.9413, 3.3446, 45.5107, -3.9413, 3.3446, 48.3645, -3.9413, 3.3446, 48.3645, -3.9413, 5.0169997, 51.2184, -3.9413, 6.6893, 54.072197, -3.9413, 8.3616, 51.2184, -3.9413, 8.3616, 51.2184, -3.9413, 8.3616, 54.072197, -3.9413, 8.3616, 54.072197, -3.9413, 10.033899, 48.3645, -3.9413, 5.0169997, 51.2184, -3.9413, 6.6893, 48.3645, -3.9413, 6.6893, 48.3645, -3.9413, 6.6893, 51.2184, -3.9413, 6.6893, 51.2184, -3.9413, 8.3616, 45.5107, -3.9413, 3.3446, 48.3645, -3.9413, 5.0169997, 45.5107, -3.9413, 5.0169997, 45.5107, -3.9413, 5.0169997, 48.3645, -3.9413, 5.0169997, 48.3645, -3.9413, 6.6893, 51.2184, -3.9413, 8.3616, 54.072197, -3.9413, 10.033899, 51.2184, -3.9413, 10.033899, 51.2184, -3.9413, 10.033899, 54.072197, -3.9413, 10.033899, 54.072197, -3.9413, 11.7063, 48.3645, -3.9413, 6.6893, 51.2184, -3.9413, 8.3616, 48.3645, -3.9413, 8.3616, 48.3645, -3.9413, 8.3616, 51.2184, -3.9413, 8.3616, 51.2184, -3.9413, 10.033899, 45.5107, -3.9413, 5.0169997, 48.3645, -3.9413, 6.6893, 45.5107, -3.9413, 6.6893, 45.5107, -3.9413, 6.6893, 48.3645, -3.9413, 6.6893, 48.3645, -3.9413, 8.3616, 51.2184, -3.9413, 10.033899, 54.072197, -3.9413, 11.7063, 51.2184, -3.9413, 11.7063, 51.2184, -3.9413, 11.7063, 54.072197, -3.9413, 11.7063, 54.072197, -3.9413, 13.3786, 48.3645, -3.9413, 8.3616, 51.2184, -3.9413, 10.033899, 48.3645, -3.9413, 10.033899, 48.3645, -3.9413, 10.033899, 51.2184, -3.9413, 10.033899, 51.2184, -3.9413, 11.7063, 45.5107, -3.9413, 6.6893, 48.3645, -3.9413, 8.3616, 45.5107, -3.9413, 8.3616, 45.5107, -3.9413, 8.3616, 48.3645, -3.9413, 8.3616, 48.3645, -3.9413, 10.033899, 51.2184, -3.9413, 11.7063, 54.072197, -3.9413, 13.3786, 51.2184, -3.9413, 13.3786, 51.2184, -3.9413, 13.3786, 54.072197, -3.9413, 13.3786, 54.072197, -3.9413, 15.0508995, 48.3645, -3.9413, 10.033899, 51.2184, -3.9413, 11.7063, 48.3645, -3.9413, 11.7063, 48.3645, -3.9413, 11.7063, 51.2184, -3.9413, 11.7063, 51.2184, -3.9413, 13.3786, 45.5107, -3.9413, 8.3616, 48.3645, -3.9413, 10.033899, 45.5107, -3.9413, 10.033899, 45.5107, -3.9413, 10.033899, 48.3645, -3.9413, 10.033899, 48.3645, -3.9413, 11.7063, 51.2184, -3.9413, 13.3786, 54.072197, -3.9413, 15.0508995, 51.2184, -3.9413, 15.0508995, 51.2184, -3.9413, 15.0508995, 54.072197, -3.9413, 15.0508995, 54.072197, -3.9413, 16.7232, 48.3645, -3.9413, 11.7063, 51.2184, -3.9413, 13.3786, 48.3645, -3.9413, 13.3786, 48.3645, -3.9413, 13.3786, 51.2184, -3.9413, 13.3786, 51.2184, -3.9413, 15.0508995, 45.5107, -3.9413, 10.033899, 48.3645, -3.9413, 11.7063, 45.5107, -3.9413, 11.7063, 45.5107, -3.9413, 11.7063, 48.3645, -3.9413, 11.7063, 48.3645, -3.9413, 13.3786, 51.2184, -3.9413, 15.0508995, 54.072197, -3.9413, 16.7232, 51.2184, -3.9413, 16.7232, 51.2184, -3.9413, 16.7232, 54.072197, -3.9413, 16.7232, 54.072197, -3.9413, 18.3955, 48.3645, -3.9413, 13.3786, 51.2184, -3.9413, 15.0508995, 48.3645, -3.9413, 15.0508995, 48.3645, -3.9413, 15.0508995, 51.2184, -3.9413, 15.0508995, 51.2184, -3.9413, 16.7232, 45.5107, -3.9413, 11.7063, 48.3645, -3.9413, 13.3786, 45.5107, -3.9413, 13.3786, 45.5107, -3.9413, 13.3786, 48.3645, -3.9413, 13.3786, 48.3645, -3.9413, 15.0508995, 51.2184, -3.9413, 16.7232, 54.072197, -3.9413, 18.3955, 51.2184, -3.9413, 18.3955, 51.2184, -3.9413, 18.3955, 54.072197, -3.9413, 18.3955, 54.072197, -3.9413, 20.0679, 48.3645, -3.9413, 15.0508995, 51.2184, -3.9413, 16.7232, 48.3645, -3.9413, 16.7232, 48.3645, -3.9413, 16.7232, 51.2184, -3.9413, 16.7232, 51.2184, -3.9413, 18.3955, 45.5107, -3.9413, 13.3786, 48.3645, -3.9413, 15.0508995, 45.5107, -3.9413, 15.0508995, 45.5107, -3.9413, 15.0508995, 48.3645, -3.9413, 15.0508995, 48.3645, -3.9413, 16.7232, 51.2184, -3.9413, 18.3955, 54.072197, -3.9413, 20.0679, 51.2184, -3.9413, 20.0679, 51.2184, -3.9413, 20.0679, 54.072197, -3.9413, 20.0679, 54.072197, -3.9413, 21.7402, 48.3645, -3.9413, 16.7232, 51.2184, -3.9413, 18.3955, 48.3645, -3.9413, 18.3955, 48.3645, -3.9413, 18.3955, 51.2184, -3.9413, 18.3955, 51.2184, -3.9413, 20.0679, 45.5107, -3.9413, 15.0508995, 48.3645, -3.9413, 16.7232, 45.5107, -3.9413, 16.7232, 45.5107, -3.9413, 16.7232, 48.3645, -3.9413, 16.7232, 48.3645, -3.9413, 18.3955, 51.2184, -3.9413, 20.0679, 54.072197, -3.9413, 21.7402, 51.2184, -3.9413, 21.7402, 51.2184, -3.9413, 21.7402, 54.072197, -3.9413, 21.7402, 54.072197, -3.9413, 23.412498, 48.3645, -3.9413, 18.3955, 51.2184, -3.9413, 20.0679, 48.3645, -3.9413, 20.0679, 48.3645, -3.9413, 20.0679, 51.2184, -3.9413, 20.0679, 51.2184, -3.9413, 21.7402, 45.5107, -3.9413, 16.7232, 48.3645, -3.9413, 18.3955, 45.5107, -3.9413, 18.3955, 45.5107, -3.9413, 18.3955, 48.3645, -3.9413, 18.3955, 48.3645, -3.9413, 20.0679, 51.2184, -3.9413, 21.7402, 54.072197, -3.9413, 23.412498, 51.2184, -3.9413, 23.412498, 51.2184, -3.9413, 23.412498, 54.072197, -3.9413, 23.412498, 54.072197, -3.9413, 25.084799, 48.3645, -3.9413, 20.0679, 51.2184, -3.9413, 21.7402, 48.3645, -3.9413, 21.7402, 48.3645, -3.9413, 21.7402, 51.2184, -3.9413, 21.7402, 51.2184, -3.9413, 23.412498, 45.5107, -3.9413, 18.3955, 48.3645, -3.9413, 20.0679, 45.5107, -3.9413, 20.0679, 45.5107, -3.9413, 20.0679, 48.3645, -3.9413, 20.0679, 48.3645, -3.9413, 21.7402, 51.2184, -3.9413, 23.412498, 54.072197, -3.9413, 25.084799, 51.2184, -3.9413, 25.084799, 51.2184, -3.9413, 25.084799, 54.072197, -3.9413, 25.084799, 54.072197, -3.9413, 26.7572, 51.2184, -3.9413, 25.084799, 54.072197, -3.9413, 26.7572, 51.2184, -3.9413, 26.7572, 48.3645, -3.9413, 23.412498, 51.2184, -3.9413, 23.412498, 51.2184, -3.9413, 25.084799, 48.3645, -3.9413, 21.7402, 51.2184, -3.9413, 23.412498, 48.3645, -3.9413, 23.412498, 48.3645, -3.9413, 25.084799, 51.2184, -3.9413, 25.084799, 51.2184, -3.9413, 26.7572, 48.3645, -3.9413, 23.412498, 51.2184, -3.9413, 25.084799, 48.3645, -3.9413, 25.084799, 48.3645, -3.9413, 25.084799, 51.2184, -3.9413, 26.7572, 48.3645, -3.9413, 26.7572, 45.5107, -3.9413, 21.7402, 48.3645, -3.9413, 21.7402, 48.3645, -3.9413, 23.412498, 45.5107, -3.9413, 20.0679, 48.3645, -3.9413, 21.7402, 45.5107, -3.9413, 21.7402, 45.5107, -3.9413, 23.412498, 48.3645, -3.9413, 23.412498, 48.3645, -3.9413, 25.084799, 45.5107, -3.9413, 21.7402, 48.3645, -3.9413, 23.412498, 45.5107, -3.9413, 23.412498, 45.5107, -3.9413, 25.084799, 48.3645, -3.9413, 25.084799, 48.3645, -3.9413, 26.7572, 45.5107, -3.9413, 23.412498, 48.3645, -3.9413, 25.084799, 45.5107, -3.9413, 25.084799, 45.5107, -3.9413, 25.084799, 48.3645, -3.9413, 26.7572, 45.5107, -3.9413, 26.7572, 42.6568, -3.9413, 25.084799, 45.5107, -3.9413, 25.084799, 45.5107, -3.9413, 26.7572, 42.6568, -3.9413, 25.084799, 45.5107, -3.9413, 26.7572, 42.6568, -3.9413, 26.7572, 39.7973, -3.9413, 25.084799, 42.6568, -3.9413, 25.084799, 42.6568, -3.9413, 26.7572, 39.7973, -3.9413, 25.084799, 42.6568, -3.9413, 26.7572, 39.7973, -3.9413, 26.7572, 39.7973, -3.9413, 23.412498, 42.6568, -3.9413, 25.084799, 39.7973, -3.9413, 25.084799, 42.6568, -3.9413, 23.412498, 45.5107, -3.9413, 25.084799, 42.6568, -3.9413, 25.084799, 39.7973, -3.9413, 23.412498, 42.6568, -3.9413, 23.412498, 42.6568, -3.9413, 25.084799, 42.6568, -3.9413, 23.412498, 45.5107, -3.9413, 23.412498, 45.5107, -3.9413, 25.084799, 39.7973, -3.9413, 21.7402, 42.6568, -3.9413, 23.412498, 39.7973, -3.9413, 23.412498, 42.6568, -3.9413, 21.7402, 45.5107, -3.9413, 23.412498, 42.6568, -3.9413, 23.412498, 39.7973, -3.9413, 21.7402, 42.6568, -3.9413, 21.7402, 42.6568, -3.9413, 23.412498, 42.6568, -3.9413, 21.7402, 45.5107, -3.9413, 21.7402, 45.5107, -3.9413, 23.412498, 39.7973, -3.9413, 20.0679, 42.6568, -3.9413, 21.7402, 39.7973, -3.9413, 21.7402, 42.6568, -3.9413, 20.0679, 45.5107, -3.9413, 21.7402, 42.6568, -3.9413, 21.7402, 39.7973, -3.9413, 20.0679, 42.6568, -3.9413, 20.0679, 42.6568, -3.9413, 21.7402, 42.6568, -3.9413, 20.0679, 45.5107, -3.9413, 20.0679, 45.5107, -3.9413, 21.7402, 39.7973, -3.9413, 18.3955, 42.6568, -3.9413, 20.0679, 39.7973, -3.9413, 20.0679, 42.6568, -3.9413, 18.3955, 45.5107, -3.9413, 20.0679, 42.6568, -3.9413, 20.0679, 39.7973, -3.9413, 18.3955, 42.6568, -3.9413, 18.3955, 42.6568, -3.9413, 20.0679, 42.6568, -3.9413, 18.3955, 45.5107, -3.9413, 18.3955, 45.5107, -3.9413, 20.0679, 39.7973, -3.9413, 16.7232, 42.6568, -3.9413, 18.3955, 39.7973, -3.9413, 18.3955, 42.6568, -3.9413, 16.7232, 45.5107, -3.9413, 18.3955, 42.6568, -3.9413, 18.3955, 39.7973, -3.9413, 16.7232, 42.6568, -3.9413, 16.7232, 42.6568, -3.9413, 18.3955, 42.6568, -3.9413, 16.7232, 45.5107, -3.9413, 16.7232, 45.5107, -3.9413, 18.3955, 39.7973, -3.9413, 15.0508995, 42.6568, -3.9413, 16.7232, 39.7973, -3.9413, 16.7232, 42.6568, -3.9413, 15.0508995, 45.5107, -3.9413, 16.7232, 42.6568, -3.9413, 16.7232, 39.7973, -3.9413, 15.0508995, 42.6568, -3.9413, 15.0508995, 42.6568, -3.9413, 16.7232, 42.6568, -3.9413, 15.0508995, 45.5107, -3.9413, 15.0508995, 45.5107, -3.9413, 16.7232, 39.7973, -3.9413, 13.3786, 42.6568, -3.9413, 15.0508995, 39.7973, -3.9413, 15.0508995, 42.6568, -3.9413, 13.3786, 45.5107, -3.9413, 15.0508995, 42.6568, -3.9413, 15.0508995, 39.7973, -3.9413, 13.3786, 42.6568, -3.9413, 13.3786, 42.6568, -3.9413, 15.0508995, 42.6568, -3.9413, 13.3786, 45.5107, -3.9413, 13.3786, 45.5107, -3.9413, 15.0508995, 39.7973, -3.9413, 11.7063, 42.6568, -3.9413, 13.3786, 39.7973, -3.9413, 13.3786, 42.6568, -3.9413, 11.7063, 45.5107, -3.9413, 13.3786, 42.6568, -3.9413, 13.3786, 39.7973, -3.9413, 11.7063, 42.6568, -3.9413, 11.7063, 42.6568, -3.9413, 13.3786, 42.6568, -3.9413, 11.7063, 45.5107, -3.9413, 11.7063, 45.5107, -3.9413, 13.3786, 39.7973, -3.9413, 10.033899, 42.6568, -3.9413, 11.7063, 39.7973, -3.9413, 11.7063, 42.6568, -3.9413, 10.033899, 45.5107, -3.9413, 11.7063, 42.6568, -3.9413, 11.7063, 39.7973, -3.9413, 10.033899, 42.6568, -3.9413, 10.033899, 42.6568, -3.9413, 11.7063, 42.6568, -3.9413, 10.033899, 45.5107, -3.9413, 10.033899, 45.5107, -3.9413, 11.7063, 39.7973, -3.9413, 8.3616, 42.6568, -3.9413, 10.033899, 39.7973, -3.9413, 10.033899, 42.6568, -3.9413, 8.3616, 45.5107, -3.9413, 10.033899, 42.6568, -3.9413, 10.033899, 39.7973, -3.9413, 8.3616, 42.6568, -3.9413, 8.3616, 42.6568, -3.9413, 10.033899, 42.6568, -3.9413, 8.3616, 45.5107, -3.9413, 8.3616, 45.5107, -3.9413, 10.033899, 39.7973, -3.9413, 6.6893, 42.6568, -3.9413, 8.3616, 39.7973, -3.9413, 8.3616, 42.6568, -3.9413, 6.6893, 45.5107, -3.9413, 8.3616, 42.6568, -3.9413, 8.3616, 39.7973, -3.9413, 6.6893, 42.6568, -3.9413, 6.6893, 42.6568, -3.9413, 8.3616, 42.6568, -3.9413, 6.6893, 45.5107, -3.9413, 6.6893, 45.5107, -3.9413, 8.3616, 39.7973, -3.9413, 5.0169997, 42.6568, -3.9413, 6.6893, 39.7973, -3.9413, 6.6893, 42.6568, -3.9413, 5.0169997, 45.5107, -3.9413, 6.6893, 42.6568, -3.9413, 6.6893, 39.7973, -3.9413, 5.0169997, 42.6568, -3.9413, 5.0169997, 42.6568, -3.9413, 6.6893, 42.6568, -3.9413, 5.0169997, 45.5107, -3.9413, 5.0169997, 45.5107, -3.9413, 6.6893, 39.7973, -3.9413, 3.3446, 42.6568, -3.9413, 5.0169997, 39.7973, -3.9413, 5.0169997, 42.6568, -3.9413, 3.3446, 45.5107, -3.9413, 5.0169997, 42.6568, -3.9413, 5.0169997, 39.7973, -3.9413, 3.3446, 42.6568, -3.9413, 3.3446, 42.6568, -3.9413, 5.0169997, 42.6568, -3.9413, 3.3446, 45.5107, -3.9413, 3.3446, 45.5107, -3.9413, 5.0169997, 39.7973, -3.9413, 1.6723, 42.6568, -3.9413, 3.3446, 39.7973, -3.9413, 3.3446, 42.6568, -3.9413, 1.6723, 45.5107, -3.9413, 3.3446, 42.6568, -3.9413, 3.3446, 39.7973, -3.9413, 1.6723, 42.6568, -3.9413, 1.6723, 42.6568, -3.9413, 3.3446, 42.6568, -3.9413, 1.6723, 45.5107, -3.9413, 1.6723, 45.5107, -3.9413, 3.3446, 39.7973, -3.9413, 0, 42.6568, -3.9413, 1.6723, 39.7973, -3.9413, 1.6723, 42.6568, -3.9413, 0, 45.5107, -3.9413, 1.6723, 42.6568, -3.9413, 1.6723, 39.7973, -3.9413, 0, 42.6568, -3.9413, 0, 42.6568, -3.9413, 1.6723, 42.6568, -3.9413, 0, 45.5107, -3.9413, 0, 45.5107, -3.9413, 1.6723, 39.7973, -3.9413, -1.6723, 42.6568, -3.9413, 0, 39.7973, -3.9413, 0, 42.6568, -3.9413, -1.6723, 45.5107, -3.9413, 0, 42.6568, -3.9413, 0, 39.7973, -3.9413, -1.6723, 42.6568, -3.9413, -1.6723, 42.6568, -3.9413, 0, 42.6568, -3.9413, -1.6723, 45.5107, -3.9413, -1.6723, 45.5107, -3.9413, 0, 39.7973, -3.9413, -3.3446, 42.6568, -3.9413, -1.6723, 39.7973, -3.9413, -1.6723, 42.6568, -3.9413, -3.3446, 45.5107, -3.9413, -1.6723, 42.6568, -3.9413, -1.6723, 39.7973, -3.9413, -3.3446, 42.6568, -3.9413, -3.3446, 42.6568, -3.9413, -1.6723, 42.6568, -3.9413, -3.3446, 45.5107, -3.9413, -3.3446, 45.5107, -3.9413, -1.6723, 39.7973, -3.9413, -5.0169997, 42.6568, -3.9413, -3.3446, 39.7973, -3.9413, -3.3446, 42.6568, -3.9413, -5.0169997, 45.5107, -3.9413, -3.3446, 42.6568, -3.9413, -3.3446, 39.7973, -3.9413, -5.0169997, 42.6568, -3.9413, -5.0169997, 42.6568, -3.9413, -3.3446, 42.6568, -3.9413, -5.0169997, 45.5107, -3.9413, -5.0169997, 45.5107, -3.9413, -3.3446, 39.7973, -3.9413, -6.6893, 42.6568, -3.9413, -5.0169997, 39.7973, -3.9413, -5.0169997, 42.6568, -3.9413, -6.6893, 45.5107, -3.9413, -5.0169997, 42.6568, -3.9413, -5.0169997, 39.7973, -3.9413, -6.6893, 42.6568, -3.9413, -6.6893, 42.6568, -3.9413, -5.0169997, 42.6568, -3.9413, -6.6893, 45.5107, -3.9413, -6.6893, 45.5107, -3.9413, -5.0169997, 39.7973, -3.9413, -8.3616, 42.6568, -3.9413, -6.6893, 39.7973, -3.9413, -6.6893, 42.6568, -3.9413, -8.3616, 45.5107, -3.9413, -6.6893, 42.6568, -3.9413, -6.6893, 39.7973, -3.9413, -8.3616, 42.6568, -3.9413, -8.3616, 42.6568, -3.9413, -6.6893, 42.6568, -3.9413, -8.3616, 45.5107, -3.9413, -8.3616, 45.5107, -3.9413, -6.6893, 39.7973, -3.9413, -10.033899, 42.6568, -3.9413, -8.3616, 39.7973, -3.9413, -8.3616, 42.6568, -3.9413, -10.033899, 45.5107, -3.9413, -8.3616, 42.6568, -3.9413, -8.3616, 39.7973, -3.9413, -10.033899, 42.6568, -3.9413, -10.033899, 42.6568, -3.9413, -8.3616, 42.6568, -3.9413, -10.033899, 45.5107, -3.9413, -10.033899, 45.5107, -3.9413, -8.3616, 39.7973, -3.9413, -11.7063, 42.6568, -3.9413, -10.033899, 39.7973, -3.9413, -10.033899, 42.6568, -3.9413, -11.7063, 45.5107, -3.9413, -10.033899, 42.6568, -3.9413, -10.033899, 39.7973, -3.9413, -11.7063, 42.6568, -3.9413, -11.7063, 42.6568, -3.9413, -10.033899, 42.6568, -3.9413, -11.7063, 45.5107, -3.9413, -11.7063, 45.5107, -3.9413, -10.033899, 39.7973, -3.9413, -13.3786, 42.6568, -3.9413, -11.7063, 39.7973, -3.9413, -11.7063, 42.6568, -3.9413, -13.3786, 45.5107, -3.9413, -11.7063, 42.6568, -3.9413, -11.7063, 39.7973, -3.9413, -13.3786, 42.6568, -3.9413, -13.3786, 42.6568, -3.9413, -11.7063, 42.6568, -3.9413, -13.3786, 45.5107, -3.9413, -13.3786, 45.5107, -3.9413, -11.7063, 39.7973, -3.9413, -15.0508995, 42.6568, -3.9413, -13.3786, 39.7973, -3.9413, -13.3786, 39.7973, -3.9413, -15.0508995, 42.6568, -3.9413, -15.0508995, 42.6568, -3.9413, -13.3786, 42.6568, -3.9413, -15.0508995, 45.5107, -3.9413, -13.3786, 42.6568, -3.9413, -13.3786, 39.7973, -3.9413, -16.7232, 42.6568, -3.9413, -15.0508995, 39.7973, -3.9413, -15.0508995, 42.6568, -3.9413, -15.0508995, 45.5107, -3.9413, -15.0508995, 45.5107, -3.9413, -13.3786, 45.5107, -3.9413, -15.0508995, 48.3645, -3.9413, -13.3786, 45.5107, -3.9413, -13.3786, 39.7973, -3.9413, -16.7232, 42.6568, -3.9413, -16.7232, 42.6568, -3.9413, -15.0508995, 42.6568, -3.9413, -16.7232, 45.5107, -3.9413, -15.0508995, 42.6568, -3.9413, -15.0508995, 39.7973, -3.9413, -18.3955, 42.6568, -3.9413, -16.7232, 39.7973, -3.9413, -16.7232, 45.5107, -3.9413, -15.0508995, 48.3645, -3.9413, -15.0508995, 48.3645, -3.9413, -13.3786, 39.7973, -3.9413, -18.3955, 42.6568, -3.9413, -18.3955, 42.6568, -3.9413, -16.7232, 42.6568, -3.9413, -16.7232, 45.5107, -3.9413, -16.7232, 45.5107, -3.9413, -15.0508995, 45.5107, -3.9413, -16.7232, 48.3645, -3.9413, -15.0508995, 45.5107, -3.9413, -15.0508995, 42.6568, -3.9413, -18.3955, 45.5107, -3.9413, -16.7232, 42.6568, -3.9413, -16.7232, 39.7973, -3.9413, -20.0679, 42.6568, -3.9413, -18.3955, 39.7973, -3.9413, -18.3955, 45.5107, -3.9413, -16.7232, 48.3645, -3.9413, -16.7232, 48.3645, -3.9413, -15.0508995, 48.3645, -3.9413, -16.7232, 51.2184, -3.9413, -15.0508995, 48.3645, -3.9413, -15.0508995, 42.6568, -3.9413, -18.3955, 45.5107, -3.9413, -18.3955, 45.5107, -3.9413, -16.7232, 45.5107, -3.9413, -18.3955, 48.3645, -3.9413, -16.7232, 45.5107, -3.9413, -16.7232, 39.7973, -3.9413, -20.0679, 42.6568, -3.9413, -20.0679, 42.6568, -3.9413, -18.3955, 42.6568, -3.9413, -20.0679, 45.5107, -3.9413, -18.3955, 42.6568, -3.9413, -18.3955, 39.7973, -3.9413, -21.7402, 42.6568, -3.9413, -20.0679, 39.7973, -3.9413, -20.0679, 48.3645, -3.9413, -16.7232, 51.2184, -3.9413, -16.7232, 51.2184, -3.9413, -15.0508995, 51.2184, -3.9413, -16.7232, 54.072197, -3.9413, -15.0508995, 51.2184, -3.9413, -15.0508995, 51.2184, -3.9413, -16.7232, 54.072197, -3.9413, -16.7232, 54.072197, -3.9413, -15.0508995, 48.3645, -3.9413, -18.3955, 51.2184, -3.9413, -16.7232, 48.3645, -3.9413, -16.7232, 45.5107, -3.9413, -18.3955, 48.3645, -3.9413, -18.3955, 48.3645, -3.9413, -16.7232, 51.2184, -3.9413, -18.3955, 54.072197, -3.9413, -16.7232, 51.2184, -3.9413, -16.7232, 48.3645, -3.9413, -18.3955, 51.2184, -3.9413, -18.3955, 51.2184, -3.9413, -16.7232, 51.2184, -3.9413, -18.3955, 54.072197, -3.9413, -18.3955, 54.072197, -3.9413, -16.7232, 45.5107, -3.9413, -20.0679, 48.3645, -3.9413, -18.3955, 45.5107, -3.9413, -18.3955, 42.6568, -3.9413, -20.0679, 45.5107, -3.9413, -20.0679, 45.5107, -3.9413, -18.3955, 48.3645, -3.9413, -20.0679, 51.2184, -3.9413, -18.3955, 48.3645, -3.9413, -18.3955, 45.5107, -3.9413, -20.0679, 48.3645, -3.9413, -20.0679, 48.3645, -3.9413, -18.3955, 51.2184, -3.9413, -20.0679, 54.072197, -3.9413, -18.3955, 51.2184, -3.9413, -18.3955, 48.3645, -3.9413, -20.0679, 51.2184, -3.9413, -20.0679, 51.2184, -3.9413, -18.3955, 51.2184, -3.9413, -20.0679, 54.072197, -3.9413, -20.0679, 54.072197, -3.9413, -18.3955, 39.7973, -3.9413, -21.7402, 42.6568, -3.9413, -21.7402, 42.6568, -3.9413, -20.0679, 42.6568, -3.9413, -21.7402, 45.5107, -3.9413, -20.0679, 42.6568, -3.9413, -20.0679, 39.7973, -3.9413, -23.412498, 42.6568, -3.9413, -21.7402, 39.7973, -3.9413, -21.7402, 45.5107, -3.9413, -21.7402, 48.3645, -3.9413, -20.0679, 45.5107, -3.9413, -20.0679, 42.6568, -3.9413, -21.7402, 45.5107, -3.9413, -21.7402, 45.5107, -3.9413, -20.0679, 39.7973, -3.9413, -23.412498, 42.6568, -3.9413, -23.412498, 42.6568, -3.9413, -21.7402, 42.6568, -3.9413, -23.412498, 45.5107, -3.9413, -21.7402, 42.6568, -3.9413, -21.7402, 39.7973, -3.9413, -25.084799, 42.6568, -3.9413, -23.412498, 39.7973, -3.9413, -23.412498, 45.5107, -3.9413, -21.7402, 48.3645, -3.9413, -21.7402, 48.3645, -3.9413, -20.0679, 48.3645, -3.9413, -21.7402, 51.2184, -3.9413, -20.0679, 48.3645, -3.9413, -20.0679, 42.6568, -3.9413, -23.412498, 45.5107, -3.9413, -23.412498, 45.5107, -3.9413, -21.7402, 45.5107, -3.9413, -23.412498, 48.3645, -3.9413, -21.7402, 45.5107, -3.9413, -21.7402, 39.7973, -3.9413, -25.084799, 42.6568, -3.9413, -25.084799, 42.6568, -3.9413, -23.412498, 42.6568, -3.9413, -25.084799, 45.5107, -3.9413, -23.412498, 42.6568, -3.9413, -23.412498, 39.7973, -3.9413, -26.7572, 42.6568, -3.9413, -25.084799, 39.7973, -3.9413, -25.084799, 39.7973, -3.9413, -26.7572, 42.6568, -3.9413, -26.7572, 42.6568, -3.9413, -25.084799, 42.6568, -3.9413, -26.7572, 45.5107, -3.9413, -25.084799, 42.6568, -3.9413, -25.084799, 42.6568, -3.9413, -25.084799, 45.5107, -3.9413, -25.084799, 45.5107, -3.9413, -23.412498, 42.6568, -3.9413, -26.7572, 45.5107, -3.9413, -26.7572, 45.5107, -3.9413, -25.084799, 45.5107, -3.9413, -23.412498, 48.3645, -3.9413, -23.412498, 48.3645, -3.9413, -21.7402, 45.5107, -3.9413, -25.084799, 48.3645, -3.9413, -23.412498, 45.5107, -3.9413, -23.412498, 45.5107, -3.9413, -26.7572, 48.3645, -3.9413, -25.084799, 45.5107, -3.9413, -25.084799, 45.5107, -3.9413, -25.084799, 48.3645, -3.9413, -25.084799, 48.3645, -3.9413, -23.412498, 45.5107, -3.9413, -26.7572, 48.3645, -3.9413, -26.7572, 48.3645, -3.9413, -25.084799, 48.3645, -3.9413, -21.7402, 51.2184, -3.9413, -21.7402, 51.2184, -3.9413, -20.0679, 48.3645, -3.9413, -23.412498, 51.2184, -3.9413, -21.7402, 48.3645, -3.9413, -21.7402, 51.2184, -3.9413, -21.7402, 54.072197, -3.9413, -20.0679, 51.2184, -3.9413, -20.0679, 51.2184, -3.9413, -21.7402, 54.072197, -3.9413, -21.7402, 54.072197, -3.9413, -20.0679, 48.3645, -3.9413, -23.412498, 51.2184, -3.9413, -23.412498, 51.2184, -3.9413, -21.7402, 51.2184, -3.9413, -23.412498, 54.072197, -3.9413, -21.7402, 51.2184, -3.9413, -21.7402, 48.3645, -3.9413, -25.084799, 51.2184, -3.9413, -23.412498, 48.3645, -3.9413, -23.412498, 51.2184, -3.9413, -23.412498, 54.072197, -3.9413, -23.412498, 54.072197, -3.9413, -21.7402, 48.3645, -3.9413, -26.7572, 51.2184, -3.9413, -25.084799, 48.3645, -3.9413, -25.084799, 48.3645, -3.9413, -25.084799, 51.2184, -3.9413, -25.084799, 51.2184, -3.9413, -23.412498, 51.2184, -3.9413, -25.084799, 54.072197, -3.9413, -23.412498, 51.2184, -3.9413, -23.412498, 48.3645, -3.9413, -26.7572, 51.2184, -3.9413, -26.7572, 51.2184, -3.9413, -25.084799, 51.2184, -3.9413, -25.084799, 54.072197, -3.9413, -25.084799, 54.072197, -3.9413, -23.412498, 51.2184, -3.9413, -26.7572, 54.072197, -3.9413, -25.084799, 51.2184, -3.9413, -25.084799, 51.2184, -3.9413, -26.7572, 54.072197, -3.9413, -26.7572, 54.072197, -3.9413, -25.084799, 29.679499, -0.6044, -15.0508995, 32.4649, -1.1213, -13.3786, 29.679499, -0.6044, -13.3786, 29.679499, -0.6044, -13.3786, 32.4649, -1.1213, -13.3786, 32.4649, -1.1213, -11.7063, 29.679499, -0.6044, -15.0508995, 32.4649, -1.1213, -15.0508995, 32.4649, -1.1213, -13.3786, 29.679499, -0.6044, -13.3786, 32.4649, -1.1213, -11.7063, 29.679499, -0.6044, -11.7063, 29.679499, -0.6044, -16.7232, 32.4649, -1.1213, -15.0508995, 29.679499, -0.6044, -15.0508995, 29.679499, -0.6044, -11.7063, 32.4649, -1.1213, -11.7063, 32.4649, -1.1213, -10.033899, 29.679499, -0.6044, -16.7232, 32.4649, -1.1213, -16.7232, 32.4649, -1.1213, -15.0508995, 29.679499, -0.6044, -11.7063, 32.4649, -1.1213, -10.033899, 29.679499, -0.6044, -10.033899, 29.679499, -0.6044, -18.3955, 32.4649, -1.1213, -16.7232, 29.679499, -0.6044, -16.7232, 29.679499, -0.6044, -10.033899, 32.4649, -1.1213, -10.033899, 32.4649, -1.1213, -8.3616, 29.679499, -0.6044, -18.3955, 32.4649, -1.1213, -18.3955, 32.4649, -1.1213, -16.7232, 29.679499, -0.6044, -10.033899, 32.4649, -1.1213, -8.3616, 29.679499, -0.6044, -8.3616, 29.679499, -0.6044, -20.0679, 32.4649, -1.1213, -18.3955, 29.679499, -0.6044, -18.3955, 29.679499, -0.6044, -8.3616, 32.4649, -1.1213, -8.3616, 32.4649, -1.1213, -6.6893, 29.679499, -0.6044, -20.0679, 32.4649, -1.1213, -20.0679, 32.4649, -1.1213, -18.3955, 29.679499, -0.6044, -8.3616, 32.4649, -1.1213, -6.6893, 29.679499, -0.6044, -6.6893, 29.679499, -0.6044, -21.7402, 32.4649, -1.1213, -20.0679, 29.679499, -0.6044, -20.0679, 29.679499, -0.6044, -6.6893, 32.4649, -1.1213, -6.6893, 32.4649, -1.1213, -5.0169997, 29.679499, -0.6044, -21.7402, 32.4649, -1.1213, -21.7402, 32.4649, -1.1213, -20.0679, 29.679499, -0.6044, -6.6893, 32.4649, -1.1213, -5.0169997, 29.679499, -0.6044, -5.0169997, 29.679499, -0.6044, -23.412498, 32.4649, -1.1213, -21.7402, 29.679499, -0.6044, -21.7402, 29.679499, -0.6044, -5.0169997, 32.4649, -1.1213, -5.0169997, 32.4649, -1.1213, -3.3446, 29.679499, -0.6044, -23.412498, 32.4649, -1.1213, -23.412498, 32.4649, -1.1213, -21.7402, 29.679499, -0.6044, -5.0169997, 32.4649, -1.1213, -3.3446, 29.679499, -0.6044, -3.3446, 29.679499, -0.6044, -25.084799, 32.4649, -1.1213, -23.412498, 29.679499, -0.6044, -23.412498, 29.679499, -0.6044, -3.3446, 32.4649, -1.1213, -3.3446, 32.4649, -1.1213, -1.6723, 29.679499, -0.6044, -25.084799, 32.4649, -1.1213, -25.084799, 32.4649, -1.1213, -23.412498, 29.679499, -0.6044, -26.7572, 32.4649, -1.1213, -25.084799, 29.679499, -0.6044, -25.084799, 29.679499, -0.6044, -26.7572, 32.4649, -1.1213, -26.7572, 32.4649, -1.1213, -25.084799, 29.679499, -0.6044, -3.3446, 32.4649, -1.1213, -1.6723, 29.679499, -0.6044, -1.6723, 29.679499, -0.6044, -1.6723, 32.4649, -1.1213, -1.6723, 32.4649, -1.1213, 0, 29.679499, -0.6044, -1.6723, 32.4649, -1.1213, 0, 29.679499, -0.6044, 0, 29.679499, -0.6044, 0, 32.4649, -1.1213, 0, 32.4649, -1.1213, 1.6723, 29.679499, -0.6044, 0, 32.4649, -1.1213, 1.6723, 29.679499, -0.6044, 1.6723, 29.679499, -0.6044, 1.6723, 32.4649, -1.1213, 1.6723, 32.4649, -1.1213, 3.3446, 29.679499, -0.6044, 1.6723, 32.4649, -1.1213, 3.3446, 29.679499, -0.6044, 3.3446, 29.679499, -0.6044, 3.3446, 32.4649, -1.1213, 3.3446, 32.4649, -1.1213, 5.0169997, 29.679499, -0.6044, 3.3446, 32.4649, -1.1213, 5.0169997, 29.679499, -0.6044, 5.0169997, 29.679499, -0.6044, 5.0169997, 32.4649, -1.1213, 5.0169997, 32.4649, -1.1213, 6.6893, 29.679499, -0.6044, 5.0169997, 32.4649, -1.1213, 6.6893, 29.679499, -0.6044, 6.6893, 29.679499, -0.6044, 6.6893, 32.4649, -1.1213, 6.6893, 32.4649, -1.1213, 8.3616, 29.679499, -0.6044, 6.6893, 32.4649, -1.1213, 8.3616, 29.679499, -0.6044, 8.3616, 29.679499, -0.6044, 8.3616, 32.4649, -1.1213, 8.3616, 32.4649, -1.1213, 10.033899, 29.679499, -0.6044, 8.3616, 32.4649, -1.1213, 10.033899, 29.679499, -0.6044, 10.033899, 29.679499, -0.6044, 10.033899, 32.4649, -1.1213, 10.033899, 32.4649, -1.1213, 11.7063, 29.679499, -0.6044, 10.033899, 32.4649, -1.1213, 11.7063, 29.679499, -0.6044, 11.7063, 29.679499, -0.6044, 11.7063, 32.4649, -1.1213, 11.7063, 32.4649, -1.1213, 13.3786, 29.679499, -0.6044, 11.7063, 32.4649, -1.1213, 13.3786, 29.679499, -0.6044, 13.3786, 29.679499, -0.6044, 13.3786, 32.4649, -1.1213, 13.3786, 32.4649, -1.1213, 15.0508995, 29.679499, -0.6044, 13.3786, 32.4649, -1.1213, 15.0508995, 29.679499, -0.6044, 15.0508995, 29.679499, -0.6044, 15.0508995, 32.4649, -1.1213, 15.0508995, 32.4649, -1.1213, 16.7232, 29.679499, -0.6044, 15.0508995, 32.4649, -1.1213, 16.7232, 29.679499, -0.6044, 16.7232, 29.679499, -0.6044, 16.7232, 32.4649, -1.1213, 16.7232, 32.4649, -1.1213, 18.3955, 29.679499, -0.6044, 16.7232, 32.4649, -1.1213, 18.3955, 29.679499, -0.6044, 18.3955, 29.679499, -0.6044, 18.3955, 32.4649, -1.1213, 18.3955, 32.4649, -1.1213, 20.0679, 29.679499, -0.6044, 18.3955, 32.4649, -1.1213, 20.0679, 29.679499, -0.6044, 20.0679, 29.679499, -0.6044, 20.0679, 32.4649, -1.1213, 20.0679, 32.4649, -1.1213, 21.7402, 29.679499, -0.6044, 20.0679, 32.4649, -1.1213, 21.7402, 29.679499, -0.6044, 21.7402, 29.679499, -0.6044, 21.7402, 32.4649, -1.1213, 21.7402, 32.4649, -1.1213, 23.412498, 29.679499, -0.6044, 21.7402, 32.4649, -1.1213, 23.412498, 29.679499, -0.6044, 23.412498, 29.679499, -0.6044, 23.412498, 32.4649, -1.1213, 23.412498, 32.4649, -1.1213, 25.084799, 29.679499, -0.6044, 23.412498, 32.4649, -1.1213, 25.084799, 29.679499, -0.6044, 25.084799, 29.679499, -0.6044, 25.084799, 32.4649, -1.1213, 25.084799, 32.4649, -1.1213, 26.7572, 29.679499, -0.6044, 25.084799, 32.4649, -1.1213, 26.7572, 29.679499, -0.6044, 26.7572, 32.4649, -1.1213, -15.0508995, 39.7973, -3.9413, -13.3786, 32.4649, -1.1213, -13.3786, 32.4649, -1.1213, -13.3786, 39.7973, -3.9413, -13.3786, 39.7973, -3.9413, -11.7063, 32.4649, -1.1213, -15.0508995, 39.7973, -3.9413, -15.0508995, 39.7973, -3.9413, -13.3786, 32.4649, -1.1213, -13.3786, 39.7973, -3.9413, -11.7063, 32.4649, -1.1213, -11.7063, 32.4649, -1.1213, -16.7232, 39.7973, -3.9413, -15.0508995, 32.4649, -1.1213, -15.0508995, 32.4649, -1.1213, -11.7063, 39.7973, -3.9413, -11.7063, 39.7973, -3.9413, -10.033899, 32.4649, -1.1213, -16.7232, 39.7973, -3.9413, -16.7232, 39.7973, -3.9413, -15.0508995, 32.4649, -1.1213, -11.7063, 39.7973, -3.9413, -10.033899, 32.4649, -1.1213, -10.033899, 32.4649, -1.1213, -18.3955, 39.7973, -3.9413, -16.7232, 32.4649, -1.1213, -16.7232, 32.4649, -1.1213, -10.033899, 39.7973, -3.9413, -10.033899, 39.7973, -3.9413, -8.3616, 32.4649, -1.1213, -18.3955, 39.7973, -3.9413, -18.3955, 39.7973, -3.9413, -16.7232, 32.4649, -1.1213, -10.033899, 39.7973, -3.9413, -8.3616, 32.4649, -1.1213, -8.3616, 32.4649, -1.1213, -20.0679, 39.7973, -3.9413, -18.3955, 32.4649, -1.1213, -18.3955, 32.4649, -1.1213, -8.3616, 39.7973, -3.9413, -8.3616, 39.7973, -3.9413, -6.6893, 32.4649, -1.1213, -20.0679, 39.7973, -3.9413, -20.0679, 39.7973, -3.9413, -18.3955, 32.4649, -1.1213, -8.3616, 39.7973, -3.9413, -6.6893, 32.4649, -1.1213, -6.6893, 32.4649, -1.1213, -21.7402, 39.7973, -3.9413, -20.0679, 32.4649, -1.1213, -20.0679, 32.4649, -1.1213, -6.6893, 39.7973, -3.9413, -6.6893, 39.7973, -3.9413, -5.0169997, 32.4649, -1.1213, -21.7402, 39.7973, -3.9413, -21.7402, 39.7973, -3.9413, -20.0679, 32.4649, -1.1213, -6.6893, 39.7973, -3.9413, -5.0169997, 32.4649, -1.1213, -5.0169997, 32.4649, -1.1213, -23.412498, 39.7973, -3.9413, -21.7402, 32.4649, -1.1213, -21.7402, 32.4649, -1.1213, -5.0169997, 39.7973, -3.9413, -5.0169997, 39.7973, -3.9413, -3.3446, 32.4649, -1.1213, -23.412498, 39.7973, -3.9413, -23.412498, 39.7973, -3.9413, -21.7402, 32.4649, -1.1213, -5.0169997, 39.7973, -3.9413, -3.3446, 32.4649, -1.1213, -3.3446, 32.4649, -1.1213, -25.084799, 39.7973, -3.9413, -23.412498, 32.4649, -1.1213, -23.412498, 32.4649, -1.1213, -3.3446, 39.7973, -3.9413, -3.3446, 39.7973, -3.9413, -1.6723, 32.4649, -1.1213, -25.084799, 39.7973, -3.9413, -25.084799, 39.7973, -3.9413, -23.412498, 32.4649, -1.1213, -26.7572, 39.7973, -3.9413, -25.084799, 32.4649, -1.1213, -25.084799, 32.4649, -1.1213, -26.7572, 39.7973, -3.9413, -26.7572, 39.7973, -3.9413, -25.084799, 32.4649, -1.1213, -3.3446, 39.7973, -3.9413, -1.6723, 32.4649, -1.1213, -1.6723, 32.4649, -1.1213, -1.6723, 39.7973, -3.9413, -1.6723, 39.7973, -3.9413, 0, 32.4649, -1.1213, -1.6723, 39.7973, -3.9413, 0, 32.4649, -1.1213, 0, 32.4649, -1.1213, 0, 39.7973, -3.9413, 0, 39.7973, -3.9413, 1.6723, 32.4649, -1.1213, 0, 39.7973, -3.9413, 1.6723, 32.4649, -1.1213, 1.6723, 32.4649, -1.1213, 1.6723, 39.7973, -3.9413, 1.6723, 39.7973, -3.9413, 3.3446, 32.4649, -1.1213, 1.6723, 39.7973, -3.9413, 3.3446, 32.4649, -1.1213, 3.3446, 32.4649, -1.1213, 3.3446, 39.7973, -3.9413, 3.3446, 39.7973, -3.9413, 5.0169997, 32.4649, -1.1213, 3.3446, 39.7973, -3.9413, 5.0169997, 32.4649, -1.1213, 5.0169997, 32.4649, -1.1213, 5.0169997, 39.7973, -3.9413, 5.0169997, 39.7973, -3.9413, 6.6893, 32.4649, -1.1213, 5.0169997, 39.7973, -3.9413, 6.6893, 32.4649, -1.1213, 6.6893, 32.4649, -1.1213, 6.6893, 39.7973, -3.9413, 6.6893, 39.7973, -3.9413, 8.3616, 32.4649, -1.1213, 6.6893, 39.7973, -3.9413, 8.3616, 32.4649, -1.1213, 8.3616, 32.4649, -1.1213, 8.3616, 39.7973, -3.9413, 8.3616, 39.7973, -3.9413, 10.033899, 32.4649, -1.1213, 8.3616, 39.7973, -3.9413, 10.033899, 32.4649, -1.1213, 10.033899, 32.4649, -1.1213, 10.033899, 39.7973, -3.9413, 10.033899, 39.7973, -3.9413, 11.7063, 32.4649, -1.1213, 10.033899, 39.7973, -3.9413, 11.7063, 32.4649, -1.1213, 11.7063, 32.4649, -1.1213, 11.7063, 39.7973, -3.9413, 11.7063, 39.7973, -3.9413, 13.3786, 32.4649, -1.1213, 11.7063, 39.7973, -3.9413, 13.3786, 32.4649, -1.1213, 13.3786, 32.4649, -1.1213, 13.3786, 39.7973, -3.9413, 13.3786, 39.7973, -3.9413, 15.0508995, 32.4649, -1.1213, 13.3786, 39.7973, -3.9413, 15.0508995, 32.4649, -1.1213, 15.0508995, 32.4649, -1.1213, 15.0508995, 39.7973, -3.9413, 15.0508995, 39.7973, -3.9413, 16.7232, 32.4649, -1.1213, 15.0508995, 39.7973, -3.9413, 16.7232, 32.4649, -1.1213, 16.7232, 32.4649, -1.1213, 16.7232, 39.7973, -3.9413, 16.7232, 39.7973, -3.9413, 18.3955, 32.4649, -1.1213, 16.7232, 39.7973, -3.9413, 18.3955, 32.4649, -1.1213, 18.3955, 32.4649, -1.1213, 18.3955, 39.7973, -3.9413, 18.3955, 39.7973, -3.9413, 20.0679, 32.4649, -1.1213, 18.3955, 39.7973, -3.9413, 20.0679, 32.4649, -1.1213, 20.0679, 32.4649, -1.1213, 20.0679, 39.7973, -3.9413, 20.0679, 39.7973, -3.9413, 21.7402, 32.4649, -1.1213, 20.0679, 39.7973, -3.9413, 21.7402, 32.4649, -1.1213, 21.7402, 32.4649, -1.1213, 21.7402, 39.7973, -3.9413, 21.7402, 39.7973, -3.9413, 23.412498, 32.4649, -1.1213, 21.7402, 39.7973, -3.9413, 23.412498, 32.4649, -1.1213, 23.412498, 32.4649, -1.1213, 23.412498, 39.7973, -3.9413, 23.412498, 39.7973, -3.9413, 25.084799, 32.4649, -1.1213, 23.412498, 39.7973, -3.9413, 25.084799, 32.4649, -1.1213, 25.084799, 32.4649, -1.1213, 25.084799, 39.7973, -3.9413, 25.084799, 39.7973, -3.9413, 26.7572, 32.4649, -1.1213, 25.084799, 39.7973, -3.9413, 26.7572, 32.4649, -1.1213, 26.7572, 26.7572, -0.2593, 16.7232, 29.679499, -0.6044, 18.3955, 26.7572, -0.2593, 18.3955, 26.7572, -0.2593, 18.3955, 29.679499, -0.6044, 18.3955, 29.679499, -0.6044, 20.0679, 26.7572, -0.2593, 16.7232, 29.679499, -0.6044, 16.7232, 29.679499, -0.6044, 18.3955, 26.7572, -0.2593, 18.3955, 29.679499, -0.6044, 20.0679, 26.7572, -0.2593, 20.0679, 26.7572, -0.2593, 15.0508995, 29.679499, -0.6044, 16.7232, 26.7572, -0.2593, 16.7232, 26.7572, -0.2593, 20.0679, 29.679499, -0.6044, 20.0679, 29.679499, -0.6044, 21.7402, 26.7572, -0.2593, 15.0508995, 29.679499, -0.6044, 15.0508995, 29.679499, -0.6044, 16.7232, 26.7572, -0.2593, 20.0679, 29.679499, -0.6044, 21.7402, 26.7572, -0.2593, 21.7402, 26.7572, -0.2593, 13.3786, 29.679499, -0.6044, 15.0508995, 26.7572, -0.2593, 15.0508995, 26.7572, -0.2593, 21.7402, 29.679499, -0.6044, 21.7402, 29.679499, -0.6044, 23.412498, 26.7572, -0.2593, 13.3786, 29.679499, -0.6044, 13.3786, 29.679499, -0.6044, 15.0508995, 26.7572, -0.2593, 21.7402, 29.679499, -0.6044, 23.412498, 26.7572, -0.2593, 23.412498, 26.7572, -0.2593, 11.7063, 29.679499, -0.6044, 13.3786, 26.7572, -0.2593, 13.3786, 26.7572, -0.2593, 23.412498, 29.679499, -0.6044, 23.412498, 29.679499, -0.6044, 25.084799, 26.7572, -0.2593, 11.7063, 29.679499, -0.6044, 11.7063, 29.679499, -0.6044, 13.3786, 26.7572, -0.2593, 23.412498, 29.679499, -0.6044, 25.084799, 26.7572, -0.2593, 25.084799, 26.7572, -0.2593, 25.084799, 29.679499, -0.6044, 25.084799, 29.679499, -0.6044, 26.7572, 26.7572, -0.2593, 25.084799, 29.679499, -0.6044, 26.7572, 26.7572, -0.2593, 26.7572, 26.7572, -0.2593, 10.033899, 29.679499, -0.6044, 11.7063, 26.7572, -0.2593, 11.7063, 26.7572, -0.2593, 10.033899, 29.679499, -0.6044, 10.033899, 29.679499, -0.6044, 11.7063, 26.7572, -0.2593, 8.3616, 29.679499, -0.6044, 10.033899, 26.7572, -0.2593, 10.033899, 26.7572, -0.2593, 8.3616, 29.679499, -0.6044, 8.3616, 29.679499, -0.6044, 10.033899, 26.7572, -0.2593, 6.6893, 29.679499, -0.6044, 8.3616, 26.7572, -0.2593, 8.3616, 26.7572, -0.2593, 6.6893, 29.679499, -0.6044, 6.6893, 29.679499, -0.6044, 8.3616, 26.7572, -0.2593, 5.0169997, 29.679499, -0.6044, 6.6893, 26.7572, -0.2593, 6.6893, 26.7572, -0.2593, 5.0169997, 29.679499, -0.6044, 5.0169997, 29.679499, -0.6044, 6.6893, 26.7572, -0.2593, 3.3446, 29.679499, -0.6044, 5.0169997, 26.7572, -0.2593, 5.0169997, 26.7572, -0.2593, 3.3446, 29.679499, -0.6044, 3.3446, 29.679499, -0.6044, 5.0169997, 26.7572, -0.2593, 1.6723, 29.679499, -0.6044, 3.3446, 26.7572, -0.2593, 3.3446, 26.7572, -0.2593, 1.6723, 29.679499, -0.6044, 1.6723, 29.679499, -0.6044, 3.3446, 26.7572, -0.2593, 0, 29.679499, -0.6044, 1.6723, 26.7572, -0.2593, 1.6723, 26.7572, -0.2593, 0, 29.679499, -0.6044, 0, 29.679499, -0.6044, 1.6723, 26.7572, -0.2593, -1.6723, 29.679499, -0.6044, 0, 26.7572, -0.2593, 0, 26.7572, -0.2593, -1.6723, 29.679499, -0.6044, -1.6723, 29.679499, -0.6044, 0, 26.7572, -0.2593, -3.3446, 29.679499, -0.6044, -1.6723, 26.7572, -0.2593, -1.6723, 26.7572, -0.2593, -3.3446, 29.679499, -0.6044, -3.3446, 29.679499, -0.6044, -1.6723, 26.7572, -0.2593, -5.0169997, 29.679499, -0.6044, -3.3446, 26.7572, -0.2593, -3.3446, 26.7572, -0.2593, -5.0169997, 29.679499, -0.6044, -5.0169997, 29.679499, -0.6044, -3.3446, 26.7572, -0.2593, -6.6893, 29.679499, -0.6044, -5.0169997, 26.7572, -0.2593, -5.0169997, 26.7572, -0.2593, -6.6893, 29.679499, -0.6044, -6.6893, 29.679499, -0.6044, -5.0169997, 26.7572, -0.2593, -8.3616, 29.679499, -0.6044, -6.6893, 26.7572, -0.2593, -6.6893, 26.7572, -0.2593, -8.3616, 29.679499, -0.6044, -8.3616, 29.679499, -0.6044, -6.6893, 26.7572, -0.2593, -10.033899, 29.679499, -0.6044, -8.3616, 26.7572, -0.2593, -8.3616, 26.7572, -0.2593, -10.033899, 29.679499, -0.6044, -10.033899, 29.679499, -0.6044, -8.3616, 26.7572, -0.2593, -11.7063, 29.679499, -0.6044, -10.033899, 26.7572, -0.2593, -10.033899, 26.7572, -0.2593, -11.7063, 29.679499, -0.6044, -11.7063, 29.679499, -0.6044, -10.033899, 26.7572, -0.2593, -13.3786, 29.679499, -0.6044, -11.7063, 26.7572, -0.2593, -11.7063, 26.7572, -0.2593, -13.3786, 29.679499, -0.6044, -13.3786, 29.679499, -0.6044, -11.7063, 26.7572, -0.2593, -15.0508995, 29.679499, -0.6044, -13.3786, 26.7572, -0.2593, -13.3786, 26.7572, -0.2593, -15.0508995, 29.679499, -0.6044, -15.0508995, 29.679499, -0.6044, -13.3786, 26.7572, -0.2593, -16.7232, 29.679499, -0.6044, -15.0508995, 26.7572, -0.2593, -15.0508995, 26.7572, -0.2593, -16.7232, 29.679499, -0.6044, -16.7232, 29.679499, -0.6044, -15.0508995, 26.7572, -0.2593, -18.3955, 29.679499, -0.6044, -16.7232, 26.7572, -0.2593, -16.7232, 26.7572, -0.2593, -18.3955, 29.679499, -0.6044, -18.3955, 29.679499, -0.6044, -16.7232, 26.7572, -0.2593, -20.0679, 29.679499, -0.6044, -18.3955, 26.7572, -0.2593, -18.3955, 26.7572, -0.2593, -20.0679, 29.679499, -0.6044, -20.0679, 29.679499, -0.6044, -18.3955, 26.7572, -0.2593, -21.7402, 29.679499, -0.6044, -20.0679, 26.7572, -0.2593, -20.0679, 26.7572, -0.2593, -21.7402, 29.679499, -0.6044, -21.7402, 29.679499, -0.6044, -20.0679, 26.7572, -0.2593, -23.412498, 29.679499, -0.6044, -21.7402, 26.7572, -0.2593, -21.7402, 26.7572, -0.2593, -23.412498, 29.679499, -0.6044, -23.412498, 29.679499, -0.6044, -21.7402, 26.7572, -0.2593, -25.084799, 29.679499, -0.6044, -23.412498, 26.7572, -0.2593, -23.412498, 26.7572, -0.2593, -25.084799, 29.679499, -0.6044, -25.084799, 29.679499, -0.6044, -23.412498, 26.7572, -0.2593, -26.7572, 29.679499, -0.6044, -25.084799, 26.7572, -0.2593, -25.084799, 26.7572, -0.2593, -26.7572, 29.679499, -0.6044, -26.7572, 29.679499, -0.6044, -25.084799) @@ -293,3 +294,7 @@ position = Vector3(-3.25, 3.42, 11.25) [node name="DecorShopWorld" parent="Interactables" instance=ExtResource("25_decor_shop")] position = Vector3(-3.25, 3.42, 11.25) rotation = Vector3(0, 1.5707964, 0) + +[node name="RVUpgradeShopWorld" parent="Interactables" instance=ExtResource("26_rv_upgrade")] +position = Vector3(-6.25, 3.42, 9) +rotation = Vector3(0, 1.5707964, 0) diff --git a/world/regions/world_region.gd b/world/regions/world_region.gd index 85f6e1b..d054938 100644 --- a/world/regions/world_region.gd +++ b/world/regions/world_region.gd @@ -22,6 +22,10 @@ func get_decor_shop() -> DecorShopInteraction: return null +func get_rv_upgrade_shop() -> RVUpgradeInteraction: + return null + + func get_player_storage() -> PlayerStorageInteraction: return null @@ -42,10 +46,24 @@ func get_spawn_surface_triangles( _material_names: Array[StringName], _minimum_global_y: float, _minimum_up_dot: float = 0.6, + _maximum_global_y: float = 100.0, ) -> Array[PackedVector3Array]: return [] +func get_saltwater_surface_height() -> float: + for water_region: FishableWaterRegion in get_fishable_water_regions(): + if water_region.water_type == WaterType.Type.SALT_WATER: + return water_region.get_surface_height() + return NAN + + +## Authored regions are assumed to expose only deliberately reachable home +## sites. Procedural regions override this to reject isolated elevations. +func is_home_exterior_position_accessible(_position: Vector3) -> bool: + return true + + func get_fishable_water_regions() -> Array[FishableWaterRegion]: var regions: Array[FishableWaterRegion] = [] var root: Node = get_node_or_null(fishable_water_root) diff --git a/world/rv_upgrade_interaction.gd b/world/rv_upgrade_interaction.gd new file mode 100644 index 0000000..fb24246 --- /dev/null +++ b/world/rv_upgrade_interaction.gd @@ -0,0 +1,15 @@ +class_name RVUpgradeInteraction +extends FishingShopInteraction + +const TENT_DIALOGUE_TEXT: String = ( + "That tent is looking awful cramped. Can I talk you into an upgrade?" +) +const RV_DIALOGUE_TEXT: String = "How's the new RV treating you?" + + +func get_dialogue_text(home_tier: int = -1) -> String: + return ( + RV_DIALOGUE_TEXT + if home_tier >= PlayerHomeState.STARTER_RV_TIER + else TENT_DIALOGUE_TEXT + ) diff --git a/world/rv_upgrade_interaction.gd.uid b/world/rv_upgrade_interaction.gd.uid new file mode 100644 index 0000000..cb57804 --- /dev/null +++ b/world/rv_upgrade_interaction.gd.uid @@ -0,0 +1 @@ +uid://c0h08goorv2of diff --git a/world/test_world.gd b/world/test_world.gd index 1b0a813..2e25206 100644 --- a/world/test_world.gd +++ b/world/test_world.gd @@ -10,6 +10,9 @@ const PlayerStorageInteractionType = preload( const DecorShopInteractionType = preload( "res://world/decor_shop_interaction.gd" ) +const RVUpgradeInteractionType = preload( + "res://world/rv_upgrade_interaction.gd" +) const WorldLayoutType = preload("res://world/world_layout.gd") const GENERATED_REGION_SCENE: PackedScene = preload( "res://world/generation/generated_world_region.tscn" @@ -75,6 +78,10 @@ func get_decor_shop() -> DecorShopInteractionType: return _active_region.get_decor_shop() +func get_rv_upgrade_shop() -> RVUpgradeInteractionType: + return _active_region.get_rv_upgrade_shop() + + func get_player_spawn_transform() -> Transform3D: return _active_region.get_player_spawn_transform() @@ -170,10 +177,29 @@ func get_saltwater_shoreline_mesh() -> MeshInstance3D: func get_spawn_surface_triangles( material_names: Array[StringName], minimum_global_y: float, + minimum_up_dot: float = 0.6, + maximum_global_y: float = 100.0, ) -> Array[PackedVector3Array]: return _active_region.get_spawn_surface_triangles( material_names, minimum_global_y, + minimum_up_dot, + maximum_global_y, + ) + + +func get_saltwater_surface_height() -> float: + return ( + _active_region.get_saltwater_surface_height() + if _active_region != null + else NAN + ) + + +func is_home_exterior_position_accessible(position: Vector3) -> bool: + return ( + _active_region != null + and _active_region.is_home_exterior_position_accessible(position) )