From 1903b9e9382b06c693c232eadc87b6c2ba44ba44 Mon Sep 17 00:00:00 2001 From: landgreen Date: Thu, 13 Jun 2024 12:05:40 -0700 Subject: [PATCH] double jump tech: working mass - in midair molecular assembler or pilot wave prints a block to jump off buckling: 100%->50% chance to spawn a power up from any block that kills a mob no longer requires the block to be thrown mobs: powerUpBoss, snakeBoss tails, cellBoss, ghoster, sucker - all collide with blocks now added a few more blocks to towers level deprecated: 1.05->1.07 damage per removed tech laserLayerBoss has 33% less health and has fewer lasers at higher difficulties bugfix disabled spawnDelay stopping on damage because it had too many negative tech interactions metastability + paradigm shift no longer makes all ejected tech explode --- img/working mass.webp | Bin 0 -> 49246 bytes js/bullet.js | 8 +- js/engine.js | 13 +-- js/level.js | 18 ++-- js/player.js | 185 ++++++++++++++++++++++++++++++++++++------ js/powerup.js | 5 +- js/simulation.js | 28 +------ js/spawn.js | 18 ++-- js/tech.js | 90 ++++++++++---------- style.css | 5 ++ todo.txt | 52 ++++++------ 11 files changed, 268 insertions(+), 154 deletions(-) create mode 100644 img/working mass.webp diff --git a/img/working mass.webp b/img/working mass.webp new file mode 100644 index 0000000000000000000000000000000000000000..d98237bc3b18ca1a87c876ee9e30ffa6b3d4572b GIT binary patch literal 49246 zcmV(pK=8j(Nk&FizyJVOMM6+kP&gn;zyJVHUICo}Du4k10X_r)Qvd)6mQ&Zd<`I@A zU&bwuuzk&X|IGhn4matq&|h%>A^y|*@9rPUKl7U-e z@PCy3^ZAMYU;91ohx>>5|NKAgzubI+e?b1_|4Z}Z=PUki{_k>M^WX0O{ds z`rpUz+&@zP8~Jzbzute%e|Y}g|3mz*$G`NQ;kuXoclwXr-*JDG{h|9$_doJq;=j6o z>Hksl5Bz`4Pe6V|e_8%Z_mBMt$S>jF$A7JVas7e*+5fx!2i8~H|JeMB^QPW^$$!EB zW$ZQUU(A2H|7-s-{+s)^?N`(P&wsuD8S5wNzuv#n|CRm2|7-RG{CD|Z_kZpGw4dF7 z`G2wdYyF4(j~Cyz|EK?}{-fXr`2X|Y@qgX_%YVH83;*N(XX9V=zwdv{f1m%q{)hkn zy>HRKzyH1eAO64oxA_nM-}Jvg|BnAS{}uhm{FnS6@BjaQ=6&A((){-N0sA}uhup9A zPyLVQAMg5-22>}qpAfgdk+U#ioy$=n_MeP8A7|aSt~kbb{&@JFBWTFuf|qnQ&W4QT zS++ssXAnd$%n}!2J>Q!?Xy{NJMn>mZVEZIH_WI6}QjxCw<5OMuFP9t`pMNF) z2FL@o0^8oK+Q0l;04wfQ@$HH?wh_17D3#)ti4b!CEK zL`I1s+eGg5WMdo$W*tybl?}UJQa9_#X*VDkY%s@c(n%x81#6w_&$s+zKvV?kJuN2> z$1A^xUQuqTyX=C?F_CN1h4k-JwFX}#&SZh9%kG{aq+xe^!_B z>;c>E$Az1j=mUmk!XHOy0rH|^jlESJ$){9b zwQ%g&Zw#6sNZ%Hf?gz!v_@R8O=OQAXpQ)yYarBhxdt-?5Tk!z<%=vT}UNT8E=FBrK z3v}%y=J%Ljm}Q~{Botex$=PT1lrb-c1n}pz_e)@@$Aj`fZj{118i+aXr{ka zkmWZaZ_+NdzuEXLN>&G0B*GDB0gl+%{-yUJSA9{KYoWiJEQ2~_un$!9|FuhWj=F&| zBe6M!O$*=@2vER?`YgLuhA5~UgGv8+JOd;{kkAr1*2JpP8kOgH|T zx{e{lek(JPYpA;uxsleDG_3-bD+aye{Q1-J=x#McDtex(i|08q{%-l(3|Ks{ldS>X zd_HC8W7#}lQ<~L5m9nHB!Z#qsRD%~2ak|iHK7pH49M*;WZ;4TRL?`Ijs3`hKxeE)olHS$s0_#chRL zyuWBs9zUt!Ant`_?ftr_@BFGZod2_l%hJnG+AnDj!B?=2eDUQ2y6udeHlnuARZKT3T$UvFsRhj7VD&;1ti>N=ekif9aJ+=X4%;{{QwMjmxN{~cC&|MG!i)|hmv7=hAkwHy$)SlR z?cj;B@d+TlxCU`}#4em*yvGz_6N3*kmpKXy55(IuWQOUKslPk7TS+mx-0&m1EN7yp zy=%wyV#L$*u{yx6>1O7IdWr7Za)foGvUEiuC-*oanEv6%o>kijGVMj~ZSHNkOmCQb ztC_k^emka=x8r&XdvQCEi%yH*&3{EA){H`XN5VvG{4BtyE~*ctE~UT4KIpj`=FX#4IshB-NpEJ@rQq{qmrM zKY)73CRE1;K+#?)RL2i{UmaE=Vz4VOg2YO~CXemG$^G_AD0bKJx9w!qod$aR2Fb1Y zdf^-j#s@hLnUR3)IQ-Riwd_aaj3H*^!2ri}xCkui=86a58Q8M34E&|hY?v=gNiMlkiusSgKeLbHD7!1hW&TwP@nzN??WfR`Jz>HQ{ws! z^scT-NYtv^FdS3G;Altiyx{DD6i!cx6ns0v92FvneX0Nm3LsV z7r8qE!Q>2X%xbw4_ZYO~53V%mJ8({^XE=l13i@drDjN2$Zn50LE6Bf3a#9qD*a=GU zzUYkR{L}}Ct!ICVG6zNS;`i5p^SP|{OYlPz5okp7LlFJtYX>|Fwn~23 znZ)M14z_l7OymuoZ~kYmlhXKKGiQ`&C@v^Qvrw6;ZHG0hdC}yTq|_TaxkGE|YW(ltAz?`hcjuT4K2ji9K=fVq)fS9gLXT=yQ6Bu>uIuiLviTmu z+rH8dzHYEY;sZX=mT)NFd@sGBjOa41(hi2PxXT4&}R>L3oEReI6fQujQHV(k=$SWHqIrli33IH!nL<(E;p9!}$&_-87r z(nF_nKN=V)Xj*7~46ZVB)bY-Uv!h3gR3eMM2><~8|NcE5A5>HjdR4D+e=&zFcB}3M z^rZ4ChEbPG3wiL(d1kuw%sDDp+sq{sd_eOg9S*ZFdMQ?(WLCwCN;F2toeNqkc137^ ziYQjU3QGJuCPts&tSN<`%Lf*w!%ew_r+G$1QwiB!pnE2*AJ7{^SyyLrp{L}K(p18(oz+;SW&68Vs(1WI>b!VJR9AnJ6wiN zC6x1~tD1rivY>>g=;|bh=q{$;oT&u^+Is<7t&psZICa(|_rwAXJCv+_ zFd?~;$9a0Pe?^7gFb+)Bzf{G8TD^>}N+G@)j~$TeWKIvyU3eo#6PPD)OpX)B&%m7K0`m0KKE0T981C7YD zW$Tzb?&rhMsk=F&Y?I#ZeX>X&MKce)SzH%3EtiB2Rk?&xXK?#}60*a3Nj8B)A8$$j z&dM!qD=10SyLz)Q%vns{S2|3o-Shl1SLTU|_(v+=g1O?-#M(8=g=PI3F_7n@-ps51 z9LS4Scn`F|vU2ppMNPrB1;1n2fep~4zM<=YC~QwbrImDh26iDWe_;z30W}`R!(^OE zvlEDvw}r@=26eo|#5Gl~6jouaiZn4dy0#=Z_A!|6UYk2OsftSNGn!#87*i)jrJrbm zD0!p8T_rm$NZ7Lara?{<38BE^3oA`tv1jH_p*r{%IzmN@WKowT`3rYYn-n8q^knHb z$%@U_a@=tIG{(~f9|KO+z{{_H0=KPv|OG@g#n+GaXTyawham zOPl9|4bq4Gv{ug9e3b4s-9 z_F-dwMt%4LJ2ub~^*nmjz*_*WS$rS!p)GvOCNH9Q1|CU2iEOW(e`l!49R0N(rrk?x zmcP?%J41&CdA%EmkZ`&fc5I%2tUVfX4lS}n@1V-DI=Ml^=42*dl%C9iEI7%z4)eAJ z7wYy62$@EcftAbW_>e=jTCeZdg0$2#4>}{A8=H)HH{2;&K_$332i}3(F$mJdkB6{LLg^%ZiaR~onMnU zuZbm7*Nue>ai(l<(T^jT*ylmAB4P##Bj;~OwR#rWm+qg1?zzWmw7#5RyOffJTiD9i zn!VmF1qgDQK~RE-yxQ*oyv5+j(0lOQfFMH@l3B1nT85(xJgNllM1t{#euUE?S6E;z zSiw+FT9BZQQ|h0x`rIQT=k<8^Zp;F*gQ{u}54V5$gNQy1OQu95yqbj+ z=B6oi%x4uJv~{xaPDy|O0R~EYdOoIHfI|t3`<%Bk>=jf!+HRZ5jmS_TkmBTF+y{lr zNYTcH!8yxi2OB;dEE#)t+YrUzrrJ3MX0ni6@$2N%&uoFOTPgLblj61jzAV9_AY2UTO*TfCl}`+g=j
D;iiim3|O3~ z18z++wGFu6YKVP6cz_xii5r+1l3h>K$sC@J1)I$@*IOR5J3W??K?L9k37AF&49T9W zghoIQSx3$7{%f4`zT<&D627PaAcRi=`9*RSan>Lt6oS*Dx&h1AG)L_xdiPHMFc5MAasK$r2YX-vsDfxc=XihRI^sgE_|O}4;WDcY= zdD=EL{Ls{_ndFxn<4(!GnQ$pU=SVK3=Ow+d)OU(h?)-1s6n)1G-Xwv2PW`5UD&72U zq9FP776nrP7dWhZ?t%1Bx|EoxFas05D`j*?h#M2j=S|1uy(0^`_d|7U9MeeO!uF!a znk{-II7otd=?_*w&I}OZ)msmT3P^C+?djSb(y`Jy4Xx9En1&Le9)XcgJ^!k4$B+q! zatK$~#G2FnIlKQlt`Xz_qk!ET3Zeof44Go-J8ZK?V%zV%EG9e@tC-q) z=c1>khPo`ds=J;h}g*c^Dp*vUmLS zvyx{FWhELi0Q?QY@MNv6R5E%7B3o)E{s2PL457lX43^}7-;-@J_$#0d@NsPz+r8Q6 zYGgVTNB!#t#sJ9=vMV*@<1Fc~U!SRuUM6T9-F5}UJ22Wazj>)Zb)>RnoM4ijrP|!pC-G29AZTROh~{FOCM?3$tymvfFB5q{m`UlYKWw#&`q_Y8rHu(`?OJ ze=}bRfB*?N1Lj&4Tm2K2Pf{8F6=?u$k1$??5T8?)XL2EBt&N}HD647()IvruzyZ(! zUDn+tOCH|bae^}SQ$5$(@`n6d z1`EZ&(fe|Wbwv`f&=s;kHe$=c*3K&+C6Gp#)liIz>XwV}j2aXLZ98X27a$6fzEa-f zrqIxyB?Hnd4q*rEETf=_#|++MoLA<#$f7hZ0F9R31oM}cVf3#IP5wZCM@Z2G;9m!L zK{bh>Fag&KDB)SM#-So!zT?vH41?;vctdT|rg%kf#;Z6$bm%qjlbtd?dAHlZ0kB@R zV0{%fV^ChfbJpcOWET9GzRvAT!ug=qm?%{%?B$&6v~G>4fCeU$v<;rXbKkQyy854j z6+LVVV$QdMa^~YZZnK~a`fqHaBrwe}z;7olToGrJ?7)ty(lXpIzyr#Y$Np`OIEZ_Z z8GM++%Qkf9ymTJ5Fu(Kvxhy*IhZ4%>Kz~6{XDPNvYcmt`axTHiuCrE@FUnv>U2Q01 z<_&x0c&4sVR3416q=2(THT+PNz8E6_0?Itv-+?tAsKldWXbNfY7-v>^CM5t)dNvKV zp^-%Bwc*n6{fX(K20?0tdpmA>$}tm7M`ie9(rY0fv+z~I;YsHbQmcvcDzQEv0WBWF z{%UKm$Kl?g|*{GWj4vaR*{4X_TqS#qy z6|&?VoylEC7`bjMoPErD-Hr(Hfe2;G=H3fW5$u-$dk+z;XxofvdK3&qzZeS)<)W1)#G_j{MtLUm}|eb@pKB{gLVnlFG`+ug*v5u z=>M~%VF_#JLT?RSBR4j&gC$BPE&45CG0AnDb@_=>&h6s=d~LxR+d^{@BO2GbPgmq4 z<1Xqd1uBK&`4D#ZD;1<)(V?;+Z~&!1z!GpWoO;4?#A|HbS}X)vZ51&n;EIHoHgQ^K z4g>62ZPYIQiVHzUgg7*#L|zAeU}>5OmbM}08ioIqjH?NEW@JR`|5ZDdm&Vx<&W)NF zSnDx4f4AxYl%jH0KE|ydDoZ`@p}0gd?(VEqq_yIB0qkGFZ`}Nr-9t)5N89gGIZX24eiVv0{{) z$jmx7ln_{~B%g}P$1u2Z?$W){;}JGUpLLQ@l?G5Iq=^STS&&o&(Ts zE-Yc}HxEKak5v*qn8AlgNR92yE)MSlqbVE1nTl?vfxfx7*slCXLgDp#!)`c-juUXk zbJvWI!06m+NLh>uf7uw}%{_?lmG8uo@<%)LIl}He93%7^jZK81X&#eq4P^B*i-!?& zym+>M_XXN@rxSPWF>^f(^Ipc!)f27HbR8i1ud1bd1K-D+(8UXeb1pB*Sr~#=I%>Yj z+(lZ(?;&zzMfy43$Tv_S#oc+vT2Cu+aP_tx{u8Y~_%hytFI}24_sPa8FG;MFO;A1l z7yb^V?g6rXGozQ9hB zh!ENxZ_>E^zii>*VgUO*n=2yvwB8Ri2;Ud7*C=OMleAjg9ei+04Bj(hjRCo^(wWd& z<=8%?Hs0(G6$f}Z!SuiP4^7xq&0dOtXq+x-FVtEhAGEvA=leX~6Z!%{%EU+@e1Oy} zk9bM;=M^YMKh6;Y;9iqz1vWq(peG+|Kn+h@Z|i=lw7nFCI$UgQMX?=oT+b!wX(N{m z(9D~;Wm(m60=1agMB5ET;z>b@XvjBd8=w`eolm5`IsEkCws+gh0A-mVr1*?a;?0xp zVFazbj`hN)ND#xva~N=O^#;v~gj|K?0x1li;zGo|T!PIC$^Z!apwseZ>U&fo%kG5AgsonV&*^*m z8pKy|lT?%nT!yu36N_W*Qr>%2lI8X?3jg{#qDI-;Wb9ET4F;^ot+5f4-0v9aE9135 zN#4LB9G_Bg>%$i?MOSDX!?Y|{yhhcmU-#NZZ+2gXFu}FDBCX;LiLO23!@;O-Di+j; z`COy^KBJ}4orXf`W{NYuM&hlPAuf9%U)Yf3ZZTFInxrlk7dRe<$2iKxVq z2m>4dnmN!aG^?a3-PjK5vs#g|h;Nc_jaf{yp*Vm~hMg)L0CsC#Dne7QkW)ovsQwQb z8cpWFActE|#nd1Sd({iuzf<8o+8cmiyUcRfD<_{}V^o5l;PDoK4%zL#0S8z;VC$jW zhi1WzAWMx5D@$xV_+PYQ-9?jqb^b)OIs+70PxO`tnMw8F&$8z;2keD8c(&H4yA*_A zP6gNn!$ z7Rgwq3o=}$G=fgIjQA{$AkksaumA8zPMIONgiy}f)kIrcjS*t$(I`EsPo+}e5=OIZ zWE`U@S&cF{FSl3C5?1?G1EW&n?fHOBOi@z^1Bjv>pLcj(;NJPCcW4ACA0fjB9OD}3 zdkp0^W_XCao6z~vF!Kf@sA#7n^gVX_=f^kNRKkA^unD|h(9?|<|I{`9M z1zIrD^HER3KtGKM%8NDU`!HQ0kV19-ahba#tL9Z z`Erj&5gA>XQuoV@=VExa+N5lY?va}>BE#S6Qa(UfhY_b|f< z3(-{`|7$v$vX5(uhzN~aJa`vEz)7{5*Lz3417k+JG$kttuZ!`^KSj>XUGE*f!S_}N z65|umP)a$+OM7-QFKEb>S@%fT1jTaeKnaf>22MPLX^8ncU2_h44PV5IITNvWu=D)|?c5G?Ol;ZL&Tr|b%A`i5XsgFc~-F7AX zRfWPBi%?~FfzK?b?_Ve;73q8|YR63O;i4V9N6pNSR;}*9wU+RLl?s#Lx6eZ(IQg;} zMfRF=Asn7S($0G71Q&)lmoGMNd@o>4r19{ENK}w^da&SzURWzq@90s%MO(40+u^*9 zb30&ag$&DBXm*&dheWjiY=TGGlDdLtV4pVpM$f`d5X68z8-OsD*CX~99xN53$)9V7iDmu_%=Av11=$kMC1OXxk3X>w zE(-I%=t=$4PO{UmSEg=Le~k;JeSB~l-$#72I>};8K@#%U{uuWyR&^_z^h*_f?K9P- zPR6ZD;JZlIlwJ}>-z%zBXPw%#?uC!UYno%^Bq~ze3vVnXdyxuot27|k7q8^pbcpfv z&Xn6Etq?JE?uQ31T;s>W!Nb`6OEYT(sFNi_Nx&wOSi%}My?1e3a6K&2#NSYugcvpR ze6CamHU8=PFAW5~3Y@AaiU|-yu0;mSpJw?sAmk6*Nn1WfS0j9MosOC&HEZJXMk^GF zQFBk|UnK?SfQn-@)>6J2zWZUx*IojT!SCb+qF01=5HvkV(Xfrx5N!0O9=yE=4J^o# zKyAqS!sZ5a{~PJ2R~8KcI2a2D08jCR!=db|B=}|dREM{3a7O&~`rCRcsn3%X~W4x_w5G;+>%|C7>Ws=V=y zwtb+a!<~L%A@MbvpziN?9&XHczARb9+N5P6r2CQ_-r`EEJ+ETm5`(r387{UVbo{G* z4I!Z+{JYZAl*qcdJj`%s!pls{c`zO`k>4MX(Jg>RK_~AFm79KDnLZ5v-$Q>Xe?|?I z`x>mOuiFVAJ=QEgnfP(3$N43)3^&zxH!%`FJxXbi8c}wTzSBX!k z{dV;_L^39aQ|y}8*h{5nFF-~YTZr|yr8*Ak^~e-aNn#^x4O_dED!K_zxdV4g`RRI5 z-;RwrBg)&mnsb@Zn|irX>FC&c@(+E6oacnsw2J*(E{aXvn(bW?Iz-0OSaVfKZZwrA z?v4vD3lH5>M{|eH9m*C{^8n4PYCPBQJh3~h#n+;z$V|#}#?T4S{)Ah-{oafgalzlV zLXJ$m-C@ce7acDbT(yKUZiWP^zh9nr(w?}=;C~6UWAK5IM4iPVIxP$D#Jyz39@wTq ze6sQ&LvWgVMKTvzk;{Ta0fdCE9Z^O1RQ=qpeZO^Xm0rkN*$ZDOlY#2_XNtaKL#2H( z?|6&5w`e|1NvP3#^wOcoKiFa$>HT7Uk9&S@r;}cwD}F6qVGGe)F+ee4)#C{77vFmc zNEgd3)t>r4a@dQFy{}`GB$#WRxq?sF^MIC zErY-caF$ciZ?!mXcoKVwbOxvXay;Bbcu#0nb9N4CSv=kS`JkF#L1kq5?GM)3;5&C) zq355Osvwc59_N^eVQ;NYli`2(y_`tnkX(7#fNB)m$((+DBgzy+%0NE|qrd$-qk7Gi z(nF+g>ql2~V{LEMMeaFT_C@nc0*QzntSfnJ78`d1|FY6cc+ipY0t)?O~BQp^1q^2(F;6(fZl zBeBB%2|>d;v6Ou81dn!CVlte16i11v^l-Feu;SgPY3Pv0Ej(<|7wU%>XdtLn{ zkbkiC5o5G#`Lj18Mz~QsNC@QmpD5$WfuUec{11$6Z~H%Hc&+4%*d5G@=d+7b6YbI` z8L>GoIOwhvVz4BcA`cUIDn;&HzADe?rK=g++?WLAr8w`d!tv|mYfj~SX zFcM|E^k#7!RS>wLz!-#$M7A>sYHUH84>tV0JsW$F203umK4YRJ29U!z#P#EUSD!<-fZvp zu64~?R{!y}3gCO9VZQHTQ@5S;()N3*JB5@3LeY@rfrOOx-?ksb#UIW>-S|?9$}>v* zp_m_ZJ0ds0Bys_oTs2Ea1mrV@Ry$i=a2m~1+s<&*TkYU!5epxB$ifOI zJq|c6xElZloy?5Q_Z^26qRpB>#0NK(?LQemf)d!^TKd%3E$*MsMR?^)4UTj zAX!^Xr&WX6LiQc*B^B&+3oT997en%Ipv}OW_t6?H(tc~i(Vlp?4PLy3O4&ik$aUz* zG+Ox_@m1>=iC_04EoG%V8f(6;jw-l99DZ4Lxh2v(DPBdFEqER6p_Ij?#q@~b;frBH zb8H?sG?G;IP|H9azdumP7jo~U&}|1x6;*J+9BP2&%ZH^s2hN*R6l*^5gnQ%l3*URy z=D|Fzive^{`yH7SJe=2~h!|@*$kZ%4HkA6NIML~~@%k)gg}~stUg_uW7#2A@72O`A zoieiSYn%+=p++|smuHX4bkbsnt`jA1zG5^;=5v1-*4Q{u8i++hvkE!OK&uNgfJm3e zu_AjVi-p>QIYguL8x0DP*zBzXf?-L8oPht7^vH&_Y7nhAxm zo7pGPna1a`||-%3Lky*A4Kq^#=L(Yal-`a@{8aS z805admhgmtVsM13nv615&FWK}VU3mDQca zvC@8x8cA}QASSUAKiV&+x2zV^7VE#W0h1Afn3=h5WZpi1L1aP`h{>obO!B5<5_Tmp z!(>)wBFb^as!tq`1S1p}s-PA@4dAOkkW&>S z6dcO*cuxw)Gqojl<5ArE6KHG`(23Wz86sBb~*offH4RDmE_o)k6*K4g|bQ5F3Rl{8A+d)&Oz^{l1q23t=80>T>G~ z9tGH(?|r3fx$-r|y=nLuqU|i0J_rYuwb(2RF4BR{1MLqu@&5oAe*s7D?eWP-7_1X1 zpGeqXC4_*IkDgY{kSFm-SZ;`j=GVQLXVko*`EF#d5XGObuR8cXiHyk*ducMb`Nw_wL_^2LKO()<& z5=nL(QrhfPW5k$^01!BW6-={-{1dr ze~c43dE=}B&T=1k)*$r1V(~fbOo%l=$R2P+G)tZ=eg)0_gFvO zsS^wN;{}yzQoX&Y``L?<#)ubO(X(FnK$DgVZRV`wQKd7;220OX0fVhI&5130wByG~ zm54$+dMhiOCvbHy&o_8;6J5eT;LrW+fjyQu>I%Y;z%AUdWz)BKagLC^4EMBK(BWs0Df|M3>n2Y9jwm=3WZV_t6+lY5lsKD22g6(OEj=Ny9}7@S z_78wTr3#jeKb5{6fSf%*kKndJ-qK2}Kpza*td^+9(40au;k6qK7{xqiS%fFPO@e_I z-soj(HXT-At0gRL$D;lV6mBWdY=qV`>sEde5{X{vm>>TQqohbB6ZUlZZP(#$nH6Tr zMo7g%tfnL<*ecb-R1ea zEOo6ZZQJ0Rk^A|OB_I-W7hAXbgzQ4-wEFe&v|3^vwG3zsE=%28Z((_V_W|l1P<(NV zvx~>XXHQ7b7S#Kt?m9=X)nI z`?B~}M>{*-4F+ie8^%7x!dfQXd!223fr7#q)+enMUBV1gD8~M&r2cpHihY@}xy(zg zogvY3KHA(cX@w-;Nf#Rm#eQSzocP1-HmIkLuBi{IeY9`7uGG z${_v27f{>>m?0ovMkmL1{?<0I#}qM*U|&(!bM)5nxF6^lDtA3xd5Ge_YrjZ3gTS%6 zb9@0kKA0r4=D#s$q3~UdFIn^L^LB6gy8GGt#3-3)id+V-cMDBc_ww_Tc7`h6W#hhL zJAmRgT!Y2_)wzL6lL+L5qk{^3#;gP@om0TaMM11Ns1IbuPg7ns(Nz~wR)Eyav7h$A z-^3<$CkCP`1AAeVy@cprJYwYn_o`+r_HK>(IzB-XjNCydEds) zjZ;qn<0q-RQhKjLCVeDXpQHE^l_u|3m+nECd%mYms_Du0p~0sVuqM)gODOP*nV|r}&Z5h>-h-h53|~)jRffNtRX$2m_IKR$ zZ4Sqw0^a;>TxC<1KBnwX*gyx-Uv~gdxvcz%KqRQkm7qH6rh*2b?z5sP^`dOItB7xf zt8zX9MxkJz0)i}R-(P7GxP|48AT6qo*la&xqtg4F#lAB^iKLeugnJmh(50R5+z(=@ z_EkQm?R&>^V|>NIy8vTGd#nnytjq=rZ+0n>lwX_?Ls~Jap9phOM2QPHLmfuBYcpj5|_d%;O`8X;f<(1N>HrG#Zs-@1-fdJsC z9C#8)!-?=-7Z%8RN)y*t; z3%)d_lm&r|n2Kp?)1)E*B#Wh-u5+yg(ohed!0Uj-XydZ`6tYN8|I6IaQDXCk-x2l= zeSF@6MaMY%3*rHOA3S$|aF@Is{nbs+5uG;yq!hSeJuAV7Ryh}WIKr>%f;FAk0w!t$!?wRWCP#w#PMKsH}et&Lsf00 zND$%S3^JbME3Y~h7AS(q&7g2}67h>kUNhlXLOLjxDbtUCEaRl)3moMvzAW>%LoMh8 zjC;470Szz!I~Z)K8b z7HQP19ks8&+*iwMoWuncK_5T#MDuJK{4@P<0ug;Vt9B>{eD|_dpobM~WTDIxa%Fmn zy&q;q1pNp{VMOgU1`*5WosJpD&^v?ySn5s0IbHh4Hm%NMqw|%TNj6C&WAd)7lw|@a z_zRG9WtbR4>DEN3Out{}3tm8=A51-tXS$b6n!qL!Hc5g6z2`qB`$hZ z&`mWqP65kW;4yq8G@{@T;sA|>S`0D%$!NSy9@+p6Rb6)%jSY%^*zj$Lu?|g;Sy@yvaV5tBJ*>d{P#GREK(!DomzQlcM8v7urRag@lx{>wyhL=<= z0pp*x0X^%C(D|2TeOgftUza0HPy)@0 zN59!%N}^C<5P^fGHcEMap4pCMJum||Fvz$uN|%TJWiRn*(H!XW0g&s{#rbyE3TIvc z9V{Kr45oUAdS$}wfHvQ8ylGa>bs;7uFaUzZdw^$aG0JUQ`Tj`l;zR*|u{UGe^i)=9 zdGna&$pAy*zW{~l>}tTaE5|Fv){siZ39ww{4WA*I(>?G<%#FXK+TDdciz=; zh>uQvd*y-wP-nM+4&qH5Up)@ex5T<0<@s^v&2Od>*Rbe6gW`9(HvZ@iT3=eOk#K+) z3~uk%mWbe*$f)HB*lxM7@+G%16g98@ITn@?J|3$_Pno0Hp($kCWn4YtUqe$$Tcp6) za6%3(%hJ5~=?`TkLMUs(9@VG$VoYBaKc6B|>2EoG0ovgo@&Kw~t?Zcsq% znXzzIOfWwJt^QxaJ!DDB=$5gT?g0{jQn(;zx9|rFBncbGQBsg<;0m?1-wQ>dy?hsACy{Q$pBv?G zZP4?2ahT}p*pXu|K@80j|9rZ-4p@~H`CU6D!cDaFzZ4gNmZR7sV{WSzt=bWXVGjzG6O7N2RN34V(in$bYF~(za9MJN!_8{%yEq@>wSj8{ z8NY{!u^UY+Fom0e>ua3pewUZE>~SY|G{XrP#EI>gy*MBK78h35mH{C3`a%c_gS9|5 z7$WgRFz9u-U!DlE80s-C2tu*#0B6%{cZ~oaK;XaiMz|}5P0>@}0&UwsaV^Q7ALji3-c$$3n!7;sJldnqq{j0M5mNSP zh=}Zbu)K&4Kh{O}j%^ozR*nv|1vZ>`;^_|I&`7Y2Rma}Ai_ns+4w8%3nhHmTsQP<< zm5iC(y><>HH!@8?3hb40&i_;%&kMmZqx$$)aeLSQeNG$?tw{g~Qn1NtH+!^@2#!Xh9{H=}cpw#U7$)P!}&$oFERo|I#OYbb(7!MN7ROr?aF(0WW~8;)51x!cI1s~I;@>^Q zk8qy8oPAgOXe3~{LU}ulC!F_+$|h?dODlE|POE{Ilzb@hGPG=BA0LhCw8LapHnIZ< zFH?537)b*#o{d|A`u#o#XD2Bu2ajTnt(JbgR%ai9^Iq0;X_|eDGg(0R*dgHqSdnO# zjl-dwMd!%B%r{mGR2X(|r&Uwb$EJ|V)UZ+dqJ+i8V|d&N6#GZ7P9E^IbQd4axJ#)# zi>q!q?W3)9d-l-Y+JspToqDd+p<9)gY0BjH$99{Hwi=&MQ>@vbt4%=*6YZfV_C22+ zZ~kV*DEz?^6-#$rp)u%X3A#)_-Yw_TMZr~KBvO7Rw>$@#jC?Bue}LfE19RZr zN=D@iV(7jCdyDfsgTSXOkoWTU$Im*#s}w*oPw7tjxJ)aUqxaE?@^vuY*tdkKONWc^ zF6#~8W5sk2KP6XZq^F}4{{tqa3qU~T(jkJ1#U69H3(dY7-|d`4YnS(T@?a1ZT(5u) zRZTyQKxrD+8XT5t63m>lRpp>#g(@yAakm>}P)Tgz#)>{4Fm8;v!y&24B*%^J!7gkj zQPIF0+wZ5Q<)9ys!jcIYx;;FvyNQ2z;M!cYX zyauNfooB=aAP|Oyjf(<0Vj_>2BoFv`7XVjFa2({>ejz%%dG3W{`NDtk`i@ICLgB}* zAoA}E;6U(-ojn@D#cForIu>;yV7X8$fpc@NIfb~H)>VLIVrs5{^%`XV$7&pv#8{|| zAMKXR^~nmWgZ}5I$`SWF5=XvgzdcHw5ik9-rJ&vP&&tls_8u1#s%Qr>9-j+0N+g)|xpS zUEji@ma>cG5(&!+|M~RHJTp@pEvAFnn3ICD%lMOKWF8FfPU%DYAqbzeYm71oT2r!) ztMJ(3WlVLAJ^Yq3Ks6Bdq(MFke7g0Bk{t7kqezXt+j#1kC^lSnfB-MJH)}p!*StMe zTCDO9tsw(xT5L}?3brT+y`9&?Ra=K$to&C6mQEyLbyQDJl$VZw>T0I`qgw`-mAq;- z$`~JwUue5H$&2DlX;@Y|Qeg$7K+dp6H)7JCk6LIFK77Wz?VXF|&%*+oe$j0gw1y$s1_wEKp`zOg8YAxP21axQ};5x|XA670559yD>U(1LWK@)2* z6w!Ph9b<2;5Bjy(x*XpgF22uRzB`gcwGYeyzJr6uaii;+g?uWUd&9 zp^9IkRi3xnjE(PA>9N95Ql24J6)3DGG&725!PA+bQuJV&sE)Y+)WmTR7Kut4jJ(xFK3pU?2I&5#VjkVq2u@TiOc)Vh7;(<(WJYd!8h z&~o$XA4uhGEXR-i=!1_I)UXxa)c$*6FTdp~`e_J7HN`ySgJruPb&RAoAn$AB7fN3l z9z!cZ_ga-xwH8l7UbZ=XsS6EBHL|T3DzER_+yy5L5Ao`&LkZ5n&`I&q;ky*x_}}Z= zdU0_h3@~EK-JF~189$R3Yzv9 zFR^dhgenXNPMh%o6J%lO`!OK@4bAP7((8Wpe1m5d@ZJ?M(^!9Lfn^E}8V0X?)XJOr zQI}izNn^V(IVjx!f0U6u0X^?W+2~YN@%sAw=fyn+60#FW+UJPkM%eMQ(ksctPxH+~ z<#_+T2XG%Ee8kK6luI&bwQ$=!SCaIy(bFz43P;)rY*ly8^_Iv7%*HRZ5N$&l#H$t; zonYc>jde?jM!u9k>HhnLvm&JyRqWSjpaI-V$Fr_6IYX2$&2JL_5GKJB)4dxWCfGEg zhBffpOG2Ler0^cPQeKOSn|!bm0e^(K{BcvO#n>H=c}|TQYYIWlGvsgM*`&0jPA?Ub zKpriJb0agN9Qa{p?gqXO6BGf##J$g11az;O4YZ?3MfF}LS_ZqtDw+%4-{PVrC)C#x zMH)S^#6MvcEzOG}Dd{dL({<#kl1V(Vrs5rS#7?fBu9)QVF9(rt<0fnB@`J*2j7hhs z^YBcoGlB*pi0WVF>v>OE`RF-@*PKRfMs-du1-5R&N>}%4Pn@W||CzL2a7lrUc^9g}8#9oe_R+1e1$i-pou|9K7!>z9kBVU0Xxg>1y|^heOG4(- zvpbsYrzRwvu(!k4d76XB*rJYx4|zTyEC%M|3k?VMaHt{_lmsWGfxR4ympBdMFW5Rk z<@6)dJAnHtm=n$K2%sHDu<<(|Can~@vs9mq&dIYkD$6etrPe#(9giC~qDKXQc%YJb zHnx9DO<3DqTtiytWRm&(m8ztf(!jmN&YXqt>i?zCg%bFS(w7t01UI5h<5hW5`K~9_ z>6K=CjrzNMUm}bG<&nJDU;r>jZED>o%^XbxaIwTzedWJ`ZhMBG{5}ATlZWs^QAdD4 zjt^PiFAH;S-~J{kzZpa4ML2aXl|ixz^Y4Ouf>73P`g~VYI?ac*Wg1MHfliE`WC_Y( zHz4G0#By?L`^VIBjZ$kf`Zi8DzCtn4 zIWs|&stKmj_S|j}<+_nWhH>~wo{5yb_{R-t7qc&Mq>2Q9IE+^qel<$(ndKS4cH5_Y zCOWNOo#)T>nQl(5k|W@Rx{dh2VzDj-PkXgTMJV@(eRt*wqj?Olc=99Buyg9*0@4v7 z>2s_MLUeY5Ev6v|fA}H}3s7~s&m;JX?(}Tx&xq{o{%qvS3n|o=a)Ds%pk0?H8}SzO z!)-atsjJX-baMlZ4w@q^_*tv6@}B76OnoY6#*P}{JYCF^MrudDfro0k6E#t%3_ZL@Q}o&06&Z?djiP;)8yjY7mwADjGptStNtDD zQ!aCfhTjOQ%bRP7clhr+I(*qS(CKjd!pxf$b&L?GxUDU&a1MpJr4pthOCWPZ1t3~= zoirqthD8rIhZP+qM@`?|7su~Ho2_3rM!tRh%w;| z)2DFDS&1UxjW!|J96imPhIDY=`LE7<-#beeTDGR7-oTUS)-JFz?0@B|6AHhn`R4H_ z1yMts%EAc3i9D3^0aiGCDchtX=D#9hhsV4+{R$aL&uJUI=_w+I`O zsK;+?jgi`;Ub4<3o~dJth?db?2cafYVHv-{_>7b^;L6a*UFPM+xqlv$wLLswB(4Nq zw|^f|sjM>gKHXkWytr*m-P3vv5R3fCPsGXl!p_n}nDh24NUJ6stHLqg-2OzSxkEOaaZ>U2C zqKi?>D93c6M-wz|3S>`5mfL~0ju)Q#lKA4g(UtAOsS6NWaALT-T=UBCs;j69&0C71 z5vLq&@{mjAJPYKzGSrkZHyiKIgJ`5}I6Y2|^Xtzr4K_qRsetnzF=Eqa7$Db&aPob2 zG9Geho@ZZpUNDClFb86alNq5mtZwf$8sF;#=f*!DG`jN7Rczv^@=CpYv1E=qScuRE@HIeI|qEqyVcb_|HBR+_m8}=c3!0Xo9~z`q47p2sEE-g9LIz$GWz*%};Wv<< zW9$@%*Q_sOD<8;W!V8{k7{1;263dww>eFx>PJksp#>2G!emuGzTYUMYG5{SsgEl)$ z)kM`KEVFV#rQ@U|BW%Qar&$xmqtuSgK=V>k&eM$?sdfA1h%1I-d+ORdH!FC8n~Oyt zGDHmJ4zF^pw3b42q(%7qm@iTN_s&-W05_b1IfS>J!WUp>UI+797D|sS2!lD1>25%f zK>1Z{K-2t%0V0vf^t}Rs;Z6IdFhvi=Tmu28Y(PQMP5rGysdWo-B+s09I=s^vZ zFn|IHwUmW3@yIF6pVv1y;{x7k04ovLzq$l}sC{|K1wi}ZFf16xqZSrBOkw|zde z@Yrp8&+09OU8IHV99!iSZ@rjJRaa|Jz0yDNx?gXsk_^Aemi?_|3mO3di$vOk?fvt2 zVWkbhI?!2-lJyN|Vpc$`%72cO_@8*CEp%}aB{*898|vqFeS}W{z9e}q(4hgCd4Uc0 zU=yF&l6JbP`hNe~Xluuk2>WYN15@fv75yr8m;S^2G2RR+B(_#z>9qDdLo{^-+A200 zxEUyU#)ZLdjB?3SO2jABO4HsZ7pOv?A0=`o&Dsd0{a9zR;9fsmdKk*99_?t(ghB7) zG^ln>u8jfEiBMl-`U~&1&#C4sh?U}j8jHZP!r{~Ttm$i~XkiPNX-h^gG?Bk4#sSGQ z8k>X5P)vDQ%8!Dw!|PZ2{B55t8_~awITzxfI0|3k@c0QhoC+9lW#fa&bG>p#j3Y8p22SDLPlyv@ zBb{h;vE1L9FW=X}orLACmn7AV5wpEjm1h?-MFWo(?Bk`ZSW~n`HaDxx^48gp`cESg zw_@3WJC`4|mtXN+ht&R@p5}b7YbI3@p*@{9t+sN)`as+Y?4R5T=3Okm(R(J^a?Yu_ zqw0d}RWUt2p#p z&5c_i%Yc?J`;E{xdf-u-Uqltg7a4N<2kiH!0m$hHgzm=1bOGs0 zEw8uv!}Z{Te)iZu`13mawVBoda4TE0aQTBF`jUyRI_&ee_s#k~=ZVXZ{Ys7X7qI6If51@9PD%WoiQGZl7~( zjC${re#`ePjhdOLi?2>-YUmKimnKvwW@T^}A03fzm#zQl^ggOIsTqY=c^RCqs7sc= z=>lxlpAv|5yKToVNYTcy?FJ=h7LW;(fGv0x`8V=ZDv8zr1J%2k!D4DE;~a zFonm!N-=E_g;LJmb!4ps6RZh-+QdPqGTtKY_dQZ=IE&YN{#%vwm7v5CQUFnoqJ^T^ zYmUcXBaLO+OfNZpyNzw&k*hDy!-hrHVi9uf`z^!^xe8%)4GQCVW^v}B$}Aw`8n?QI zT+wdi*474V8OBLE?hsp~Yd?<8GYz)YVu@j)c{IoTp-GkQvl9fn>*ah_*41VpD_wWA zjSssP>LHV(JK@}EM}srDaxU6oqLeYC!RCTXLX@XGDdp^V=lE1q2*BKdWW&YYD4nAs zgoa*|%zW)aryXoM@%z(-s4Jf^J8~587dW1pZS0`e-5hxUM{(g_rhi`y6{wok^)ESu3#RC8ccQ``4hv&eP8G|{i84z8u9z}E z8CxNpfg1(GQY;9P#am9wsen;ese~8s*NKLPM-by$27YeaHmFer7zL=N0Ms!lbu^Eu zd&JWn(H>Zc$PvgG@a%r$lFgTa(w%mcE^`gRqID^i0v|aRC*Joc0peBbl&LW5J)fc^ z=oi*Bzq)(7T-8tm@C%Y301FB3!hQm5p7vEl)Px$Vs}03i$V>gSo-cPbIrO&QN%vr% z=r=!m>}H|oS~Z`t2i>!I7}XOp&cq><<=JhyKj5I%SiuDg$R5^`^L|PmWLJz?szcRYSLlOe{C)CS+g-lw zO{}W+`$S^bnpj}JJ#gfuRK3hMpVjv`qHX1}zZu0$P#z~k%sJ+*nV~p{N!)d+kk1gX zKvB?xK^L>lX!^8#mse0cLA;PWC0Nta6@va%$v)lFFNP6JJ>>(n4BOHU9LCm=uLS5A zKdzJHpoCk(Dm+pKSO}&P^t*|;f0A<$M!EF?tiOG~gDq7v3q9xbmL8A7sa{5X z-9`U`5vQ$mt16~+Fdu0dvbm93QRgR$c)PSj*wk%DvMfPQG!-|N+wsSrWo=pxp>C4Z zWKn0zj-Q}M7mPOC%p70B;kIUa&)771B`i`qVH_Dc;w|YbOw~v?v%eJqvC^Yyn80eu zxhcrql+Rozj2#yO36`>y9s@~yB4lp;pr*3jAg?PKNn|}9nLSJ%9k`QCNP<}QJG70~ z8F14txwK9b&LN5-o;Od@S}|#io91;wQ0NI4OscnMm1chRY3FJOINc(QD{k)tB`w!- z8}L|ntNw)u-~hXj%(qfP@N%{)!aRk+A`Bgu7E0%bm2E4u&P7Px8V(6>2ZUV^d?yaJ*KfmokT~9j6EXU2;4O$RsVcoh^ab%D|0*ev zbK|QyiN0E%sD-TnQsFgx>}|@d&XD^6MhM~Zk@luzTwf;lA^})+Q!+k8l=%0H5C@PJ z$gFl|&XOA&PVI0o_O^VzB7GkL`4k?XI<0G_IE)S=aO6o3S~mB@xn|$75gLuS{zvin zMj*GHq20(@_K2BbaI9`6O~oB;8+3&6C~<;4 z>CAaX&=VW&c>E$(FW6YbEoA%Gn-NRi)tQu98@Rgm%B#gI-ivdO@9jGnSw+!}uut-G zWAI!K)--iwqQe;&G4u!S3jDczL_No@!Ix}oH~?87tyxuSKggWeB&6G~k#J2fPq|uE zZwlsiwbxsUE$D|LnD;tcx76!7qQefDcJzG?^;E_k|Kw>I;yGg;RRmijhEhQ>9`cUm zfGatVXQrAwUfJMt>u>>#k5RD-B9X#Bk4ZQPb#wtyo^O$>l8HI^l-%z%xoc-kFs}H< z{kklYRxd)(3lDateUPXfSV&!sG||rc(jko1VlCYIieS3V2?6_?WqhD*M61n8sm+N6 zSZ9Hs^$>pc>%6Oc0&i|vBF(*{y85obnJ&8@TVO&Nf#MVJ*aBB@klw6qk}_ZNAQDYf z7()R0YqX~S;;Gyjc}zzTU|>))X4Uel5`F_MdQP$Nnmy8@S}|Bvp_ey61PdTi`PN@& znIBPbbwKnUq3S-8#aLfxZsOw)4)nFPzLIal5%iy7Gri?>2GE;Fr4WW6lE6mqcF?0o zo1wtR0=4tF(2Dh0CttGjgkes{K&+{U9oij9Z8x-fP4uIWS}lOUEA=F*h_g$ZIIiD(_nk_u`Z2jtuS|wM2ZXHS259KigYJL(#ofID9nKN5;Po$H{ z72UOB-#X9b{T^oX@{GvwBrbaXBppDFkqPZ+;+Cnxe;ykXMpxa5Fm^?6-S_KT4@~pedW# z2$CC5FkyS~+NT_&fa+x}E7=WWP&`^sU21q3OymK-d?TxaUwJOp;{)2Ge})MY702Mk zk_Pb8k{a@cTe0{Od=$v1<-Cv!r#-Pg+P?*jAE6J1EEiitK%U`*?z081q)mK1g+MSVbYh@69eJAOIe|afRt}GK6D(u8-a7QgAliz(+Aee;3J>wu4E7sD293m{tBJr}b>S^< zSTF}F8Dq=tLFn_TD%uYQ z0F3Ml`evr%=6s8wRS@oKszBXQHU*4Ra@k(k)j?nZDJ~p*_8@rF6#g(%5yYmExeJZfCf9($ z4e3kFaIXq$s>dui4X9SQ{C#ZD2Ld#F3j9XDnv_%bhz*M+o9rCsZz4Asn#}}6s^j7q zh|?+bfR8x|5Zr;$0gULmA*T^pl9%0m8|AO|$g0H$5}5cvX)fO15wl}#1u z%YgyTFa9fG6aFaSua@k2<(N(m{Lc-8rU8`>KS21NPhRG&hS*?to@$O7+C{#m2}~z7 zRq9+}M%~|!eM2O=C9VE3Wmd`XKU&@@JByvcEQAS=Qiua7yNnx2>f0iK7{KM@^B;M;n*4Al^?&Jq&O9TXzj`^WtIZDUZYpp5ey|-jJ zX!|1~eWn18NZjf0se0T`NGTMC$Uei}ClILrGofu}JOnM5(5S3|>bjJNcx8|RL8ZL! zo}Z=Scl^}tLd~rbP4H*pTj{*w}_` ze`fk--^cLc7^3i*ladP4Fo>oqJn8VlI~edLJL@QQScFR9nM6Gv#08A;TvL@K{E__x zX*Rw)1rro<`MB_5P?eU(esftLdcoEM(%c;S)0=pZ`?aEYtd}yo=b($>;ZpX&Err(Q zF^OG)%nMsSZ2HHhm=HvBj+9(q-2ewpEe@#W@Kz*JlE7mG^QlMUD$rF?d^-$l&h=?f zO9oK!!Rd%B9w>v%OHmT|{_X4{DtR;o%RS@-x`);a+_!qc4k}C@V%ZKKhA^MEq zd5i-0w?98#d_cX??hoFBa$Q<;mIkz~>hoV9HtiQ}Xdw@)Lv3@h)}Yqq$XoOj!xTP6 zEtkI?n(8bR8lds#yTA8azCoo6_pSnBVhd z&-Om^$}_P}eOVy@^(@f_+IZvs)d7xed+6N98#VjorV-`-S~jO*C_2J@F4M3EIwv)k zwW{YzW6VGIsMCfO?^sy@YFzaDxw7PX*YnEvS=4l|2se`;brs9cw`h2oIGgSAhjb`g zF97S6^R@h#v5cA6ICG+QN%&z=uPrY)R9d`%9ATNv(LAKOLaQ z7|(fvMX8MaidEbvXwfH@_#PzL+F;* z>^7drtE(@BdLOSMcOFIrh8Esl&v0`dZEcF)<89P9v(8 zSV#QzV^ZWD*ZCSIW%Sg8y2jJP_Y}9E^n(pa0I*`H{R1v27KmLgVhv=&@ zm;#a@h_`O3PJGq`YozY+8I*d_-trG9$24}xbJcGm)MFy~EbdfgwzpewAt^_||JJ(!Ql1*0Ul_<$Cbt}f4<5Se|{8q9A^K#YV{4}(=y z8$mPGFc*EF1J6n2)KlN)s`<%Xk3iI5d01JJMU6S9i~fntHGfHzV)H@rd&u#X=R|^N zY((SdHP4xOU!rv|VoGSb-z1%?AA#kC9d`<(rvOY5@xsi~pqO4yZ&W!)La$k?VvG%` zgri&hj1|z8@h}wTI@%6dn&%KhgCkI{UaD(d#;nZgpb*f~m5nhK%zo|YfSZvs23F)v z&2L?bt(5q*SFJLsmhetNT|L7Yr&!7b!pzqT;HQWW3Da|k-u;g<&0?Rn*9}D7PBq+a zJLq%bt{Ijy;B12tS1%uh$s=xFMqg|6towMD$}+k1UqsW@NtAXaI+Eq!6<@IASs}h0 zhd^+Fv6FpBa>TB5mn+o`*wYtr_Xy2cy>CsV6J`z07mRDZW}(!jN9NR7&|Gx10xOJ9 zAH1o)4_XPgu4(HNG}*ce@$tmVM;BmbuQwPtuagFmQ*xLW^G5;_KSKiTYr9&A9P&_W z9;&UFDu~+P`7P-~iqIk!O8q&_yA#mFq{MyIA`u>~6xvzXu@cJ8dF;1N{>^R6ZdEy* z%>Kd@5`c!Qr(zg2opyyXW*u+#TnqcyOG_-`h{O%~h%38+(>R zKu4;F7)`-8h!ElOaVj=r9$9WFpit_hdgBrz=>Dwe1goO>V4|+$Y`!XlqgkU{_rLSE zhnr&KKlmOU4IP@jygrZ{depk^7zI9|=A|?N;Y_>TUA{^x@->f&uYg6quea~E%x`Twmj-YRhWeN4T&JFt|xlWB@RSO2H21M z2oh2-e|Vt&IOZ-8PB=f3k!f~E#$aWD*W$~LV^u;z#ppvD>Cf*iW>DR9lAEERC8JToiM0o#AjZen%E=ZMdSSjT=Myg9)Y82L)M@n}0Fa3_q);BtMQp5>9 zh2chi3cUp*9&2zid8z+xW_I6%$t>Q%CCYSf()VU<1e@@agF#7Bwlb5Irx)as{2q`O z{G3Hvx1+b_-qjM?X}l6fdCI9niu&>9ykO zcboH{N3F|`p$T8$RimBS9&JAjKQqg?Tqipz)zDL52Kv}UK%l!Kr`d*y}L z?oX>7))cGHv-=eu^So*rU2@bMGC16rJE6)n5YCzC( zu0|#l;ty4Fczum$pn&|ab>(q%NE(}eP#kF@c(-4oKyrVt?eEe>sDoRHLQ`p=?mT;3{{s)zK$lj#y>i#XtD;@z7u%nrmP&~cy+-) zXSXa;2en|8p4#XECtO|YpLfp+NvN3fxTI;{N4NK;h<7XQFAoS*AtQfoD6B9;FQr`BnPT3BbrR+kvw0a(NWx*tl|! zUYwKQzp>~~|A}~#e%m1?D?gcp*BCPwBhNMtEg`@J$or!dVO2RnG&?MmJtuBNaF4hy zmTn)ih+>*A*eUc)(CUIcQIWhPe@FIIL4qRI9hH{f4oSsSf6g@a)GL3>h&Ib>gE6ge z;2ZulkGAz_7-2RYB&$(3;nN%t>#`mj6vlmq_^XBAqPh%OXV6om^MmA6>ZR>pyuow5 z^r+8_Wu~GDk)`x(^?Lxgj{s9|8%-;H=G+F3)R)wH-GKD1baJ1mtYNd%1eaj_ClRE2>Yy~adV<9=z4vcX-r$8$J4TthuKHnv^oOKKsB|I5;FA69V=g2(Z=<^BRyoR(;Wu{o^8i8K>6I2ZiyN%Eg_nt#Z zb-TW2bLR2zP-b#T+V7t97OW6*&ROvm*PLrYO_B2|Q0jX3>~?;~L*{g8`yg(9$)@Jw zTtwsKWLMg+RJhv;_!O?f{2+B4&Y!MjHYBhDzR;?^k#{QqyZOv*`t#mq6o8i&)Bk_h z*sVnG(9SWS)2*o{cap2~t47;R6u2eJYR?=_zV!65lMtHg9 z+|}tF3BG*o+MW8qUHEUFdd6lk5yQneu**xjRupzWYwdb;?mDT}gLn45Zr_ntM~(jC zDtMNsHFmY;$c1R!O=4t94WrwQ;qGhq>}jv;drtjur~FQpp?}0Pics0b$##s-aVU4Y z%eB~g4YojG(M9MS>@}ZNpU*xFqCYq_0XRf#)pLKtqUg`VZ$l!kk$6SEMjYrl@gCbS zT%UL9(aNfPu=sBD_Smg3{WDb2dge=}#rFf(!y0YO?v0hj(QM`KO7mjSe{@D4*57d)*^#^SEA93 zlRAIXz79AKBH0m25%WJJDgg+1xKP&Dgjx*Bcj^AN{>@rm9bNua2nvBg^-eh5hadUH zp-XJxRTU_k<}0g1W#AxbKnj41b_UUFS#l9?3vizm=TB`VbIR{X{elTg#6=p01FmP8 zj{ED<(whnBCC~Y&c>C@sMV=WD4d6qQ(B$hg06-ZyGY>=rjBYShKAXGB&OQ@#`1XQUW! zN_}9n@uFTH3;)Z5%k%fBMLLowxy_Aj8&FMe$-Cxq`>jv^n4n^{>?v zJIX>0K*dxWxioX>L|AYS!FYF3c$1%Fsd^PyhI%0ks-9Z7%|4Q#K^sGiLb*a6Auh5l z8coVwiZ5$KzOK~qPiI>rlkDbRG_fI5kn|M&C$^#91O9*VyxWY<{lLL2KTB!D&+$S) zkYxZ66sj?B z70Gb_D4p%Ok++4x+Pws*@MhANrO4`uQ{owWB`BWjlW3qzDU;;tVmwXDs1&|8gQ#i6{6xRGUXBq$vF6k_ zx6!?|+HQw{6^xVBbviPLt@S9?gcJ}eOtf#cNf%Hv5>c?@T*%#7W<+Y9*Y*jE@5(= z{ucAQ6?S@xOnhxM^)%+{ad_Kq9|{UB5L(%DN$X%4-Eg{QCK0(;_`>-hkCDCz)4kU? zu4_9ok&xzAdK{z)ckHY8FE~J-5#SaH+t#fFTaGO?7vIxVl4B5#ga+$$c1r)H(Itm@ zS&m2`nS#o;#Pw}z@oAc%1Z&}7IUOJfp|y9$?dk&csY8Q58$6CtGP7l*3e$!HvpTtI zzDCo~#Dc)`s~Pf_W92}!;SD-P>4U0*ajR^v{4S`Cf~2&+ZG%5Wk^C7s$_XmuYsR@3 z@`cF}_j5wq)1Kq&o5DwA2d{rrXlQf45VHHSm@x50#)lYtWss~speup0Bx)OJ^P%Fl ze6;>E87}U504oH3OI_A;cqqnnVwTAjfK68?Mlf3Xts;s;1uWH(ojwiGZQ>(~jh^J# zLeh+t;ipBjR^S)rqxqf}$68B5_L1MFilIA_$MGjk8LgBHb%T1D9hoX970_3+f%Z}F zTayHoP6E5fsv_0ZXJZMm4u$?iGzr*7o)+~SRe2zLHorv~o_?6V(&aI)f%^?NxIYqh zE;p(f{*-DjlON4_D@CS=Ip!Kl9u)S~qJD}8w%I%3;wxE8_5W2``4mX+2d5g2Y#1)J z2wD=AW-|G)U(W`O9sXc=MM$~uWC?8Bw!v4;29a|Q;k|Q{#Wuw#?jf|?$Mrr1W9DF* z%2PPPxssH!O@n1;9?i`)5Ljwl6I0wV)cEPHGYakdN&fU8!-%R)iW#ARM&^( zmaivIPOW64Z3_yJX7m_@AxZ$^K7t;?zt|1Eh$d+~G?9%CHMbF~;Dx(7=X&(S9b6c? zbGFiA{-ASAz9M=AP?lXSM0KTdi0JSmwgoNkQQNjC@8!&>{fsYk$zOWKIS@vw z9$O~zUFu~)5Dh+-Z7hyA1~bNd{qTy-21%_i%^{NJpH3Mh5g}Xdh4)?%)SJSe8qvf> zU-qPwpAsdKo^pq}WuXT8M4XID)T+|L?Lxo7LIVdB$$%q|p_&Ip%abIF%93SXW4PYv zaycLyd>qC=3$Vb#Iv!#UXxAkH@p1=$(I8`8Pt66&2TQEBA}`n8DpG(3qoWahOctHs zS=1%&#FfrW|2GH@mcD~fEqwU?n+1*U3fjk63*hLEX5HHh1g4z$G!!~EPQ9#+aV&iTVJgisRbi#|xi$h_ur zIV}q%veN|X-=7qz&yu>d%3UzvicX>^QR@hS)d!b!{v5o7f5^?7bTQD_KcsKTYKF7m zbtJLfogGPk3VgJ6e!(Dq57cx-Yde#mw6T;(j8&H0>=U8Ydsl%&ex^AVMj&1)_W6oU)v4xPq6{){|>fLEX)D zRHNf7M3m#|0IrQ)?na>E37kBrru^1?SJHxMl~)hRsEz54-k+a(Y4IXE$UlFce2F9ZYHzjke_!gZ=6dumGeM6wVo#u2;!}nO_;%=%YeJ*^ueH}I zrJ0NMG~9M(mLP>BNIO}E?`EAiW%ur&uIv{^zC~|91GoAD$gKUaeY13-#HzJ3x8m`) z>4QM~lPP$sA1(=7KB@8?u9IX|V}*O6_Kwy+nd(_@6&u_M9Tg~|Wz*Do|*R5 z<4(BzquaXKTgdlpnHK=+q!4WLgHV>%o&N=g2W@>5!Hci3{o-3$l_4Vqq!P2sz){0z)4b>e5b^G(Ne?uRkPyWkHUOP8MU~&OiS(BF+7EgR;}8!h1Uw0B5v# zsUn@#$34heNNUJifUZ=u0ey%skGL)CaXQZWrXH@UTt&4tUTZ)KRgRMmB-6R#H^$~dVTu0{7ni7 z*n$*}*N=0OSJQTVk)w$m-!(7+sH&+6TAc~;l`nYYYO z&co@lYd2~#S#lH2xeuTFNI@E6a8hvNGJ|+Ba~A__AuahJqwciEEe1|}imDA7OW)e+ zrY4KzDC!J;1;YZb&!(EPw}*{n9eKCuAPOK{Po-if20h=`sV2`&*{SO=% z?-NEbIED~XPzH%|Kua^GCP19z^2Jnrl+phvHUARSxPCwp{v~I(S zUA3ye`hjBV5#uf6!RDlUie^8mBEQvK&M@5v=m`eRHJ~vl6M^G?Uc$daNc}oe?KN~! zaESC4B6-Y=1|@aaH=Z$#(@k0YZ$x1YZLa{@xL>xj>Rb2GtXsPUj0A+@QY#7W13YHe zD>F37L9-0)(W2k&1TO(FK+nI9c`+DsOICqYMs5Ss-#F4H^+Q&E{FA%(XJ-q@EWZ&EJU9^i$iX$HScy-_7Tm_Gqs&;@iN{RW1*>a~*ksnPAHT z;#uRXkrHMToimFL!zq0dT-U8@RcqZnKSvYG%zK$?UZabEMi|_Gdv(e&}Xvfh%S?;=zE~{N>c{}ev1x-xx z#3STT^-6s3_#W*37qhhsuKXTc1_p#*cf3x%w9I2cN^cRbeWpr*mWZDwwZ2I8QaAb0lJ!&k@NPEQajDi6S!lPSPJU15zcd_O^D^-K2 zLuQGL_|-KB{+zx?g#H1$hT@eND{J}F8@H(DEbQQbf(++uh+Cbne_9ntL#?W8bDx$Rt39A#J^q8yaL_r{dhC z*A}teV-G-78?pDh@qbEp(F0r8F))7+$?#L_fo@`gkj2wV-l5P$%q2!=X zlOqQJIci&K_A}nc?-(-BoqHAz$sbS#kG1($4Ia}gSOy!@mEYMMu5Q5Fe_3-<^V0|^ zVr&+5qdxq-bfftvpsuL!Wf<8ya#P!5;B|DiMq2~-#06_|o&Hv1f(eWI10V{vTe4~? zBmvn$`3Q#|Mm#jIr8LD=-s@i{N;`HUs^>T!V=$iMa*W||*Z9>7B%&?5AdhOtVX}>+ zkyN1u+>ivfpQB3zey1q;P3szlG_oB{k(XMCryAY+;>mKPBMz3VF=BUD+DDS4T~lVq z$*~W@;h0kpJNf!=elLiQ>KvKQ^8t3w*M3up2*)MUaQIE_VN+4$gdn!fQg395(^iRb zQ`=b9V%m3pOQ!ZDFQ51RbrGPV8W2i(%DAMQMY7Ld!qG(wM9Kp8Od3Y6?0$bRCxMwA zMf&Y&;a-CQyIvf%kgK}_&TI*_3clJ4dT!KRv5SI@_*==bF^^w1-oUBYn?01N(HVB8 zo8)A=Tkh^Om$9`GV%E{o%QM2Bh$8=IdBiUA1n@h)mBNNQ$r)G4${1@O`78gLp(OJj zmS$E`NAIubBJP3WmqT2Wde-`~s%tK2_cW+J)#+X^I<0;}x^5Vk#zS#L?|n#5>L^n9 z`Q>2K1&L?~rI8iDV(xIW;lhPPKlxBoPKnL8$r~rZk*^kPWgV3x&wG}MCaOsG(&=uPu<7ti~8t}%BBV!HK7ubFE z$az~Xv%4oI`>&_*ky8fc>baYt?=-V8{`tAte->Jk19AfPo0k;6+1lR@Ss6Noi=Uj= z8xJSatZ*=Yhxj{jkwezGQtV?v?lcIij#+4e4D^|-^PBsCYT--g3M^m(=nu-W6N7lA-Us878kTj<0I}Jk3)t-Rh<%eJ((331 z&)G)YR+JZ^qY-M%tv%-CjQPWDyZ>@;YTPk73#$dmc<^FtI`=}nyG}BWJY~VrsZX5) zRJ>p!jugNZ#lJl@^zF1ac55xzymi?OEhn9vEF{SBi06vy-x4sVRcs@*Z;Jj$+oD=`L zH0pi6qOAh?`tOoW%TguhK|OkSGWx%TIere8)fwTEp2NHQjFBv5twxz~Vw`vUyJ}$v z4H3k)NiFJk6Ag?0r2(hzTXd%)M$iSdDH*|=s8P6usb{J_A+6iPwP>&a_|Y1~DlMIL zBT-Hz3bY@XV!$_l`z?xE z$&<#)cTQHNJE5u$<6m4atnufR5yq=Ao$ilcEw=yP1Bg7zO7S`04RwA62y!$@I5nk4 zP=MRroPTrbpFDQU1Lt|te%PB3-xHrnglyF7oKo?`*EF!h8reALZ!eedKNB6+E;|s- zZdM0RYu0x_F#LVIeTJvIo!k9)KfzR{AVCl~1a2)wgF_;oZvoN5a2L=;s28PDax1}v zSCGC`#o7R|8S0TBg?aMCRmf=4)%4mZ@ONI{gAl*6ZYq66#T~5PfEuD`>I@{Us7FAA zHPhqqCASA`Ie$cVQ~Q-hS~#8MCt3A1MB6fjP@L_=M|7G3~0Bb%8h}eo;l0NiJC-5pf^h z?`C#x6~kg~T83D*lRUad>-H{&@oftNfxeM{cOgxs6}Z5JNKCtH|H~kkVyiWs{Ea~& zJsXlEKdrH9myQ&)oYU8%l?Nyn>Rdy|Ebn;fFemi(>ML zw>Hc~?>7-1`*+fE_n+#1ATf#=^o=iy8Jo>mB4=|JcT(-vk@f^d@YHw9_VMUacPnjj z7UNcF*qRWf06O2A7MCX%^0y<(h4j~xX|F;YU@uT}xOsrQa*nneuW$vtWnHfPm z%W@`Gu`&*MNjzV{It8iqpz_I4jZvq7)<&U&#zo*Tc@9o+FF0ZJ3HOycDwRk-l^sE6JictCWuCgeTBawYV8clyxxx~#e>@nSqVIkj^Eu(k3yn0-^2APSK*)kkc=7L*8w=??7gEW51^e^%LC8h94vvE)7whvl2CGNon7ZY0RjVqqOee#-WG{ zkzCLGG|@N$+>BjE#nliyrselyaz-&vZJ~K3KlhDRDgiw{j2A9brbXK#>onZVcc2c) z(8a2}$)+fuuECSl88gWfR(FIzTJb%2b($+u^PpI%=sWH)W?)Vd&(8NTu!{=RS^dE_ zjuitCD5b|cVgS>O)?BWd=MYP3o5M|{H$sIw@)Jdc8Pkl~By>b!G}fP5h;Pd(-9aS* zceL<^X^PA?b31hcl!5=AmMG$GXLF66{|AYV6#y~nzkRup9VKh~+l$fOR!kj0D-c0* z-7{u6b72I}jbWeu$QdbFHSfikz1rWzN;~6mx zw(po3suzlcK5dT`g7CxlusAB_*b8j+I#Z91XU%VzlDm_ly=~H4yPl|=*1PYpR%80d zqtd35=;M0q^*2~1{!f?hh^@1i3QO=E`Dl&W6^`)h`IL^}y|GDPe0<@*DOgGbrc4c< zGUy#rGX8*SG6NYg4S2I)0{t$nna(j>=s}9vxW+#wfjd!Y_|Yimr_tvZS@3^yXUdj} zuGI^xyJI1XX$0lM7TY_pUIT=N+PbB}*Sa;`f%kvJLQch>Z(FUi{rByzv~`0Ip!Z|u z6qhgZ2Zm{emD6t2H*Sh;?j;9(su)-rCaIio$f(5l3_8w4P&-Vedc%PYO8%Xp=DQj=3hhaLeG)Lx=d} z)rY4z;9kYl!NbNfms{DNpi)H>?Ay3{gMJ|WzWZKm=tzQM0>;mMx71smZRqviI-7$i zU5#8CNf1@-pL-#7K-@5P2EJ*c7#|F*8LsNv|l7dn!owVM|wlB2l@b9(LI z7f+}GA?iKs)h&UHoD?dR$~UIg4?gDk0v_g&Ta4DEWG=(t7&wx{(7xOxM%W|h)J2H} zO1GPDFjJ6>u^rD=<6j1k!SJNfE#<@QN(`(S)e;7oWIm1VEUb;Kh;W)f&nM!~GHFV$ zp)(<4-q2c)%n-=7QxL(YFgcjA&^J1=eSI25V(Ji3AW)iQraGD=LVGJj0@o2})qIgi zHVFq^`A8iusM3()=jAbzV1jL?7H3i_hKbfj^Rw5ooA;HV?0H@|Gdwa^M=b99e*gaa zn;|+SCHIie{bBO>2UM!QFC=bb(s0plEffH0jfu)T{-A8G_|^?D=Ul4zZ~FO>OQS~( zUY9Nrw-6*MI(KJnFN)}D0MBKd(`%5Md{WK~n`u(YW{|J&bs_NK7=WZ7u4!LPW2v;_ zohCC1soCf~omkV_cU9L+#a#UHyz%|Xt^XH)eO$fJhnjhNp&y^--y8l0YNj;)LF8*f z8e`P@@KDEvFU@e>-@q{-jw3M+S&qKB(zldO@wbDn!GG#OGmicJywy~<&vtK2;S{pJ z^FDx}cpjVzg?nTILo#9LAhg@bngue`7$Gm8G_N`@=?n_1b(hdcXO*-ek>c0q+0+?*nLRezucMJKZ_0l47d3Th{FbFb1U}ePP9llBs;B`GN)ic9C7=hNTJ)J7QlD;bCzG+NigBx{zpY9CL&vBOq zZHCf4-bMY&c_nj_J21HPRE_%T!lj~tUE+&YothlNi^QN!6;5bMB7>@W_?-|hFtwzH z8-&jX?=3a5&y5^#)(L06;!x*8HO0QwM>mXK72<3a1gL{j^)j@Ll^F{G zYFfWr@ri9vk**r)IDI#sZ-pmhRm}Q=c#!(_w7T0sPoFxYBAkS}zLXw<4-=@|HEU*$ zqF&ZEugw-%15UjuwR)-TI)E3rXA9Pv)|I9}O|;(Rk-w`sAt0%&hSP|iFN+&9j=1|b zW=n_Yr58ePHXl$s$_5&30(%K3k5bfckR&MVCLV%Gi(V;O7hUy1$pFp9CG4~4`u&wE z?BuWuPbP{3XE_mRrl28)orx;Dyue^2C5$Y2M+$}VOP zefW5NHnw^UDjc)2O-+))RLj5dedGDlPH$Wc&l;bVjorgt>q@YfRp#ALswX{6GN^6J zlTSiXIV*}AMW#_#X{M{{eQoUq2Kb4(j3vE1>=v1`fLf_S@+NGj^x^;~Y7KuQgD>G+&L5?(rRO_Sjr=qnh8 z=Jg4#ypiRrr>5(cdA9;aywp42@8Q!lx##%qKnqy;k!AC`4mqv|tXRC;`%|BNmC*_` zhB=Kxp6HsdR2N6IEyUi51 z-ABvaxAce`8E`ep7{BDNC@-(HF%?TAvpE3JuE>l6g>Mx}Z?r_@+p%-@8uwW-jO>jqCTt4amwD~|XV-fI(XVBG zzLNRIB2p?MTHAL+7qWEmJ%-y~$=?_WW(gu%=l zl=O{4U#?icKN zQ@{;n*{zpnTkqk45;QM8;nF=MH(PDpdSIe30pp@fZjNp>=l0Y*3h;ntZK2_2cJPE+ z$=(?{BX4dgMu(j|SycBKm70n2{7{~<{QEssbRV3eZPN}H-X@#A4x}wrL~a|=j=$^@ zZ0_qth>P)y>n4tUiJy4UsApPVC6>P`PG4!nwEQnynzX}wnq1Y@)+Hq7Q)Zxv=WIJL zVKduGtOoY4=1Lz;^=!=u0b<5{Gl}1Kjjeb78W6dX#im>8PExc+R}P3 zLg&D`30yODZkD-Q0plCg>y_Rxwp*-E~1m-<_waVZt*9vfzj)< zcpCAv87Cts%cKeQym+F`Yq`iTaFr4H{Q)fE*ykUxdEc(G(MTl2V(q6kO-ghFxNG)h z@woA$*i^NPEn9}W1L5|F@|yq9d_8jHyI&`{wOI7F3&o--#gRKi@@1SI##+;fja0Uc!fgZ!|7PN`d%sjw6Scv)bI&GzqR;`9!p!pUMC4#Hn* z2DdKSha`K~@#GxOAtlK*JU*4Wnqi^zfmi1&sl5<`N@)3U&HdsWKQr$NmDy;l{uQ#2 zYu8&mrt?%*%F1eS2S-E+YBfccqfSfUJ?M-M(GAxf#4desIcH>L_?I<*X;$%s zOHYqSaH-SWfk9M0DefwI@;t;Xo|kIn2yyGoltgIBqD2_3x8D&a0Q(Qg7}@M4GWd${ z4**dWW3;D^O4L64a_UShWv6>lO1FW_0}9!6O4C5$MFr6&Xe5BER2JHLbQ!P2V>sE+ z-+@V+J3D7JxsdP#1XHt?mqNN@;GM~aKNe)7rIRUQ=;cX=B5;Z3do>XHaV=63c?QM- zlo7)1Gv6VH#FE?QaQzc5OIBw4MEd%oZN?JLP~p8#D#}1vQ{bv}tWjT)!LYs$Eqre7 zCXJsx)5+L*$95(#PglS5>Fr{FL7;Gx60*9Y;5pJFD_R#yRG4AVjAOSJ+iw({oyhmz zV+(ex;?tlK38Pp1wB?13gbf!fTHo;zDQ!N*#1q(%pYk`=uu2jtzVhVr;rf4@Kf82f zV0o`)FV>F^Yg`ZY3MX$l`<79V3U0)NvtW%zrj%Uyh%|s_(mc_8oRW&mL$|c62WuF0 zKpk}{aXGlV_XgB&CfnJnjt8r{glC*;k1h$%%bvgH~aLbVyik;wsHHE+)n(R&Km?JM3+b3uJpB(b$^4|wLhG)r`K zn$Oh`E8bX|Yc2K}3c2RsH6HT7q^2=YEj?b}H{?g5{LB>6c`L3lX2!t?tt6N#RE+ZE znJlG5n*OK}_2PDCneciYqoF>fq;$)+7F>=PX5!ZgZ^QwVo8jxOpI?JLA=GXb-16ZB zQhe2D3_Y1JXUdW}VNIyJeJPUs>&zb&Xg5pv9P_} zi)18IPGM0TM=BQfEfwj4^2u-Dh%7(wO4utUMMi!UeRwY}@cZ68=p2-i!}h@6T{(~^ zaq*dug?QF;@&kP}svhK;v$KnO9#Ri_zA_=aXU5NwV2G;l$LWF)_5FH7>-awz@CkYq zvKEzuERO7~rGw}sh8dX!7)x?f_^`;<`L6yWHQ|@wbu&0T?*sVQ2FkjO-m9>OTf!&Y z1Ziv*T;lN`W7jjY+;5<>p{=qawe9PqU*-ZL+n^zV_VfX!Szl2T3+f^sUaa!(Rq{6c zzD|Ekhw3|6fw3&)xOF0Q20+!7qKsB@ZP!PZw&BbsE!7{p-&##$WVF+0bskoAs4)Xc znA0P^hK#7(EGAFB;83ee=Bk|WoV-8588q5JU&L}+t~S1}WDK<0>o*DP8CqAtGU7}F z`q=ClIYGnh);^hpQDa1@0AH0K_X#cZL-7W%EV+e0Lg-==HLG!HDRsTQkW=}z>p$%8 zRS=e%*ilsDq?IS)dwplD&HYSTa?AWWh;p0S4)pBsPt7|DD$kI+J+mL&zk?Ix+vS{z*Swu2`JUcE=8 z?{aEtjMCWpE$|K(maF;M!-#$vzvf}yDK~G87o~*L;{_NR^&v|flhPEH{D(|t%HAe% zh^($VF6qtzn8BZsGxPoWjPpg2*(kxp6z-`H;FZ|28(?wH6^vnx#aO-9HZk!ZxT$*xu_-K~VvZQ`U@| zBsIDcWD>EMNhk;H7w)y5K<7>xphn~GJmfD{rgu3|h!Gp{aEYEN2DMf_FF38`>vNwlC zC^tS$eNV}yLv<~|+enQU$T@biIylAu2d*iv)5G#ZSp8oE9#VjYrzvwW=I8k@Tpn<{ z8R9VMec$Pyo%9%@B~!VzHog21#KAZlRoI!t&;0)BvPyF;%L`tb)$2rc$4IMW&200U zO6B*F9=wk_(NnZ#teDc1-yGehVEd|GrY`u*R82Kju7@r9tpaIsog3JOpGPdXzAtPY zKXyC!(!C;5cZm$#A!{{*>YQ|4Xzh~n&s`t9-fb941BT|L)kjpvmX`8t_37{N3b~A} z8|s-_49g9#B?VYZEy@oi%Y%fXq`6CeTkJ-)dl-S&3WW=Q@d)$K_*tJkO-myj({JX* zHwZ%=NXA<|wvSTE3^mv=w7{F2hu9~ja0g&x{TO(n6iO0;RIs$NAUHwbf0K||#azb} z2E>v6mAc1<#S0{+WiK@25|7U_wgP?@3orZ&cM2h5AGwd!707YPO+I69PkE*0!!z~N zdVQFp*LdJjnz zjQzDleLBws+OF`b>d{BOXE2o?^hn1jIT}p%^FatT(fgLNha|&Ni?e`Mg973>5}V6^ zX#aJ-Ph*z;`Gua#^mLRR{^nf9Z52w>uMo4`&54xVR4S22$QlM@>(bxGp1}aib zNQ!LuH|mh=^d-Q=VY_cT?c*Q+P4OF zi8k+`Z-&3VwWt*#Bc)0`ac$h50-M}dQ=|XG>iy$4>6Kp)f%M8k9k!BSshW}{?y+K- z24B(jZ#7xcL3MtKMv9uiNoK#T-)93@^EE*4Z!1>qbsxkZA{?%v#990QVPg3XvI91H zLGXnyLm3}uW}hvDokcCP##S^Er2UREh_pGWJ#yd7L#A}XvCL5e<4B(D@G*u%y@T#? zmh)Q-q#IQ2ZDxLVprE;vrT5gSPq=brLYMWm)Sx!ei*DNy1b35sR2JSt$xT%_*!^V? zWozUI6)~V5b$5Lw7-pi|30T4?%r0%`R)o`(5)UBiU{(E)ejn;4x*4wXA~u_r(V40C z)1b2fqmKwo8^Ra_;JqR+90N~;*Gu8qU4-6R@F+URkw|DrbFhy+=u4RkhFV>Mi0Nf53~5JBz&S4Sp$lsEdQo z9xzlbJ}WQJy3DE8)HvyvyiCotSB-VB`0$087Z87^s=3c(nnzc+9+S!*rwn(M)qFiM z?ye!A2yX$D@H1SdGE8~`A|t(^f3(7g7BL1o6hjO2Qky{Z^ikR!a93dfo9Fr+lm|N^-xdSC(aeS zq)=Q8b_O@3z7P&|8wnXxh)zrH2{X^pcalBe5;$Jbw*jAbzEfZfH*v{aw17}FXuiXd zdTxifnbGUHXl*?Lk!t1q@w>3{ti|Sb_$(z+oon zEeGBdwPc#jZB~4WKWpb!M$1lPfJU&BDW2au&s231w>~}rOuSdsg)Ob;K>mZ3w(fGHh zyN+d0k-df?T#0`NT+bcBF@iWaL~`5RV3cdXjaLU6kfeI+#$y4V-$D`DJ|L?ByEqUi zb8+put{RRl>LNpzPay@%DEUicES(j@=KKHN!{)5o=fS02TYdjo=cPILP#p=dmq3lT zdUA&+a*o*5!tP-XB=-Y?KOor~_y{7t?CR9~9-OS6!#eQYdTvnkm6bg(H@h2vnziKA zw$0PSy=$~+oz5ne<;D?9zm*4mO~pD(GwlKJ6*>TSSx_$g?(IOZvT0)I^ScFr@8snI zit?yLKyBq(i0P6QT;KiuDEKUHkIX5CDxhk;^*A-~E?)C*)<3Z{QgCk2-iBkj78;_y zKCKibCo|MhDGVpLvgFvEp)`+5#rys4f?*?%KhW0ZH#}w1BQeQm6`mI$C-Aitvk5_` zy!hl{@lWdfXu}_WqQAcS5l7~3r?AbX<#pkiLo#u?pP_;cB8Xd7+qNdvX~6Jks!7h} zfv_i4w~m0Vr6MVMJMsA!hV+#iXqA3SyeeUe$h^69F9G2 zc~>K?oX_8?H1}2HOYwq$;N)u?DyP`-#nA2Au#RU4m!Id53pV$xO*(w>r8{F4lYd5* zDK{cZt~0>vT6?_(^5P<8kufTH-d(T_p++_QnfzK1{MN->ZrttzzB8rL*eKr?zM?N@h2op-dL$!OV=Nv*1#*ZZEuo2DJ&u$a{ktbrt(DOm`pDh z#q41&w40wl?}N^4$^lYE(!#kT;(SG2A(H79UnRK-NfpL|QXx-hRTcsYw-oJUB!Ng7 zb!71aXp4G#JkIZ_9+083%KFG)bEY$96Ta13bK+A?+kDn*fIchnHw~ECR%}G=)mxU% zRuN{S;u;c0ZP|}ZThES=6IT{zYD}X68P5nMm2#YkIML!JlYJ3pKgf>*3{i7V-$Ztf z1hR8aWOM)$wbgLA%nHLDU9s2XQe5U2TSyc$V*~exK}UCW9`N=dQGnNLKA9&Thc7 z+z$!kGV)lfkVz?fpvLUMa7=+sL$P?tV=#PJ0MMfr0c>{D>lg1&S;i^*ndu>@J(slJnH#yyd%mBKS9sFM^=}fl7=1@+2}L<^^A3|d-bIH>)IzPQdIoJ z!B=AwI#s|P$1AwWq+mbY%{!Gyt4WkRzAvHnhJjmSB5Rne-!vHmZLF#jrcdqrExJya>}g~BMi z6veJk7<=17{Am$IaK6655SKxLQc(_5@O7^(aarcdENY3{T9!BoL^%d=J&!nZA;9?{ zWyiyX^Bod`{q3Q?smUd$qT6jug_A?y-Xa6pI6L3XUO_mAylS%~o^%fJyVpwW%3NeYsECt0RLKx8>Zo$84yW9m=Saf96e zPNAM5YO@JRpcVF=7bwBYAsAMBHmLe!bV}g%P7a6Tqr0VYERF{`L^>8$u$>Lp5ptRo z2i8dl2lI%+h;x^SCxHbUZH3dv7fsDL_t=pb9Z`AVq#;YlK5|!h0(T2L-tqIc9xPBx zuMRaAG4VVy(h-vRArrCrI}Z=WyMY&0#3lZC%4?>@K{HrjMo;roZJrgWin|OAU&XOk z_v@>pmo{uexN!Uc?QEU!Fxus12{ z`+NauNx*+>tS+D%eKUIW(YLnKU*uz4Z`sbIeT6m!TkXz%Xz4=)!$YI+tTUr``d|+k)Y*;VC=!k(oX=;44u+gE&wMlLO6$mvIGcO1&@S_ z+uhW-=Avt;-s^B-aE`CL{SnTKgHuscu|G1>Th_I4AtVP9-a_l^nBvJb_BlNly3~tn zizf5EcU4xCeAB@1kn>DPX0&ev)GnJ9CRq_fM6))63IL8H9&RmAA26651rl%Yx%(7P z{sOyW6z7%lXdT<7xBY}D{zsBqHY~NAv1)$t53dG>v0{K8P{lMo=k47qD>lV`Wu31q zTyBx^+M-N_t-8^vbk}6yF>PKy?wFyK;8u&K z&{WGcs6J%|NrwW`=&h&!`(d}0YEM%c>u6Ymk`ZKdwBo1{D1^k$mdHnMZdB`lsX52p zt{oX-kQhoI3cuxAqZXM_(iLk`dtB$0Izc2`_&Auo;>E;uVf zntLp9POfKbzx8Op)M2^Gg}VO6>k}W_bPU(@nBrRhxdn9a8+;@^vqQUsY;-@Q)rNm!<-kk@4l@ zk-!5$s@T#6K2Bh$%De{*?6-x5j`%e?IZsev6dD87DJii~a#cmBVxNb#v)q6xXg|Px z5B?yn&wj)EwysQ953`e&rPpy{roO#fE+iG<{Pv(>tp&k7F|G+`A~_$|eaCA4J|G~F zSP8!3{PmM*QAvY%Hv1a1jFJ+FO*`9X8pLukXV+K1X~|SVdeT`pzNhk_o0)lLOO$KDIV_ISHl+(ISw!8XP+Lf_iB?Ian*L^lX|cku>Sx z|L}fDk^jD0KDV;ZLUhYO`QOqa4RUCIo(ld#p1jBkPcnbB_=H9We`y0uXZ^J1m@&Kq zAQ1C3Low(_YGpq_?>O}x%>u=SbE___K36OEKA}0Dj$((Jdg*nR&+i3;A!0UXZ5XFe z5!m(0Ptdddek`eNES(SEEhnYwO(+$3U>3g1IlC$uheO*`!Q?pxWe!&+$-~ktM;%rc zT~2U`0l7!l|8^|RV+|VwzS|O^tEw=iR#cC%Z zlo@?uDi0o}V5T;?Vn)lB=}%~_Z}ZJ2<)>uc2I1fIGMx_r~i7lV4{l7RvIdN?3jMQRTe1p&8Eq97*Obiah$@Wfnr z*kqO;qQoc#+qH1(c@(g1-vi$1E&%8W@b&((>5Z<@G{5sjILZz^*nK+4Na}T|izcgQ^k3G4XjGVRF@EVL5mYydaWE(~6R}bdD(6f$+;% zYM(Oc*yhN^<~A1o1il>2BMsk!O{Y)O=1Z?Nov4kwg`WH*r(-Ba?>}~W=m0FNt8MJ+ z9py{6y|=D{s;(lD>D3XE(8zh&aI7UxXX*871Jcb*o0ubmi{YRrNS6Pl|pz4nOlT%HpQI6Z+T*)I2!LH zh)wHlu$z?SSp4o~w>ZswVm0_Mj>yYp8`b*1%Gb;1c}+E%q9=F|b40)^vJlr~e}N0b zM^&Ab;MJ8Cn2^lD!aBn7`TV917YPI}3Kboar%SaXW=0q1F)8~ARy@J+Y zm$2mnWJ8|y+XL@b2iC_lKpm5C3or_6_24rnMc%3bUDO4Q zlYI9IyI)BveWSNWG}fs+cM7S=d46-_WjDQd9*wFojhJ5lC1{9Qdg8%3S;qC`{1$b& zP?!llE0`XNF45kMJ^Y-2A*i^Lg#%$Y03;#b21*mHW|yitArS9GZUB+BE4`{^`T^zx zd{H#+!OqD^ol603kTNU7Sj5F)l54W?1~8?0{&t%+yaXI%|bk%T({1*!5OI^WAPon@Pu{;d9|8DBy*15~szHZa{}@1n|lL zfGy^78Qczivyj3fjfL!_+d)~;@6 z97Hxva=W^>Wi3i%C-n6I@dTkYTvS7CNHnIaa7bt!0!U8>T8sRD33l}B%(TuUL0H^M zt(1`1yLEd%lvey~H=Sha%0dQ&hGWpeawMCJCGmRAbcMq|Q4? z=;T(!CAS!%)KVQUn8rej0jG6%#> z-KJ=>vj_tY$?DoYVahDdEE_ya-Ax2kpx(R>a4ktGz_DDaf!slHlzbTw(cep9m!~?-22S!Q zHs@}S566?_u-h>DNK5T#734etWTI5+=$|>pD1?zfVq6Cl%n8gS{cISxKiRb=`GEXi%Msn&m&b~G$gyV0-!P-Cu> zaa4}_s{!nrpAyd!54=n-37|kjEwX>@+UtUSM<*7K$cFmB z7Rz5s?;xO3sj3?o9WK4^?g|m@y{$;n&zyidmz0o$uH!=qQ18}9P%eC9ZVdf-*c zn{JU&a~Iu*&U`RxS*4i`16NYpEL(~Cp6|ZgKbcC# zgQ0;)Un|Pyk*>fq^c|D^J)oGG%n9UG;c5Sc(%hXsMFB&$cgigO)LmI&NAtujN(K*h z!_EO}+ed>Ec@v@UTJ=f*mzkW}5eV`rt@Wz%mnm5>uw|aK`lqAIdverz+6)ul!086f zL|m<`>a->p+cNu|gGOkIImBh=MgFDqNl_npRIhK!5JVR+r7j$Pd&5G8{DwGMF{7&W zV{@B3{9^bZi8*K~bJoDh*ue0YQC#KZ@eqzvdcO+PlyPR?T}lAipl^wg;r3fnI89=k z0~$ZQ_LNsSd-zV)hWZNJ`-YB(>-gMC=$z2GXRNn&{>=R+eTMK%a zi1i5N*BkI%=^iS!;0?T#Vxpg+W5!%dXQ9Mt=PpudO3>mMIj3>1GYI;(1u+1!;JS2# zj5HxS^O!(4CaXS{01%7ZnGHLEuZISdx>=qd@8l{6M)v>(-{IDcw?uD^=x8mZbgIPjpq4>KH@fK^UfLlqLWbVNm( z;a=Ix+($rgUG#n8;lfhXg72+e=y)YL)k)PJrr)J+w1*RYn6s6g?})6Z>uXA4o(8aMV$Iiq_@ee?t^uh@+dj|8-C7i4gsx{6D8UI z3%!rxBQBKw`gNJafjyUqu@NZiViAkq=cio!C(c*imZQl0kH~01 zTY+8idEu21-cT7H*3SIH>e~iy7AK*=`1>5}zdPmYcbso~a$`VX(Yrga!DN;u z6AWyuQ;Kj{oo}_kUTW362SUlBpfqdUA7cbr)^Mk z5YIH#@7ar{q)DrD;4-4<@Hl3t11ZLIDk~=oT1>~p%P91&h!FlXMX5b{NmG34aZD0J zTryc_N!iO?WWLBAy+RqbJyGagM^s;9FW8#<+Ldsp5Bc4qISn_RtFmc4U%lKG< zyJ>zkjvi)Xm&4|Bde9VM6Vx(au 0.05) { - m.energy -= 0.05 + if (found && m.energy > 0.041) { + m.energy -= 0.04 //remove the body and spawn a new drone Composite.remove(engine.world, found) body.splice(body.indexOf(found), 1) @@ -3552,8 +3552,8 @@ const b = { const distB = Vector.magnitude(Vector.sub(this.position, b.position)) return distA < distB ? a : b }) - if (found && m.energy > 0.05) { - m.energy -= 0.1 + if (found && m.energy > 0.091) { + m.energy -= 0.09 //remove the body and spawn a new drone Composite.remove(engine.world, found) body.splice(body.indexOf(found), 1) diff --git a/js/engine.js b/js/engine.js index f7c6865..fb7c481 100644 --- a/js/engine.js +++ b/js/engine.js @@ -174,15 +174,8 @@ function collisionChecks(event) { if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles //extra kick between player and mob //this section would be better with forces but they don't work... let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); - Matter.Body.setVelocity(player, { - x: player.velocity.x + 8 * Math.cos(angle), - y: player.velocity.y + 8 * Math.sin(angle) - }); - Matter.Body.setVelocity(mob[k], { - x: mob[k].velocity.x - 8 * Math.cos(angle), - y: mob[k].velocity.y - 8 * Math.sin(angle) - }); - + Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) }); + Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) }); if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) { m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage @@ -250,7 +243,7 @@ function collisionChecks(event) { if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { options = ["coupling", "boost", "heal", "research"] if (!tech.isEnergyNoAmmo) options.push("ammo") powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]); diff --git a/js/level.js b/js/level.js index fa739a5..51e091b 100644 --- a/js/level.js +++ b/js/level.js @@ -44,10 +44,9 @@ const level = { // requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); // for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization") // tech.giveTech("Newtons 2nd law") - // for (let i = 0; i < 1; ++i) tech.giveTech("lens") // for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide") - // for (let i = 0; i < 1; ++i) tech.giveTech("nitinol") - // for (let i = 0; i < 1; ++i) tech.giveTech("reaction mass") + // for (let i = 0; i < 1; ++i) tech.giveTech("working mass") + // for (let i = 0; i < 1; ++i) tech.giveTech("buckling") // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") }); // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") @@ -57,11 +56,11 @@ const level = { // for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing - // level.yingYang(); + // level.testing(); - // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) + // for (let i = 0; i < 1; ++i) spawn.snakeSpitBoss(1400, -500) // Matter.Body.setPosition(player, { x: -200, y: -3330 }); - // for (let i = 0; i < 4; ++i) spawn.ghoster(1300, -500 + 100 * Math.random()) + // for (let i = 0; i < 4; ++i) spawn.sucker(1300, -500 + 100 * Math.random()) // spawn.hopper(1900, -500) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) @@ -4235,7 +4234,6 @@ const level = { powerUps.addResearchToLevel() //needs to run after mobs are spawned }, towers() { - // simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // simulation.isHorizontalFlipped = true level.announceMobTypes() const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false @@ -4448,6 +4446,12 @@ const level = { spawn.bodyRect(8975, -1575, 50, 50, 0.2); spawn.bodyRect(5725, -1700, 125, 175, 0.2); spawn.bodyRect(6850, -1725, 150, 200, 0.2); + spawn.bodyRect(500, -400, 100, 50, 0.3); + spawn.bodyRect(6025, 1050, 100, 50, 0.2); + spawn.bodyRect(6000, -800, 75, 200, 0.2); + spawn.bodyRect(6775, -75, 125, 75, 0.5); + spawn.bodyRect(7200, 1300, 50, 200, 0.5); + //mobs spawn.randomMob(5700, -75, 0); diff --git a/js/player.js b/js/player.js index 5cfaed3..6e83d3a 100644 --- a/js/player.js +++ b/js/player.js @@ -240,11 +240,7 @@ const m = { jump() { m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass //apply a fraction of the jump force to the body the player is jumping off of - Matter.Body.applyForce(m.standingOn, m.pos, { - x: 0, - y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) - }); - + Matter.Body.applyForce(m.standingOn, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); player.force.y = -m.jumpForce; //player jump force Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps x: player.velocity.x, @@ -473,13 +469,10 @@ const m = { m.displayHealth(); document.getElementById("text-log").style.display = "none" document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas - // build.shareURL(false) setTimeout(function () { Composite.clear(engine.world); Engine.clear(engine); simulation.splashReturn(); - //if you die after clearing fewer than 4 levels the difficulty settings automatically opens - if ((level.levelsCleared < 4 || level.levelsCleared > 12) && !simulation.isTraining && !simulation.isCheating) document.getElementById("constraint-details").open = true; }, 5000); } }, @@ -3488,11 +3481,11 @@ const m = { }, { name: "molecular assembler", - description: `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second`, + description: `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second`, setDescription() { - return `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second` + return `excess energy used to print ${simulation.molecularMode === 0 ? "spores" : simulation.molecularMode === 1 ? "missiles" : simulation.molecularMode === 2 ? "ice IX" : "drones"}
use energy to deflect mobs
12 energy per second` }, - doubleJumpPhase: 0, + blockJumpPhase: 0, effect: () => { m.fieldMeterColor = "#ff0" m.eyeFillColor = m.fieldMeterColor @@ -3604,20 +3597,106 @@ const m = { } m.drawRegenEnergy() - if (tech.isDoubleJump) { - - - // if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump() - - if (this.doubleJumpPhase === 0 && input.up) { //1st jump - - } else if (this.doubleJumpPhase === 0 && input.up) { - - } else { //reset + if (tech.isBlockJump) { + if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block + if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall + this.blockJumpPhase = 1 + } else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump + this.blockJumpPhase = 2 + } else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump + this.blockJumpPhase = 3 + //make a block + const radius = 25 + Math.floor(15 * Math.random()) + body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 65 + radius, 4, radius, { + friction: 0.05, + frictionAir: 0.001, + collisionFilter: { + category: cat.body, + mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + }, + classType: "body", + }); + const block = body[body.length - 1] + //mess with the block shape (this code is horrible) + Composite.add(engine.world, block); //add to world + const r1 = radius * (1 + 0.4 * Math.random()) + const r2 = radius * (1 + 0.4 * Math.random()) + let angle = 0 + const vertices = [] + for (let i = 0, len = block.vertices.length; i < len; i++) { + angle += 2 * Math.PI / len + vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) }) + } + Matter.Body.setVertices(block, vertices) + Matter.Body.setAngle(block, Math.PI / 4) + Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 }); + Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + if (tech.isBlockRestitution) { + block.restitution = 0.999 //extra bouncy + block.friction = block.frictionStatic = block.frictionAir = 0.001 + } + if (tech.isAddBlockMass) { + const expand = function (that, massLimit) { + if (that.mass < massLimit) { + const scale = 1.04; + Matter.Body.scale(that, scale, scale); + setTimeout(expand, 20, that, massLimit); + } + }; + expand(block, Math.min(20, block.mass * 3)) + } + //jump + m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + let horizontalVelocity = 8 * (- input.left + input.right) + Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y }); + player.force.y = -m.jumpForce; //player jump force + } else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) { + //reset + this.blockJumpPhase = 0 //reset } - } + + + // if (tech.isBlockJump) { + // //make sure only 1 ephemera is running + // simulation.ephemera.push({ + // name: "2 jump", + // mode: 0, + // do() { + // // console.log('hi') + // if (m.buttonCD_jump + 20 < m.cycle && m.onGround) simulation.removeEphemera(this.name) + // if (this.mode === 0) { + // if (!input.up) this.mode = 1 + // } else if (this.mode === 1) { + // if (input.up && m.buttonCD_jump + 20 < m.cycle) { + // simulation.removeEphemera(this.name) + // //make a block + // body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 80, 4, 30 + Math.floor(10 * Math.random()), { + // friction: 0.05, + // frictionAir: 0.001, + // collisionFilter: { + // category: cat.body, + // mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + // }, + // classType: "body", + // // isPrinted: true, + // }); + // const who = body[body.length - 1] + // Composite.add(engine.world, who); //add to world + // Matter.Body.setVelocity(who, { x: player.velocity.x * 0.5, y: +30 }); + // Matter.Body.applyForce(who, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + + // //jump again + // m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + // player.force.y = -m.jumpForce; //player jump force + // Matter.Body.setVelocity(player, { x: player.velocity.x, y: -7.5 + 0.25 * player.velocity.y }); + // } + // } + // }, + // }) + + // } } } }, @@ -4663,6 +4742,66 @@ const m = { m.fieldRadius = 0 } m.drawRegenEnergy("rgba(0,0,0,0.2)") + + if (tech.isBlockJump) { + if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block + if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall + this.blockJumpPhase = 1 + } else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump + this.blockJumpPhase = 2 + } else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump + this.blockJumpPhase = 3 + + //make a block + const radius = 25 + Math.floor(15 * Math.random()) + body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 60 + radius, 4, radius, { + friction: 0.05, + frictionAir: 0.001, + collisionFilter: { + category: cat.body, + mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + }, + classType: "body", + }); + const block = body[body.length - 1] + //mess with the block shape (this code is horrible) + Composite.add(engine.world, block); //add to world + const r1 = radius * (1 + 0.4 * Math.random()) + const r2 = radius * (1 + 0.4 * Math.random()) + let angle = 0 + const vertices = [] + for (let i = 0, len = block.vertices.length; i < len; i++) { + angle += 2 * Math.PI / len + vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) }) + } + Matter.Body.setVertices(block, vertices) + Matter.Body.setAngle(block, Math.PI / 4) + Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 }); + Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) }); + if (tech.isBlockRestitution) { + block.restitution = 0.999 //extra bouncy + block.friction = block.frictionStatic = block.frictionAir = 0.001 + } + if (tech.isAddBlockMass) { + const expand = function (that, massLimit) { + if (that.mass < massLimit) { + const scale = 1.04; + Matter.Body.scale(that, scale, scale); + setTimeout(expand, 20, that, massLimit); + } + }; + expand(block, Math.min(20, block.mass * 3)) + } + //jump + m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass + let horizontalVelocity = 8 * (- input.left + input.right) + Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y }); + player.force.y = -m.jumpForce; //player jump force + } else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) { + //reset + this.blockJumpPhase = 0 //reset + } + } } } }, @@ -5619,7 +5758,7 @@ const m = { let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2 : 1); if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); - if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { + if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { type = "heal" diff --git a/js/powerup.js b/js/powerup.js index a6414da..d96f70e 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -1437,11 +1437,10 @@ const powerUps = { }, }, spawnDelay(type, count, delay = 2) { - const lastHarmCycle = m.lastHarmCycle //stop releasing power ups if you take damage count *= delay let cycle = () => { if (count > 0) { - if (m.alive && lastHarmCycle === m.lastHarmCycle) requestAnimationFrame(cycle); + if (m.alive) requestAnimationFrame(cycle); if (!simulation.paused && !simulation.isChoosing && powerUp.length < 300) { //&& !(simulation.cycle % 2) count-- if (!(count % delay)) { @@ -1622,7 +1621,7 @@ const powerUps = { for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); - powerUp[powerUp.length - 1].isDuplicated = true + // powerUp[powerUp.length - 1].isDuplicated = true } // remove a random tech from the list of tech you have tech.tech[choose].remove(); diff --git a/js/simulation.js b/js/simulation.js index 61aeffc..0ae161f 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -814,7 +814,6 @@ const simulation = { simulation.isChoosing = false; b.setFireMethod() b.setFireCD(); - // simulation.updateTechHUD(); for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero @@ -827,17 +826,12 @@ const simulation = { powerUps.boost.endCycle = 0 powerUps.isFieldSpawned = false m.setFillColors(); - // m.maxHealth = 1 - // m.maxEnergy = 1 - // m.energy = 1 input.isPauseKeyReady = true simulation.wipe = function () { //set wipe to normal ctx.clearRect(0, 0, canvas.width, canvas.height); } m.hole.isOn = false simulation.paused = false; - // simulation.cycle = 0 - // m.cycle = 0 engine.timing.timeScale = 1; simulation.fpsCap = simulation.fpsCapDefault; simulation.isAutoZoom = true; @@ -853,18 +847,11 @@ const simulation = { document.getElementById("text-log").style.display = "none" document.getElementById("fade-out").style.opacity = 0; document.title = "n-gon"; - // simulation.makeTextLog(`input.key.up: ["${input.key.up}", "ArrowUp"]`); - // simulation.makeTextLog(`input.key.left: ["${input.key.left}", "ArrowLeft"]`); - // simulation.makeTextLog(`input.key.down: ["${input.key.down}", "ArrowDown"]`); - // simulation.makeTextLog(`input.key.right: ["${input.key.right}", "ArrowRight"]`); simulation.makeTextLog(`Math.seed = ${Math.initialSeed}`); simulation.makeTextLog(`const engine = Engine.create(); //simulation begin`); simulation.makeTextLog(`engine.timing.timeScale = 1`); - // simulation.makeTextLog(`input.key.field: ["${input.key.field}", "MouseRight"]`); - - // document.getElementById("health").style.display = "inline" - // document.getElementById("health-bg").style.display = "inline" m.alive = true; + m.definePlayerMass(); m.onGround = false m.lastOnGroundCycle = 0 m.health = 0; @@ -874,23 +861,10 @@ const simulation = { //set to default field tech.healMaxEnergyBonus = 0 - // m.setMaxEnergy(); m.energy = 0 m.immuneCycle = 0; - // simulation.makeTextLog(`${simulation.SVGrightMouse} ${m.fieldUpgrades[m.fieldMode].name}

${m.fieldUpgrades[m.fieldMode].description}`, 600); - // simulation.makeTextLog(` - // input.key.up = ["${input.key.up}", "ArrowUp"] - //
input.key.left = ["${input.key.left}", "ArrowLeft"] - //
input.key.down = ["${input.key.down}", "ArrowDown"] - //
input.key.right = ["${input.key.right}", "ArrowRight"] - //
- //
m.fieldMode = "${m.fieldUpgrades[m.fieldMode].name}" - //
input.key.field = ["${input.key.field}", "right mouse"] - //
m.field.description = "${m.fieldUpgrades[m.fieldMode].description}" - // `, 800); m.coupling = 0 m.setField(0) //this calls m.couplingChange(), which sets max health and max energy - // m.energy = 0; //exit testing if (simulation.testing) { simulation.testing = false; diff --git a/js/spawn.js b/js/spawn.js index 1e3c9ac..5759357 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1427,7 +1427,7 @@ const spawn = { me.seePlayerFreq = Math.floor(11 + 7 * Math.random()) me.seeAtDistance2 = 1400000; me.cellMassMax = 70 - me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map + me.collisionFilter.mask = cat.player | cat.bullet | cat.body// | cat.map Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001 me.damageReduction = 0.17 @@ -1755,7 +1755,7 @@ const spawn = { me.seeAtDistance2 = 1000000; me.accelMag = 0.0002 + 0.0004 * simulation.accelScale; Matter.Body.setDensity(me, 0.0003); //normal is 0.001 - me.collisionFilter.mask = cat.bullet | cat.player //| cat.body + me.collisionFilter.mask = cat.bullet | cat.player | cat.body me.memory = Infinity; me.seePlayerFreq = 30 me.lockedOn = null; @@ -2314,7 +2314,7 @@ const spawn = { me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon me.accelMag = 0.00012 * simulation.accelScale; me.frictionAir = 0.025; - me.collisionFilter.mask = cat.player | cat.bullet //| cat.body + me.collisionFilter.mask = cat.player | cat.bullet | cat.body me.memory = Infinity; Matter.Body.setDensity(me, 0.015); //extra dense //normal is 0.001 //makes effective life much larger me.do = function () { @@ -4263,7 +4263,7 @@ const spawn = { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger - me.damageReduction = 0.25 + me.damageReduction = 0.33 me.startingDamageReduction = me.damageReduction me.isInvulnerable = false me.nextHealthThreshold = 0.75 @@ -4279,7 +4279,7 @@ const spawn = { } }; me.lasers = [] //keeps track of static laser beams - me.laserLimit = 2 + (simulation.difficultyMode < 3 ? 1 : 2) + me.laserLimit = 2 + (simulation.difficultyMode > 2) + (simulation.difficultyMode > 4) me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) me.cycle = 0 me.laserDelay = 210 @@ -5910,7 +5910,7 @@ const spawn = { me.alpha = 1; //used in drawGhost me.isNotCloaked = false; //used in drawGhost me.isBadTarget = true; - me.collisionFilter.mask = cat.bullet //| cat.body + me.collisionFilter.mask = cat.bullet | cat.body me.showHealthBar = false; me.memory = 900; me.delay = 60 @@ -5961,7 +5961,7 @@ const spawn = { if (!this.isNotCloaked) { this.isNotCloaked = true; this.isBadTarget = false; - this.collisionFilter.mask = cat.player | cat.bullet + this.collisionFilter.mask = cat.player | cat.bullet | cat.body } } //draw body @@ -5976,7 +5976,7 @@ const spawn = { } else if (this.isNotCloaked) { this.isNotCloaked = false; this.isBadTarget = true; - this.collisionFilter.mask = cat.bullet; //can't touch player or walls + this.collisionFilter.mask = cat.bullet | cat.body; //can't touch player or walls } }; }, @@ -7392,7 +7392,7 @@ const spawn = { snakeBody(x, y, radius = 10) { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); let me = mob[mob.length - 1]; - me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body + me.collisionFilter.mask = cat.bullet | cat.player | cat.body //| cat.mob me.damageReduction = 0.028 Matter.Body.setDensity(me, 0.0001); //normal is 0.001 diff --git a/js/tech.js b/js/tech.js index e956a7b..e5014ea 100644 --- a/js/tech.js +++ b/js/tech.js @@ -108,20 +108,8 @@ const tech = { if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0 } }, - giveRandomJUNK() { - const list = [] - for (let i = 0; i < tech.tech.length; i++) { - if (tech.tech[i].isJunk) list.push(tech.tech[i].name) - } - let name = list[Math.floor(Math.random() * list.length)] - simulation.makeTextLog(`tech.giveTech("${name}")`); - tech.giveTech(name) - }, + giveTech(index = 'random') { - // if (Math.random() < tech.junkChance) { - // tech.giveRandomJUNK(); - // return - // } if (index === 'random') { let options = []; for (let i = 0; i < tech.tech.length; i++) { @@ -2342,7 +2330,7 @@ const tech = { { name: "buckling", descriptionFunction() { - return `if a block you threw kills a mob
spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` + return `if a block kills a mob there's a 50% chance
to spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` }, maxCount: 1, count: 0, @@ -4291,7 +4279,7 @@ const tech = { remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage - powerUps.spawnDelay("research", 15) + requestAnimationFrame(() => { powerUps.spawnDelay("research", 15) }); this.frequency = 0 } } @@ -4349,16 +4337,16 @@ const tech = { remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage - powerUps.spawnDelay("ammo", this.ammo) this.frequency = 0 + requestAnimationFrame(() => { powerUps.spawnDelay("ammo", this.ammo) }); } } }, { name: "deprecated", - scale: 0.05, + scale: 0.07, descriptionFunction() { - return `after removing this gain
1.05x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` + return `after removing this gain
${1 + this.scale}x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -6453,7 +6441,7 @@ const tech = { }, { name: "von Neumann probe", //"drone repair", - description: "after a drone expires it will use -5 energy
and a nearby block to replicate itself", + description: "after a drone expires it will use -4 energy
and a nearby block to replicate itself", // description: "broken drones repair if the drone gun is active
repairing has a 25% chance to use 1 drone", isGunTech: true, maxCount: 1, @@ -6461,7 +6449,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("drones") + return tech.haveGunCheck("drones") || (m.fieldMode === 4 && simulation.molecularMode === 3) }, requires: "drones", effect() { @@ -7862,8 +7850,7 @@ const tech = { // }, { name: "additive manufacturing", - description: "hold crouch and use your field to print a block
with 1.8x density, damage, and launch speed", - // description: "simultaneously fire and activate your field to make
molecular assembler print a throwable block
+80% block throwing speed", + description: "hold crouch and use your field to print a block
with 1.8x density, damage, and launch speed", isFieldTech: true, maxCount: 1, count: 0, @@ -7881,6 +7868,29 @@ const tech = { tech.isPrinter = false; } }, + { + name: "working mass", + // description: "molecular assembler prints one block
to jump off while midair", + descriptionFunction() { + const fieldName = m.fieldMode === 8 ? "pilot wave" : "molecular assembler" + return `${fieldName} prints a block
to jump off while midair a second time` + }, + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (m.fieldMode === 4 || m.fieldMode === 8) + }, + requires: "molecular assembler, pilot wave", + effect() { + tech.isBlockJump = true + }, + remove() { + tech.isBlockJump = false + } + }, { name: "pair production", description: "after picking up a power up
+200 energy", @@ -7901,26 +7911,6 @@ const tech = { tech.isMassEnergy = false; } }, - // { - // name: "working mass", - // // description: "after jumping jump again in midair
double jumping requires 50% of current energy
double jumping boosts speed", - // description: "", - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 2, - // frequencyDefault: 2, - // allowed() { - // return m.fieldMode === 4 - // }, - // requires: "molecular assembler", - // effect() { - // tech.isDoubleJump = true - // }, - // remove() { - // tech.isDoubleJump = false - // } - // }, { name: "electric generator", description: "after deflecting mobs
molecular assembler generates +50 energy", @@ -8195,7 +8185,7 @@ const tech = { }, { name: "Lorentz transformation", - description: `use ${powerUps.orb.research(3)}
1.5x movement, jumping, and fire rate`, + description: `use ${powerUps.orb.research(3)}
1.5x movement, jumping, and fire rate`, isFieldTech: true, maxCount: 1, count: 0, @@ -9271,9 +9261,15 @@ const tech = { allowed: () => true, requires: "", effect() { - tech.giveRandomJUNK() - tech.giveRandomJUNK() - tech.giveRandomJUNK() + for (let i = 0; i < 3; i++) { + const list = [] + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].isJunk) list.push(tech.tech[i].name) + } + let name = list[Math.floor(Math.random() * list.length)] + simulation.makeTextLog(`tech.giveTech("${name}")`); + tech.giveTech(name) + } }, remove() { } }, @@ -11848,5 +11844,5 @@ const tech = { interestRate: null, isImmunityDamage: null, isMobDeathImmunity: null, - isDoubleJump: null, + isBlockJump: null, } \ No newline at end of file diff --git a/style.css b/style.css index 1146a25..7855b46 100644 --- a/style.css +++ b/style.css @@ -935,6 +935,11 @@ summary { text-shadow: 1px 0px 2px #234; } +.color-print { + color: #567; + font-family: 'Courier New', Courier, monospace; +} + .color-defense { background-color: hsla(227, 9%, 71%, 0.279); padding: 2px; diff --git a/todo.txt b/todo.txt index f4bd356..74d161d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,17 @@ ******************************************************** NEXT PATCH ************************************************** -you can now jump off mobs while invulnerable - includes time dilated -pause display text updated with details menus -difficulty parameters - 0.82->0.84x damage done per level - 1.25->1.23x damage taken per level -tungsten carbide 300->400 health, but 0.08->0.02 seconds of coyote time and longer crouch time -nitinol 0.08->0.17 seconds of coyote time and much less crouching on hard landings, but 0.8->1 damage taken -mass-energy equivalence no longer costs 2 research -long power up spawns, like from interest or supply chain: - will pause new spawns until total power ups are below 300 to reduce lag - stop spawning if you take damage +tech: working mass - in midair molecular assembler or pilot wave prints a block to jump off -bug fixes +buckling: 100%->50% chance to spawn a power up from any block that kills a mob + no longer requires the block to be thrown +mobs: powerUpBoss, snakeBoss tails, cellBoss, ghoster, sucker - all collide with blocks now +added a few more blocks to towers level +deprecated: 1.05->1.07 damage per removed tech +laserLayerBoss has 33% less health and has fewer lasers at higher difficulties + +bugfix + disabled spawnDelay stopping on damage because it had too many negative tech interactions + metastability + paradigm shift no longer makes all ejected tech explode ******************************************************* DESIGN ****************************************************** @@ -36,22 +34,33 @@ list of powerful synergies duplication 100% interest + coupling, research + (peer review? or Bayesian statistics) electronegativity and high energy? - electronegativity + anyon + duplication + Maxwells demon + interest + electronegativity + anyon + duplication + Maxwells demon + interest + pair production chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level *********************************************************** TODO ***************************************************** -tech: working mass - double jump - cost flat energy not a % - field Tech for molecular assembler and print and throw a block down on 2nd jump - remove block after time or keep it around? - credit to TNTiger17 (although I'm not looking for more code contributions) +make player mass an adjustable var in the skin + does this mess with jump height or air control? +increase mass and movement speed at the same time + increase jump differently because it scales extra with mass + m.defaultMass = 4.5 + m.definePlayerMass() + possible player.mass bad interactions + grapple + +JUNK tech - player takes damage from block collisions + is this gonna contribute to lag? + +player damage seems low +player damage taken seems fine, or maybe increase difficulty rework: explicit changes to the game to increase difficulty UI - add a wire attached to difficulty power up like the one attached to player, but thinner +laser: slow light is the least fun laser tech, make it more fun + tokamak synergy tech tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?) tech: inertial confinement - while charging tokamak you can fly, and invulnerable @@ -823,11 +832,6 @@ intro map: diegeticly draw a mouse with field highlighted also indicate space? dynamically adjust drawing after picking up a gun -increase mass and movement speed at the same time - increase jump differently because it scales extra with mass - m.defaultMass = 4.5 - m.definePlayerMass() - give history boss legs? field tech - disable blocking, but does high damage to mobs inside field