From f837136e8ab741d26100c2f1e98bacc5af5bf942 Mon Sep 17 00:00:00 2001 From: neki-dev Date: Sat, 4 Nov 2023 22:57:43 +0300 Subject: [PATCH] Minor fixes --- src/assets/audio/building/electro.mp3 | Bin 0 -> 25121 bytes src/game/scenes/world/builder.ts | 21 ++++--- .../world/entities/building/building.ts | 15 +++-- .../entities/building/variants/electro.ts | 18 ++++-- .../entities/building/variants/generator.ts | 13 +++-- .../entities/building/variants/tower/tower.ts | 9 ++- src/game/scenes/world/entities/npc/npc.ts | 23 +++++--- .../world/entities/npc/variants/assistant.ts | 15 +++-- .../entities/npc/variants/enemy/enemy.ts | 17 ++++-- .../npc/variants/enemy/variants/berserk.ts | 8 ++- .../npc/variants/enemy/variants/ghost.ts | 9 +++ .../npc/variants/enemy/variants/telepath.ts | 17 +++++- src/game/scenes/world/entities/player.ts | 21 ++++--- .../scenes/world/entities/shot/ball/ball.ts | 10 ++++ src/game/scenes/world/entities/shot/lazer.ts | 2 +- src/game/scenes/world/entities/sprite.ts | 18 ++++-- src/game/scenes/world/wave.ts | 55 ++++++++++++------ src/types/world/entities/building.ts | 1 + 18 files changed, 190 insertions(+), 82 deletions(-) create mode 100644 src/assets/audio/building/electro.mp3 diff --git a/src/assets/audio/building/electro.mp3 b/src/assets/audio/building/electro.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..93bb9c4e5a79ae050d4cfab4ac28d6c4867abaf5 GIT binary patch literal 25121 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

7vI6af$-UpT{J~wAE2!IS`c;J% zKUp9jolp8Va&uvKX#r|-hVQlhOjud!kGR0w57B>AZm^0EgArBTgJoJv6}}gqDP{Z% z<|sK_3_~?nbZ!WTTmvpVm>%Cwo8Y_cUJj_~A}n=c)V6F>Gs@;vq0piHd7i_OY6f+{ z37f-1_={jYm2dt+CariyyCEkFo|mr#m$4WP$cw??&`))V;XU=D(UwB3&)76(D57g=Ja2U$?r5h}4!2qrKJkL6YN>jRo8Uz0eH$k&D7(5t_J zn$a-^OE{)lWO{!&0?7kIlAF4nnWzfQ>9r%#ienYLy^fU8SQTSfBNLP)a%g(s8Re^q z*?@fk4%sS@$)PH3MYi_*=VJWmhP`&KJ{}B8VG=Q1t+FW!MD_7r?Z(7W#DE$nXU^p>RB`rrmxT zo*51lMMj=IYEAN=;%(UB33zpN$&D*o9jXjpB?@>%RMbfi!dFZ{e4k(E_Qb3RcmY~* z)xC&(W0x2sA83!`3v`!50z;6EtP|2ly){FSt!(Hl(}?MqdU!u82lwbAEuIaZ_oP#@ z&6HDTWU>((nN+oDq6#TpX-XG3H%W#1rz))3W+XW+MsRn+s6u53Y!W_}3?B=z?pF^V zNog?R$mIudCbE}!k!z!9#=I1rOm5Bh#*a;iUx*(J3YO$fhQ(_S9#W&2&U(*ZxlX^{ z(XQYXz*o+)GB^X{b>YjfMY4U>XR2q5Dcr$HH7bTviGxc=wV^Mh0MNi&K(ki$2!ekj zR}*z79H81K{10-hq(^M=mJi*32Ua@x$iyBfs^dluZFx8?fP(bcRCC8O%7DT3bv5BA ztihoBh+h??Wm<^MoQNQ3agw!W9L}#tVT}0J4G^C>%vQ6TRj?hViixH(E zZdx>@@Tzi)lZ~%zzHyJdAX4?hY5s)9*`%4aX2|X?o#pvaaWa>6v>m^OZ!INP1ixHV z|CLj&s*wB_MS9FS4`QEY|Bn)OQ{FXP)r!kk86jSnNlmqarj>DxA6w++O_9E2q?dR$ zwF!`0&mYa!E&G@mw+1`}h<&U%HJP7ZH1!YQI@ORK5j2g$uc>nWcAz-jo?+ms;Wlt@ z)P!kPt1l|J&OTA9IJsuYWR&=#6O={4}=VvR~jJYrR5 z-mZ*wVDK(fJjs%I8g#`R&VH$UeTGZk-Agh_rvoV*M~o@Uil_l4?}6bA=l3)T;|*UB zT(pG)*a(G5jVy5dEf^zYB0?~bM$yCTkgQSLlYulL>4ZDFdiIPXdJ1Ih@N6uzbzpc5 zc0*nI7h$~|hG>S!1Q3KJEIueZjt9;RKScO&1>eBN!K&Pd{$_!!UEii+$?p8@C?nqKrW_>z;Fj&p4T+Pi>>MPiFW4~=XGIJmc{Eb`!!fmmiYLVeT zxg4{?HY>*VKND7$r|d_*ObyKN(Z8Np5p02iu%qxzatXl{01ir&Lcf=RbIE}!?!5W| zw&REs!n7Mne9YkI+zN%0^nDWAuuK#p8-h9#0xte~ggJ&5+6YV6BX2l(+hLQ6zjkb* zfn{i4OrP3uSQ`qYFZPemuw{o(= zQeALFB366_pLP!)lcpG9=?qo1V(hKVCa;nL+g!heyH#-9>y&mi$6n~Kyb?1s6 z^jwG|`Bx=iYF`Ag>qV_Ln*>qItr)BHnFcmLG@F}Ygi0F$@f7yco@Q0LIO3S{R#n8* zWEeOy;^cWT<>C{F`er7I>@O{r1>;lfpIozP6>6>qgeX9ndkbVDzbJD+My{5L zjN(bKG90qp7JpY)(N>3v$VRA3_6(JN6*5xKjw5;$g{~Z| zJ|AVsmMqc|OBxGw@C~d8X$5>}b?~(^vjKWEM#do((oM^pd^XVMZSYo6dzH<_GKhL^ ziqwQ*m3k70wvD`Nlumr1s5>W*e%P0qdAdfR9Zmbpotl36UUFe{!0(rL5PMqeT+p-+ z@|bbmtuuX??X&lke@Q0LyWbo5%AcCKlTRl6MlKlP_9;M>{y)gE^c*pPZGZf&asu|w zk_)ltUxTt^FJsE?g~)Pqn5U=?hP)R~Zm3RGm+av`ZycZqVitVcU#Y)sa3NRhX@u=} zYo8wpN(uU1XH)OACFujC0o2>NG@J}t0^5FZ?7pf95Z`N6h-;+z&zQ` z#S<~I_XWFTYg>|f#r_vH!b-PGP1qR}#;!^=MNr*0qHX zatkMM#vO%G!B?lxq&5-7&2lh?u|o@IZs6-D6|Kc&O_JliiaQDwkV^P-sf}Z277&wR z1tv)+I4mr}5VBy<*f#ryfrJo` zD9UJVE1A+hK;(z??Nm*EtT)|fw&ZV3iIY98j=O?6p89nPSO|@=6>N3&8Lgk!Sp+O& z%ez-)D;4DRQ1L1VtLktQMc{}y&_G?$)=cWVyeVa2bSW&cHX~$hHX{sGNsroye92HJ zn}BGnn2Kgwb#i-L5hp6en_oU2k*js<%*;4c1A*&82!_7RIP`!49u3Gi;;6&)W#W~w z!>R&3CV|?o_tYeZ{Q<(ik+TZBc??i3A_;W=lglxxJR`UL&lc;lI{nNXQyv{|5tbDR zLow#|M;CFW!ac!w0^?k&NH*PXy0c^@qKSLjRv_T;Pk$BFG#$?gU~+kiL-~RRy8njc zQR)y7rv8-qFryB;Et#{6dgO&26;C-jtESTd;Aj#>$mSS1!w}6Qv~*2JHRWeCb;_&Z z;E>(6Qa39XewRz{-i&nF)$Rg%|23B;rzHI#qM;ufiy21ULMOP8bX3vBJ$9rZa~5a| zk*T5_3Ce3@6BbS2M-jm-6XlhD=$w}v@7i=iXPJ6%3fqk4i^M95SB%(dR`?NDAIK^D zBb26<*snD%bBYo@S-Tj(AXBBlNu8#{b;+YBup41%`6Az{7g6gA$p|e21e<~9wP9sD z)*$g%s~NuX_ilEL(hX@bI_ZJnMy5qLZiwg|=zH6ZxoXg&0mdF;qQ4q9i3Kz`OWfA1=Rk$0M_ySe9hb=^R zZ1k-)G`dgQl#$;)orR=P zWcy_S%_oF@BWH_n^V(09o?Gf!*8WwYNmp>h5^s6_x5^2Q+w>2j+e3FXB-Ax;3C^+P zH7k;K7TE6RSCe!~lM2-C>@Q23#FK5+-xJS&i;0I&hbB6}1rmfwBNCoDumZS|W$K*E z^J(A_xl(Qpd9OAsWVD&kJiuW4K7=H=h_ZGwOU>E1W!o2ZozZ18a}(^ut5h|EjK~G* zX^*BAK2IeWs>v$wI{g;Id{<~1$n`d&Ew(kynX0D5lIMog^smKNY%m6NXB;`@&q1ZE zoGGo1bfYK6Bl}^liwKsk3&X~kD_tPLZ*h*h=`o&sf<)m+w`1~6U}P|`UZJQ8%ymIut1rQ3Ma@A`Gkuuo~cKS&ewhBEP_@Uby! z01Mk?@B18ie!gV5P_@ovjoDBEey|zZPc5%y))mo zaYRbj#U>>(>m0gNCq;JSHeY-lrE{M!lCQaDK!cG6IvDi{$Cu(MmakdzQUbqf3=O=j z477a7@aAD5MMAK6XCS#jQ8WAH{X@C=#X=xcHipKhuma)vka2pcZ%Vsw}bgTn%pW_{))d zY*onM=f>iWVues`bNT!wP-E5JFF{^XqiKX6#`n-c)+Lne8~3QqSAFqISDxqaEf!8x z$PDUl+GlYg?@u0 zeT9S3n$eI3REnXcRx0kDmPU+!VNxx4Z)_oy?Y?HU4=WRpvCtgTMvr+C~=$@pKb9s;LmFZpjbDl!hl6PBiI(n^B-zf!Y0MRuN2 zSvMF&CByP2OZ;wie0*Ydb$>QGnk=ohmv|Z1wF_ix-W&P&n5i{>>|9u=HeH%4C*)cU z0Vr1R57rs&(d3_GTDT>@=RG)Q14Lrb_Ct5yv+8ZHfU>z_M(t1KcdnYvGbgBO=0XFzOn2)*SvgR^#Bs}P?#NJ3)oC2rMnP&B8-?d7J8g_@ zAMTN#nK^S*1g~iYrKZzXDRRWQy|d4@3p>~!wVCCCYN*EeNyNuQqeWU5YGnLK;Z~QE zx!{=&eE*i)FP2xkp)d(FdFN(Xs10S`gelP_sWf?yloy}AI7PK0UxJxC?8XNbJw?_w z;pqxp|4iswCBFKuo3fi=+wYL1U!3Roy~34?tC!kVOpQiII&;FC;7B#?H*ye^8%Tf( zJ;|HD11sI*5iLf?KTE;h9zOELTHc!D@$FK7u}{3@o3p}QglHhj1!kwo#0r+817l+a zkXz{iV7B3`vLlsr@ggQ0S3P-BwrFCOItmDX3inVr2NIKd|7tQedO7v3utr8-9WTzn zh3aQghQtP}Y3p>$Wm2Rh2U6Ntl`#gMW=<7cW`^)Yjs9g`oU>6(+pnrT69|NY7W9L7 z!jU+@{(kW{&s8;5>2xzMao6v6J!voJ{o~jiPa2Z?)|NFQ%2sj-;&Q(+J`5&X)KTh? zyP|tr-BHZO1(xeb`NgCZw0Ty`?jG3g3^1JUP2GO8hS_RMWhK5ngRmSr3pb=D3RVFlu$!QKuW;S zlmJ0MM5QPoC@3Nz!o_pXIlub{-1~I*!~VX#ANIrg##&>KImaAtvSGzOqTN*GmW z-9;(4-31!g=mzp`W-?qqxe_D=r#^j2aj}SPJIODjThCYmzd5C4?a%M_=MpYkPy^Pb zU|r3FQ#QWpn;`>U7Dw5eXFJxP_GmI>2kdimGb)GmviqZKs>5f|d$M(_&83jO-{l4; z2a71A*>lKYKh4>`#VhePb>wI5vHbZx$g?0n7TYNFk{#@A|?#P$TjK^gm)F|Vc81xvar&VN6E;JV8VIYFra=F3TAUBn{n zJPm$zQ2-35HRiJFe{3=RfgGCTI6D+~3Az2hiIrdeEqB_7e~I;X4`95i(ZT2(5-=oh zue6m9I*27PDPM!@tvNxI>&5EU`VV?T~#C`Ce*cQSuOL*$h4g# zfxRF<6b0H)C6%k90{VQ_GUf9;yEEi=N7?$l-a<=$2t)$Qd#bB5*cfCL~0bf4ne7NkPkbiLw6Ow?8T?Oc{ji@^| z7|_c}YR!?7N?#YbCLmBIzaGwk7Kw3B8`nTk4s(r(Dy&%be|JrLyPxPV+}ruOX|*cE z@73Twse{m4x1Fe(XJUBu*OO(1lOG7q;E)rs?#YcJdYdK!d!;Qm*nQke6XJZ-fU{>C zGb>2S>}ys`r*l>sfxY7&O^C=GJ06Zc97fFQPNnf!KG!kQrkmrqJ2f`j6S$|hFk9*r z6lsA*b+HJJWT$vw`aPMVLz*3zZr@grf_-Q+{I)Q=-C84IB1sc1F$o zY`dI)bnK_x(=bHRcv@?~V6glRDEGAkK#UUkNH=9t5?oC?$pfLJ2_@?LqAE4{49ZKF zkjRt56k6@$MFPFC)|Gp6kQYQS=PPj7vt;ad#KRi0bZJH`BA7PhAe4JnU+6&SkMA`g zx}tDi?=8>m_epXf%Pa~bx4KwCbJAOn2&XPJcgCuBk;4JD0=GB(OMhZNP^vLzF(%!a zEqeY3a((f~WZ?$?lUR#C@mvz?KRwo*2kC;}w-DFJ3pgKwX_&+ekLs;UbWbQD#UC&Q%*r)ysJgBy`dY2|SwhBls4>mp*AHwa*_!+cRG9D6 z<&WN?$zDkje`#RZd2t68p3+v~k}m|e@K{3SnF^_vpXG1apKaSMG) zRZZnfarQDHrsD;Dh2`XHt@4CgEm!=fg*!94Jz|BknT$H98k*Eq()}7A_5qSkoE&CWh7+FfX z1sYUOEW-nW;NLppX3>)nf`xLAxuzUtc^^jA%aX zKxa4YIn949ReyJ{!C}BB+R>*w^=^z}$5U z$vbXP$TJ_s!Xxa2qcE?^9Z=*gECut~n5-ABCz2h+B@hQsfm~0Y2 zZUHXZ5V0B!-lK5gyG^HFjLcz-wHq+xv*X{$(v6di!&JEj&TA@6BE*|LDYwWcx_eVv zF-|1#MO$+Ejv4joxFadu*UuEVaxb^`R$m8IbznzrIH7(t;9-dR-SJM&d($0v%-iRE zpD9cu1422d(@>~3ujLL0b?{~wX2GxHT-`aPymh(Ympx|TGBNBn%N;)_k`s(y;iJN9 zg=%lOoBSTVKo>&gzTYprmSNa6oi^Cbqeuq%sy?0wzG}rz?E=ydS@Y5%Gm3G4Z(OV7 zp;vIrKNQIy$^?{TWfdRNG;j1Re3=N`WTFRoUCkMvJZ;e=b2kHThBC?BexM=s#GoqN zfC*tE{=NwS7YOZ+brILyhp>ze+Gq_~KwB(^7@_o1Gu9`FjV3>$jr`y#ZE_hG6higR5X}@h_{SV~6$DjNP#cKbjE+@3NPDk~h zQt(Tuun6bFu^(UhUze6y9{01Lj}gH2LXYj*Wywm{MgNY2t;^kh)Tl6tZ<%jqd8mg! z%hNKJhcz%*M^qlR1@VwhD_l!+e+yY~5W6ij6MvwfF1XUC;`0$7>?7qevF^L*qj0f4 z`+9VKF=%UPXYKRo`=yU~%-%bNu(p%7lNR6ao`ufeeF~u&7Z=m%ey%_$F~BiWFtgUg z#DIy29x$0O0$8N%GLDYgNo}jqx@Li#T`A1j84t9HLs*g@-02c-t>J6%NY^GvsUxdf zf=tgJz0D0bTFSFLt(gnnHxvB!oYrJZBo1EproM3694+K?nm;m(v1zIh&(DHbjk~*V zJVfg!D=SV9`|HOtQde!z@Ng&M?!^U32qDHI3r&PP^k})$^G_&wVDYe6zRcP{q(Wk| z5Ml%SNij6V(kxL*uKkAWrr4*QFm@*mQx5tmlru~LFI)5tMKIoDz@6;4S%tN!-pKM0 zR(Kf<_A`5~_AN-oKGVpn_iUQxn&@hMY295bI=)tVy$uU-xDG#EYZ6~(B5g9iyOuzz z?kpuS38n}G3ah(97K;)a^GV#Sp{uMUB^~%Mzx$B3B=w`W8!&Z5--udmOk8RHt_&5? zK*^+i@gOKgGFA8MsGCekaKKO`+cNwK-M$!Hh@#z=R!7%Jl0?85$O7OKD@U=YJuvI*l>3qe+lPxv*w&+bz_gX!{!-&7Tvaf`>Q9O*-+q-L+?-@tX;|5e21Bd zNywG=DTRQQ4&uHjEMbKc1vNx!<~ZceA`py57E^oS;x!YsWvWPzvw`}Fz?gOp;qgNy zJ(JNo4`q``a0X_4?X-?kbPQYRyPww~mGny07G-&j^SSX1VH;`Wg*5(J(rnDT|FdpG zjUd~umUAksKehQg^p}^0XY|QV`PmEn0fAv^HWC-bvI#D?`mvD}q#R{|D)G!RI;oB- zdu}vys{hrt#;W;-T)(yWoW|FU9eYoWivq*mpCw-I)@g&%DqR|>9kAMdNP(Q&8g&Y} zgtSNcBng?w%o0FU5{mCo)$hc8ZhIJY;V{(?QwHDLRZSVy$)D}2ds9^;$`@DH4!P38 z27P>KiMjN%N-&v}5tp$)W(DSfE6NBYf~m1&Y|vD2gRrKX=*_AL35?Jn`!KdKkFuVj zP{y&Y#UVftt1EdRc=g7bF=}{E%+b(dNY?}O6pFzlG|@>G0(`Cl6_dDR-)#k9N`K~JE~(Duvj zvZ?RDW7A><2G@tEVPA#2FAF7#+k}Q|-0OM9?Unp-9>U(!&U13Zl>XN_DKg0^>n!gX zj5A1FJhBG6&q!T3*RgM1^xjCR&uiG659Ytu_JPA@aq2Fl#yrVMo+Fs+TCg+AI3X1u znla>aoH680hv$kT#5jPqGU(Qz2A~hTR_qDEM9>%j;xf%n^v+Fjd9T%5hIkE^51Eyc z$}Kz=%)w$IuJp=gs~qxWhFW_8EMjH~UXlrT8cFOAN}Zrt_i&RyVlQ?cTaB1QddtvX z%z$N^#C@Mos9KY5|7*Ix+kF4|8>Ps`z|~EAF%27`wBldR*FQbKDEjnR zn5Ovhrqq03z8bW>{^E*?7Lh6aP_IgIC_jLm4G>$ST!k;(;Z0R8m`%!#KboqMMglr8`*3B+LLVSXh55r1se0YwTmWP| zEwx+l0JfL}##eMI20T9o$;LUOHCdQgsLLFAH8stU2DEXkFwt^0cidCh&5qSSyt;h# zXI~h0gvK=RAIM4Ukx*^^+hVo1Lg@ri=?JSA^)CGWeki0FJfg|r|NhB!OX6c7+F4_JsH%H)!f`n zb(F-t)bdbmuk@k3C&4#v4$?gC#Q%V6e!X=--kG|m!z{~X$WzCJ%%?4eF{lGXLLzYq zTCA->1f*8VM=fSwb)p1yVnY+1Cf&echcJ8AN;78Vu-8wj80n)G-Dr7|Q$%`sP*i~@tRyQmhDCE%nmB}wB%SyC(G7@H@uN~Ds z$ej2Y-ETz3Ed>Bs3wxoE4M13X_I^ug1)KJh8 zfucV-(O;RL6c%snL-izWSaDPe-r_6c@Pj57IX=dk6tZVr^p|=7fbikkx;_BnKajf& z3I>PsllAn)04|Lre}aNpl8^kIz%(`Gr5!6@-)yY(ybUOZX)8oG7`jb|eEyw~{-$MU zCg-g?z9%YK=VQ}Ifbwz5sLA;|gqfQ6%^~|XHCKcAje!PWpa|ual9$F6yi1uVm)AZ5BsE)Zbw)XPm#3%`A7$T384tQPJr#k4gKox^LQ-kd}p_pXM#4n5$&e zsjJELKFAF&?hM90!;$djcew!r*Cr}lT$E`@SP_pI7T;G}K70h!F_AN&RdX90^LFwv z83dCc&AcoE0Ga93tRgrzS{EK%YHADX%%q8<++>jnp?g*{8%GHQk|a)9$%_}X(PUBp zV-vaT87_tHIMi+ue(507K-r>aC!0sU`>!}%zm{PDyZ5SZavw$&Q9(?x8Rfz7U}j3s zT$u+gUvqF4upYQuLFFnV-u`&uOnNK0?zz`7n6JP!hTd#_s(vY}$JZ2G9n$&vM!Yi{R}U9uv<6QC<El?qO;n|xIe0!>%#^wLbZvK`!+?8s0B%5h3;u;G3mD$#(xZ@F4BYCvLcA@R7R$`ohG z0#7L$Xus>vaEknjG)w24iQKlZ8uLbcXAl;uN?}wjVX?S!-8isOyi?FL8Ztdk)Kl#p zR=G|P^7L6UV~Yp~DSUCjWuQq^PEsb4gqNAg8&qt0N@YAx2l11%L5KtskNKD6 zvMHLNwt8lM|4qA3xX##{=?Z+qbb}66wGCujW6~%wJ>?h1F$|y@N`Z;?k2=#zPzR?1 zKuh2kI!>^gV6HsHjA-=JwL8^B05Lo``>9!e!&?*Pa1WKw9S^UkDC1oG@`=PdvL%tK zmPw|5>Nq3+yw6&msp=a>dGQm~FK^Mh?%Ng)RW`fjM}T+T?OS_hI_@J^^Ti>~ z8t5>!nb&Ny_Lj#z{Pq;GSyre9AiG3D^=9g5@>ZDOtE=tfc%UPgE*aY;mjHL)A@xBqbzdncd|L=qU1(YgwbpQYW literal 0 HcmV?d00001 diff --git a/src/game/scenes/world/builder.ts b/src/game/scenes/world/builder.ts index c8f7d9ee..8ef797a9 100644 --- a/src/game/scenes/world/builder.ts +++ b/src/game/scenes/world/builder.ts @@ -5,6 +5,7 @@ import { DIFFICULTY } from '~const/world/difficulty'; import { BUILDING_TILE } from '~const/world/entities/building'; import { BUILDINGS } from '~const/world/entities/buildings'; import { LEVEL_MAP_PERSPECTIVE, LEVEL_MAP_TILE } from '~const/world/level'; +import { Analytics } from '~lib/analytics'; import { isPositionsEqual } from '~lib/dimension'; import { phrase } from '~lib/lang'; import { progressionLinear } from '~lib/progression'; @@ -74,15 +75,19 @@ export class Builder extends Phaser.Events.EventEmitter implements IBuilder { } public update() { - if (this.isCanBuild()) { - if (this.isBuild) { - this.updateSupposedPosition(); - this.updateBuildInstance(); - } else { - this.open(); + try { + if (this.isCanBuild()) { + if (this.isBuild) { + this.updateSupposedPosition(); + this.updateBuildInstance(); + } else { + this.open(); + } + } else if (this.isBuild) { + this.close(); } - } else if (this.isBuild) { - this.close(); + } catch (error) { + Analytics.TrackWarn('Failed builder update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/building/building.ts b/src/game/scenes/world/entities/building/building.ts index e0cd2c73..1369c141 100644 --- a/src/game/scenes/world/entities/building/building.ts +++ b/src/game/scenes/world/entities/building/building.ts @@ -7,6 +7,7 @@ import { BUILDING_TILE } from '~const/world/entities/building'; import { LEVEL_MAP_PERSPECTIVE } from '~const/world/level'; import { Indicator } from '~entity/addons/indicator'; import { Live } from '~entity/addons/live'; +import { Analytics } from '~lib/analytics'; import { Assets } from '~lib/assets'; import { progressionQuadratic, progressionLinear } from '~lib/progression'; import { Tutorial } from '~lib/tutorial'; @@ -153,12 +154,16 @@ export class Building extends Phaser.GameObjects.Image implements IBuilding, ITi } public update() { - this.updateOutline(); - this.updateIndicators(); + try { + this.updateOutline(); + this.updateIndicators(); - // Catch focus by camera moving - if (this.toFocus) { - this.focus(); + // Catch focus by camera moving + if (this.toFocus) { + this.focus(); + } + } catch (error) { + Analytics.TrackWarn('Failed building update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/building/variants/electro.ts b/src/game/scenes/world/entities/building/variants/electro.ts index 184f2823..a9a96ee5 100644 --- a/src/game/scenes/world/entities/building/variants/electro.ts +++ b/src/game/scenes/world/entities/building/variants/electro.ts @@ -1,10 +1,12 @@ import { DIFFICULTY } from '~const/world/difficulty'; import { LEVEL_MAP_PERSPECTIVE } from '~const/world/level'; +import { Analytics } from '~lib/analytics'; import { progressionLinear } from '~lib/progression'; import { Building } from '~scene/world/entities/building'; import { IWorld } from '~type/world'; import { EntityType } from '~type/world/entities'; import { + BuildingAudio, BuildingCategory, BuildingEvents, BuildingIcon, @@ -63,12 +65,14 @@ export class BuildingElectro extends Building implements IBuilding { public update() { super.update(); - if (!this.isActionAllowed()) { - return; + try { + if (this.isActionAllowed()) { + this.attack(); + this.pauseActions(); + } + } catch (error) { + Analytics.TrackWarn('Failed electro building update', error as TypeError); } - - this.attack(); - this.pauseActions(); } public getInfo() { @@ -149,6 +153,10 @@ export class BuildingElectro extends Building implements IBuilding { } }); + if (this.scene.game.sound.getAll(BuildingAudio.ELECTRO).length === 0) { + this.scene.game.sound.play(BuildingAudio.ELECTRO); + } + if (this.area) { this.area.setActive(true); this.area.setVisible(true); diff --git a/src/game/scenes/world/entities/building/variants/generator.ts b/src/game/scenes/world/entities/building/variants/generator.ts index 35a67b24..acfd2c35 100644 --- a/src/game/scenes/world/entities/building/variants/generator.ts +++ b/src/game/scenes/world/entities/building/variants/generator.ts @@ -1,5 +1,6 @@ import { DIFFICULTY } from '~const/world/difficulty'; import { Building } from '~entity/building'; +import { Analytics } from '~lib/analytics'; import { Tutorial } from '~lib/tutorial'; import { TutorialStep } from '~type/tutorial'; import { IWorld } from '~type/world'; @@ -47,12 +48,14 @@ export class BuildingGenerator extends Building { public update() { super.update(); - if (!this.isActionAllowed()) { - return; + try { + if (this.isActionAllowed()) { + this.generateResource(); + this.pauseActions(); + } + } catch (error) { + Analytics.TrackWarn('Failed generator building update', error as TypeError); } - - this.generateResource(); - this.pauseActions(); } public getTopFace() { diff --git a/src/game/scenes/world/entities/building/variants/tower/tower.ts b/src/game/scenes/world/entities/building/variants/tower/tower.ts index 432b120b..afa5b0c1 100644 --- a/src/game/scenes/world/entities/building/variants/tower/tower.ts +++ b/src/game/scenes/world/entities/building/variants/tower/tower.ts @@ -1,5 +1,6 @@ import { DIFFICULTY } from '~const/world/difficulty'; import { Building } from '~entity/building'; +import { Analytics } from '~lib/analytics'; import { getClosestByIsometricDistance } from '~lib/dimension'; import { progressionLinear } from '~lib/progression'; import { Tutorial } from '~lib/tutorial'; @@ -55,8 +56,12 @@ export class BuildingTower extends Building implements IBuildingTower { public update() { super.update(); - if (this.isCanAttack()) { - this.attack(); + try { + if (this.isCanAttack()) { + this.attack(); + } + } catch (error) { + Analytics.TrackWarn('Failed tower building update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/npc/npc.ts b/src/game/scenes/world/entities/npc/npc.ts index 1c35452e..93eaeffb 100644 --- a/src/game/scenes/world/entities/npc/npc.ts +++ b/src/game/scenes/world/entities/npc/npc.ts @@ -5,6 +5,7 @@ import { WORLD_DEPTH_GRAPHIC } from '~const/world'; import { NPC_PATH_FIND_RATE } from '~const/world/entities/npc'; import { LEVEL_MAP_PERSPECTIVE } from '~const/world/level'; import { Sprite } from '~entity/sprite'; +import { Analytics } from '~lib/analytics'; import { isPositionsEqual, getIsometricAngle, getIsometricDistance } from '~lib/dimension'; import { Level } from '~scene/world/level'; import { IWorld } from '~type/world'; @@ -66,18 +67,22 @@ export class NPC extends Sprite implements INPC { public update() { super.update(); - if (this.isCanPursuit()) { - if (this.getDistanceToTarget() <= this.pathFindTriggerDistance) { - this.resetPath(); - this.isPathPassed = true; + try { + if (this.isCanPursuit()) { + if (this.getDistanceToTarget() <= this.pathFindTriggerDistance) { + this.resetPath(); + this.isPathPassed = true; + } else { + this.findPathToTarget(); + this.moveByPath(); + this.isPathPassed = false; + } } else { - this.findPathToTarget(); - this.moveByPath(); + this.setVelocity(0, 0); this.isPathPassed = false; } - } else { - this.setVelocity(0, 0); - this.isPathPassed = false; + } catch (error) { + Analytics.TrackWarn('Failed NPC update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/npc/variants/assistant.ts b/src/game/scenes/world/entities/npc/variants/assistant.ts index 8f9a1372..4902a3c3 100644 --- a/src/game/scenes/world/entities/npc/variants/assistant.ts +++ b/src/game/scenes/world/entities/npc/variants/assistant.ts @@ -3,6 +3,7 @@ import { ASSISTANT_PATH_BREAKPOINT, ASSISTANT_TILE_SIZE, ASSISTANT_WEAPON } from import { NPC } from '~entity/npc'; import { ShotBallFire } from '~entity/shot/ball/variants/fire'; import { ShotLazer } from '~entity/shot/lazer'; +import { Analytics } from '~lib/analytics'; import { Assets } from '~lib/assets'; import { getClosestByIsometricDistance, getIsometricDistance } from '~lib/dimension'; import { progressionQuadratic } from '~lib/progression'; @@ -63,12 +64,16 @@ export class Assistant extends NPC implements IAssistant { public update() { super.update(); - if (this.isPathPassed) { - this.setVelocity(0, 0); - } + try { + if (this.isPathPassed) { + this.setVelocity(0, 0); + } - if (this.isCanAttack()) { - this.attack(); + if (this.isCanAttack()) { + this.attack(); + } + } catch (error) { + Analytics.TrackWarn('Failed assistant update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/npc/variants/enemy/enemy.ts b/src/game/scenes/world/entities/npc/variants/enemy/enemy.ts index 65106abb..4232891d 100644 --- a/src/game/scenes/world/entities/npc/variants/enemy/enemy.ts +++ b/src/game/scenes/world/entities/npc/variants/enemy/enemy.ts @@ -7,6 +7,7 @@ import { } from '~const/world/entities/enemy'; import { Building } from '~entity/building'; import { NPC } from '~entity/npc'; +import { Analytics } from '~lib/analytics'; import { Assets } from '~lib/assets'; import { progressionLinear, progressionQuadratic } from '~lib/progression'; import { GameSettings } from '~type/game'; @@ -124,13 +125,17 @@ export class Enemy extends NPC implements IEnemy { public update() { super.update(); - if (this.isOverlapTarget) { - this.setVelocity(0, 0); - } else if (this.isPathPassed) { - this.moveTo(this.scene.player.getBottomFace()); - } + try { + if (this.isOverlapTarget) { + this.setVelocity(0, 0); + } else if (this.isPathPassed) { + this.moveTo(this.scene.player.getBottomFace()); + } - this.isOverlapTarget = false; + this.isOverlapTarget = false; + } catch (error) { + Analytics.TrackWarn('Failed enemy update', error as TypeError); + } } public overlapTarget() { diff --git a/src/game/scenes/world/entities/npc/variants/enemy/variants/berserk.ts b/src/game/scenes/world/entities/npc/variants/enemy/variants/berserk.ts index f7fc2f51..dee2808e 100644 --- a/src/game/scenes/world/entities/npc/variants/enemy/variants/berserk.ts +++ b/src/game/scenes/world/entities/npc/variants/enemy/variants/berserk.ts @@ -1,4 +1,5 @@ import { ENEMY_HEAL_MULTIPLIER, ENEMY_HEAL_TIMESTAMP_PAUSE } from '~const/world/entities/enemy'; +import { Analytics } from '~lib/analytics'; import { IWorld } from '~type/world'; import { EnemyVariantData, EnemyTexture } from '~type/world/entities/npc/enemy'; @@ -23,8 +24,13 @@ export class EnemyBerserk extends Enemy { } public update() { - this.heal(); super.update(); + + try { + this.heal(); + } catch (error) { + Analytics.TrackWarn('Failed berserk enemy update', error as TypeError); + } } private heal() { diff --git a/src/game/scenes/world/entities/npc/variants/enemy/variants/ghost.ts b/src/game/scenes/world/entities/npc/variants/enemy/variants/ghost.ts index f594b98b..55674e4c 100644 --- a/src/game/scenes/world/entities/npc/variants/enemy/variants/ghost.ts +++ b/src/game/scenes/world/entities/npc/variants/enemy/variants/ghost.ts @@ -1,3 +1,4 @@ +import { Analytics } from '~lib/analytics'; import { IWorld } from '~type/world'; import { BuildingVariant } from '~type/world/entities/building'; import { EnemyVariantData, EnemyTexture } from '~type/world/entities/npc/enemy'; @@ -25,6 +26,14 @@ export class EnemyGhost extends Enemy { public update() { super.update(); + try { + this.updateVisible(); + } catch (error) { + Analytics.TrackWarn('Failed ghost enemy update', error as TypeError); + } + } + + private updateVisible() { const isVisible = this.scene.builder .getBuildingsByVariant(BuildingVariant.RADAR) .some((building) => building.actionsAreaContains(this)); diff --git a/src/game/scenes/world/entities/npc/variants/enemy/variants/telepath.ts b/src/game/scenes/world/entities/npc/variants/enemy/variants/telepath.ts index d42f6aee..8f679149 100644 --- a/src/game/scenes/world/entities/npc/variants/enemy/variants/telepath.ts +++ b/src/game/scenes/world/entities/npc/variants/enemy/variants/telepath.ts @@ -2,6 +2,7 @@ import { ENEMY_REGENERATION_EFFECT_COLOR, ENEMY_REGENERATION_EFFECT_DURATION, ENEMY_REGENERATION_RADIUS, } from '~const/world/entities/enemy'; import { LEVEL_MAP_PERSPECTIVE } from '~const/world/level'; +import { Analytics } from '~lib/analytics'; import { getIsometricDistance } from '~lib/dimension'; import { IWorld } from '~type/world'; import { EntityType } from '~type/world/entities'; @@ -41,11 +42,21 @@ export class EnemyTelepath extends Enemy { public update() { super.update(); - if (this.regenerateArea.visible) { - const position = this.getBottomFace(); + try { + this.updateArea(); + } catch (error) { + Analytics.TrackWarn('Failed telepth enemy update', error as TypeError); + } + } - this.regenerateArea.setPosition(position.x, position.y); + private updateArea() { + if (!this.regenerateArea.visible) { + return; } + + const position = this.getBottomFace(); + + this.regenerateArea.setPosition(position.x, position.y); } public onDamage(amount: number) { diff --git a/src/game/scenes/world/entities/player.ts b/src/game/scenes/world/entities/player.ts index b3559097..24b03e65 100644 --- a/src/game/scenes/world/entities/player.ts +++ b/src/game/scenes/world/entities/player.ts @@ -11,6 +11,7 @@ import { import { LEVEL_MAP_PERSPECTIVE } from '~const/world/level'; import { Crystal } from '~entity/crystal'; import { Sprite } from '~entity/sprite'; +import { Analytics } from '~lib/analytics'; import { Assets } from '~lib/assets'; import { getClosestByIsometricDistance, isPositionsEqual } from '~lib/dimension'; import { progressionLinear, progressionQuadratic } from '~lib/progression'; @@ -184,16 +185,20 @@ export class Player extends Sprite implements IPlayer { public update() { super.update(); - this.findPathToCrystal(); - this.drawPathToCrystal(); + try { + this.findPathToCrystal(); + this.drawPathToCrystal(); - if (!this.live.isDead()) { - this.dustEffect?.emitter.setDepth(this.depth - 1); + if (!this.live.isDead()) { + this.dustEffect?.emitter.setDepth(this.depth - 1); - this.updateMovement(); - this.updateVelocity(); - this.updateVisible(); - this.updateStamina(); + this.updateMovement(); + this.updateVelocity(); + this.updateVisible(); + this.updateStamina(); + } + } catch (error) { + Analytics.TrackWarn('Failed player update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/shot/ball/ball.ts b/src/game/scenes/world/entities/shot/ball/ball.ts index f71ff7a1..2cd746c5 100644 --- a/src/game/scenes/world/entities/shot/ball/ball.ts +++ b/src/game/scenes/world/entities/shot/ball/ball.ts @@ -82,7 +82,17 @@ export class ShotBall extends Phaser.Physics.Arcade.Image implements IShotBall { } public update() { + try { + this.updateFlyDistance(); + } catch (error) { + Analytics.TrackWarn('Failed ball shot update', error as TypeError); + } + } + + private updateFlyDistance() { if (!this.params.maxDistance || !this.startPosition) { + this.stop(); + return; } diff --git a/src/game/scenes/world/entities/shot/lazer.ts b/src/game/scenes/world/entities/shot/lazer.ts index 7f716138..76ee191f 100644 --- a/src/game/scenes/world/entities/shot/lazer.ts +++ b/src/game/scenes/world/entities/shot/lazer.ts @@ -61,7 +61,7 @@ export class ShotLazer extends Phaser.GameObjects.Line implements IShotLazer { this.updateLine(); this.processing(); } catch (error) { - Analytics.TrackWarn('Failed lazer update', error as TypeError); + Analytics.TrackWarn('Failed lazer shot update', error as TypeError); } } diff --git a/src/game/scenes/world/entities/sprite.ts b/src/game/scenes/world/entities/sprite.ts index 0435e676..bb9ce357 100644 --- a/src/game/scenes/world/entities/sprite.ts +++ b/src/game/scenes/world/entities/sprite.ts @@ -4,6 +4,7 @@ import { DEBUG_MODS } from '~const/game'; import { WORLD_COLLIDE_SPEED_FACTOR, WORLD_DEPTH_GRAPHIC } from '~const/world'; import { Indicator } from '~entity/addons/indicator'; import { Live } from '~entity/addons/live'; +import { Analytics } from '~lib/analytics'; import { isPositionsEqual } from '~lib/dimension'; import { Level } from '~scene/world/level'; import { ILive, LiveEvents } from '~type/live'; @@ -98,17 +99,24 @@ export class Sprite extends Phaser.Physics.Arcade.Sprite implements ISprite { } public update() { + try { + this.updateDimension(); + this.updateContainer(); + this.updateIndicators(); + + this.drawDebugGroundPosition(); + } catch (error) { + Analytics.TrackWarn('Failed sprite update', error as TypeError); + } + } + + private updateDimension() { const positionOnGround = this.getBottomFace(); this.positionAtMatrix = Level.ToMatrixPosition(positionOnGround); this.currentBiome = this.scene.level.map.getAt(this.positionAtMatrix); this.setDepth(positionOnGround.y); - - this.updateContainer(); - this.updateIndicators(); - - this.drawDebugGroundPosition(); } private addContainer() { diff --git a/src/game/scenes/world/wave.ts b/src/game/scenes/world/wave.ts index 8608f60c..48965585 100644 --- a/src/game/scenes/world/wave.ts +++ b/src/game/scenes/world/wave.ts @@ -71,28 +71,45 @@ export class Wave extends Phaser.Events.EventEmitter implements IWave { } public update() { + try { + this.handleTimeleft(); + this.handleProcessing(); + } catch (error) { + Analytics.TrackWarn('Failed wave update', error as TypeError); + } + } + + private handleProcessing() { + if (!this.isGoing) { + return; + } + const now = this.scene.getTime(); - if (this.isGoing) { - if (this.spawnedEnemiesCount < this.enemiesMaxCount) { - if (this.nextSpawnTimestamp <= now) { - this.spawnEnemy(); - } - } else if (this.scene.getEntitiesGroup(EntityType.ENEMY).getTotalUsed() === 0) { - this.complete(); - } - } else if (!this.isPeaceMode) { - const left = this.nextWaveTimestamp - now; - - if (left <= 0) { - this.start(); - } else if ( - left <= WAVE_TIMELEFT_ALARM - && !this.scene.isTimePaused() - && !this.alarmInterval - ) { - this.runAlarmCountdown(); + if (this.spawnedEnemiesCount < this.enemiesMaxCount) { + if (this.nextSpawnTimestamp <= now) { + this.spawnEnemy(); } + } else if (this.scene.getEntitiesGroup(EntityType.ENEMY).getTotalUsed() === 0) { + this.complete(); + } + } + + private handleTimeleft() { + if (this.isGoing || this.isPeaceMode) { + return; + } + + const left = this.nextWaveTimestamp - this.scene.getTime(); + + if (left <= 0) { + this.start(); + } else if ( + left <= WAVE_TIMELEFT_ALARM + && !this.scene.isTimePaused() + && !this.alarmInterval + ) { + this.runAlarmCountdown(); } } diff --git a/src/types/world/entities/building.ts b/src/types/world/entities/building.ts index 44d64135..8f8754ba 100644 --- a/src/types/world/entities/building.ts +++ b/src/types/world/entities/building.ts @@ -246,6 +246,7 @@ export enum BuildingAudio { REPAIR = 'building/repair', DAMAGE_1 = 'building/damage_1', DAMAGE_2 = 'building/damage_2', + ELECTRO = 'building/electro', } export enum BuildingOutlineState {