From b69adf70b3121231dcd3a670ac5bcb26fb1de747 Mon Sep 17 00:00:00 2001 From: DevelopingTom Date: Sat, 25 Oct 2025 23:06:15 +0200 Subject: [PATCH] Halloween Event (#2285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: Changed theme colors for an "autumn" ambiance: image Changed structures pixel art: image Change existing FX with new halloween-themed ones: https://github.com/user-attachments/assets/fb99be49-43cd-4d85-ad77-8c153070edaf Added new FX playing randomly on the map: https://github.com/user-attachments/assets/16631113-77e6-4b8c-b1b6-c147f5f1d275 Added a couple of new emojis, which are used by the bots when attacked: 👻🎃 ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: IngloriousTom --- resources/images/buildings/cityAlt1.png | Bin 303 -> 739 bytes resources/images/buildings/factoryAlt1.png | Bin 305 -> 647 bytes resources/images/buildings/fortAlt3.png | Bin 262 -> 592 bytes resources/images/buildings/port1.png | Bin 325 -> 843 bytes resources/images/buildings/silo1.png | Bin 227 -> 537 bytes resources/images/buildings/silo4.png | Bin 259 -> 726 bytes resources/sprites/halloween/bats.png | Bin 0 -> 316 bytes resources/sprites/halloween/bubble.png | Bin 0 -> 438 bytes resources/sprites/halloween/ghost.png | Bin 0 -> 246 bytes resources/sprites/halloween/miniPumpkin.png | Bin 0 -> 228 bytes resources/sprites/halloween/minifireGreen.png | Bin 0 -> 204 bytes resources/sprites/halloween/pumpkin.png | Bin 0 -> 341 bytes resources/sprites/halloween/sam_explosion.png | Bin 0 -> 2319 bytes resources/sprites/halloween/shark.png | Bin 0 -> 553 bytes resources/sprites/halloween/skull.png | Bin 0 -> 1168 bytes resources/sprites/halloween/skullNuke.png | Bin 0 -> 19904 bytes .../sprites/halloween/smokeAndFireGreen.png | Bin 0 -> 409 bytes resources/sprites/halloween/tentacle.png | Bin 0 -> 2088 bytes resources/sprites/halloween/tornado.png | Bin 0 -> 3531 bytes src/client/graphics/AnimatedSpriteLoader.ts | 117 ++++++++++++------ src/client/graphics/SpriteLoader.ts | 8 +- src/client/graphics/fx/ConquestFx.ts | 1 - src/client/graphics/fx/Fx.ts | 4 + src/client/graphics/fx/SpriteFx.ts | 33 ++++- src/client/graphics/layers/FxLayer.ts | 78 +++++++++++- src/core/Util.ts | 10 +- src/core/configuration/PastelTheme.ts | 18 +-- src/core/execution/utils/BotBehavior.ts | 2 +- 28 files changed, 210 insertions(+), 61 deletions(-) create mode 100644 resources/sprites/halloween/bats.png create mode 100644 resources/sprites/halloween/bubble.png create mode 100644 resources/sprites/halloween/ghost.png create mode 100644 resources/sprites/halloween/miniPumpkin.png create mode 100644 resources/sprites/halloween/minifireGreen.png create mode 100644 resources/sprites/halloween/pumpkin.png create mode 100644 resources/sprites/halloween/sam_explosion.png create mode 100644 resources/sprites/halloween/shark.png create mode 100644 resources/sprites/halloween/skull.png create mode 100644 resources/sprites/halloween/skullNuke.png create mode 100644 resources/sprites/halloween/smokeAndFireGreen.png create mode 100644 resources/sprites/halloween/tentacle.png create mode 100644 resources/sprites/halloween/tornado.png diff --git a/resources/images/buildings/cityAlt1.png b/resources/images/buildings/cityAlt1.png index 1975fd265e9c2490bf2418d976e95d61003bf39c..2f9c52d8b1ac3dd028ed9b83c61184819c86a341 100644 GIT binary patch delta 726 zcmV;{0xA8k0^VLP$cT5QVyh6c}L?(kT}L zV^2%5frdyzrV~qB35&a1usGAfedEr~?98lQ3ib;Fk2mkV&wuy#{k_?Rl1eJ+f7EE- zgeJ!A=dNq^tL?R8s~dZ+-PZt=?_ajV$5ZTv(Y^_-vCeOp+fE8a8xU&q2Wj&Mx4OMJ z1ES|v)eGgP(CQDkO2u^o!bJZ_m+4(%HOX2!p@ZGRi!#ty=jZLaY0@b#{Ucqvk;G~e z0QFB9t^R8qjdg(|gDY-Jt5HUY;LbhqBqstz0?5)12d z^}YrGrXn+j>PMd3F@RNB!IPQMy%usPIICredis_s)w~lC9d_j^b%nZjnP(ApONGz;Z-969?z>TZ@ zkZp%ZCs$pUkDE+bo$vT(G#^URFa$q7XNcY2k18wN913RLSK99NWGYc*1qnD>UrlIy zp?Cwr1b=z)dNP~v@bH*vUX>M8S)n$d0@ch$7OhRXF#s_4xJn0Hyl_RIpNh%iK~y-)?T^b2gCGz^adZ$tz_$MXxAqQ@G=JgMZ5KT&lQ}tZ)t^4g z^5wj)P$p+EQT9C-h(-dC^Hk89tfkQtvH->dN?|r271|xgRt6jp@@FlaP>3LWVzsal zet&3=xxict51R_iG0K^3ui$+MFf_646+8$)1ke_Y5y4$as8-xkFy?98D+#LMyiowo lxl8qdPzq{{6d2U6@di6y28KKNd))v4002ovPDHLkV1ipLcDVom diff --git a/resources/images/buildings/factoryAlt1.png b/resources/images/buildings/factoryAlt1.png index 40e82d8c9fc0a154b0e671dcaa57fe7389a7231d..d98e2129152d0c78df52260b1d2ed5025ada5e24 100644 GIT binary patch delta 633 zcmV-<0*3vu0*3{V8Gi-<0047(dh`GQ00DDSM?wIu&K&6g000DMK}|sb0I`n?{9y$E z00J>dL_t(oN9~nAXcJ)=ho6X0!L49P2ZiEdh6E&_I28+l43>gJhEOuNb}Jc@h(Zk) zG9*waZnnb_QaCZ2h)cn#G?NY?Rggl!N;o8fij#aU`Odqq-+%oHjV|Va8@}Ir-22>* zaDf>!{s&f*Nug$v3u^GM`Rf9%x7W5XH341CnoK=U56vBjh|+pqmxrS+c3*N%c+Gxd09;f9To1My zHFX3)u2>-l!hdSiP#ZZi_r&eOgP1&bj4IuJpVQM%mDc+8&B%s5(#QVk}Vr*6iA?eL=~B&k*4)rjXVSj96v63&Z>yo2*8{@ zWX>M4+1zHcx$T+h&g{#+cVRl6{xq`v3jc=J3JW# ziue&_v2sK!AUUr{6r68%6vqE*+*!Kj$$wqC?0oM(ei?ZhNW~WzUWxPUjH+<`N0F)6W#%P96qLH zq*~;#J?Tg_g12mMx^gY~E!*3A0&}SmY=`!QgSvuk`2uFCE7%qx5CO^x8V1ik#=7D_ z2=pKy5JG5xB@kc9ATa2YnUgor26&tR?7NzsfU38C2td(0Ac8{~pss*d2oM2yASqGr n#6eRx1mLo!UmEFRr2B7Pb(sdoMI1=K00000NkvXXu0mjf{PcOn diff --git a/resources/images/buildings/fortAlt3.png b/resources/images/buildings/fortAlt3.png index 8087a89984e51b614c5184a90c44605dc7882290..4637bdd8fa5122f31c1e32e2e2f058d266d406a5 100644 GIT binary patch delta 578 zcmV-I0=@l)0?-7I8Gi-<0047(dh`GQ00DDSM?wIu&K&6g00Ih0L_t(oh3%HHYZFl% z$3Ibfq{cit+Oouw%d_WOX;VI`t25h(m{?5G}V!E5%8q zVpG8`rUgM0V>w9)Dd8NNT)k58y(ZvtpXKp*?|$DeKfdqBL4Qa{NJz*S6w6gFSEzX7 z)HpLK(OjY8&1EfRGg1al63rDVUM8J_{qGdZ)xeoym88v_Q*rBy9;4md1V9%Ws$Ebr z0Pya8gLbRM?EYKa9?V9;?ZK}LY4$ol0sK`4=?vsegS=_@d$$MC>+^hcuOOmF_jIA5 z3r*TUME2q+1AikEb!U}?uJifR2VWSV<@N#CSX-8=Ep6a$69FUkQb1Tm9MudYbe&NM z>&|LG_;?3oQJw=U>xM`vf!0leP_HB1 zfnvGpWzs38n;o7!yG8TIYi?e07*qoM6N<$g7T^l-~a#s delta 245 zcmVwmVfsG{pqKG5$%>T2IA-sG$4VNSV0Dt!P4=}e7FF6l}7F@b|1<{#V z4NBmglE$8@;>Gk2?tPae!6iu?92RqOE&~A2?rp-vWYS>7OcRqy;k6)3!Kc#ax$&0 zQ}$+(d;AOlVv9>cH2|z^Y;rH$yxs}`2zZ;d7=L9<;Ewt_#Mid~lXkg9QEOG}<+IPY zlF5R=WI}5}Y;j5J&&tN8!PMH$t_If|v1(PP$BoX@N-CKwluVXm&@(p_a*vqOM)G+sVEb<$ItZ76&+fsng9CN`UA2SbfvbyrYrye002ov JPDHLkV1gRoiwFP! delta 309 zcmV-50m}Z%2E_u98Gi!+002a!ipBr{069=hR7C&)0G64X*3T>P>t0t^S9yASo0ScA zEeW@(wM;V*RM{3Zhtb970rJk4^V^CiMR@! z9vH)XJ5O4|Cs=zLw^BC(*osGISKA^koZiq4S>BYFxxTTbuP6Z(B8|^2Q3Lr*FaAmttXGxlTMEb^>29t{Zs|MRRbUA00000NkvXX Hu0mjf4l;rT diff --git a/resources/images/buildings/silo1.png b/resources/images/buildings/silo1.png index 89686639c74825d9e59ed3deed6d8c18646ed906..a68c5e5c992ea07870b4b9af7488dba8ad0d7b8a 100644 GIT binary patch delta 524 zcmV+n0`vXj0ht7l7=H)`0001UdV2H#0004VQb$4nuFf3k00004XF*Lt006O%3;baP z0005QNklJRP)Z%RCfcE8172|l$AlNdHm~>O&SWEE*rssv z3I3cQGBqGFHGfcb&gq(j=AXC=>c6TM9sWQ~vJnaGo%8(iC2uxYiRS+Sa5$>nIA580CX310QCNTH}@&E9HLet4+z-km8~7|?unmzz0J{}IX*oj&NOP$pkHw>xB_Gi#v(SWjG+Jk O002ovP6b4+LSTX!k?uhN delta 211 zcmV;^04)ER1mgja7=Hu<0001iRAHSxR4{#`E08z1W*K0R#zyZC~(<9;)2k`2oiBXHkC=)NCDL$%m!#KWl|tNqyT)554%Oa*Yf}X N002ovPDHLkV1l4vQ`i6i diff --git a/resources/images/buildings/silo4.png b/resources/images/buildings/silo4.png index 8216f6b2f70d6c45634bf8add0d1f3dd2b6a4592..b01f33adf912486ec75ac5948c56fc996ef365f7 100644 GIT binary patch delta 714 zcmV;*0yX`E0@ekP7=H)`0001UdV2H#0004VQb$4nuFf3k00004XF*Lt006O%3;baP z0007jNklpe&R~YAnGp62-aEQ6rl%O$Q)` zt%*hlHBDqwVS@-Ek!UD`e_Fd#P45_hq?7~`lUpR}bFlAnoPYiE&Nw*qv)y~Y`~AM} z_vhU~lO|36A*n=C^mX@$yuU@{{Vl?|Uk$Hw;crMKk|LEzir&tUbE_d9=YktjiKGDN z?F{i~@fiTRVE_;c23c5MYUsbAK{f1w3tKvwTo&Chc=F|U@bLbjvR_vvaHd+G`r5>0 zLcyTJS`B5TGJmiR7=Hu<0001iRA+LgDSV(Ga z|AmEWkdyjQQ2!4P<|jt+00001bW%=J06^y0W&i*HkV!;AR4C75pfg}JFF@ssSWQ6X zD;X=G@P!~c5PT6WWF0`hqmTiT0FW=JgscON&%grY8>83>s0^%002ovPDHLkV1m?hSfT&` diff --git a/resources/sprites/halloween/bats.png b/resources/sprites/halloween/bats.png new file mode 100644 index 0000000000000000000000000000000000000000..ff96f164b109d72ccb0ae9e669ecbb7495b5ccc9 GIT binary patch literal 316 zcmV-C0mJ@@P)Px#_DMuRR9J=Wn86OiAP9za@51}+xWgWAhaLMqJWO{ou|_N)I@|CkO=`hUP(m6* zaJgJ_1OWTLV|Z9VR!HP3N_%C!XHs62!Voc1KBcY2M8ufC*Zep<2~#3Y?pkh&(}EWi zXP^R8Hc7<+z@8qBT{_$+sow5^M~(bB`$uBq7+P611J zJ+W}O`8ehuN3_bjw_j>bPy4MgN98`G(q>h!70-&>)3v1RY0&5EZPLfB?Em5n; zf!p_E^7rV>1(~(V>8(&_uE8WPaMEPUR^-g}nFp{l@5eN`vURy!7ts${W+3Ac9hz?d O0000Px$a7jc#RCt{2nL!SOAPhxmGMCl^=&?H+NeDq`OI0BMEft@@4Bw(5000000L%z8 z^VfX<01OHO0swH!Y5}p@cmPn3BXlCF@X4#4Pza2q0us3e+cp!HdDCpo-s+Rqjo=x883H1_Q<=Cg z?2+kt0em;l9-)+9>lsARvuyCBKdRTHO&Son+iUCM9TJa(PONMcTcjdHMDe4N#C5$_ zYC5fb@pfA8XLd>(PPUMXbS~s79or07ujVPLaj)#vxV^pUL!jkO+ts|K^LK7(byGVo g@k;s)0058j2Q&bzF=ofgnE(I)07*qoM6N<$g3qeA%K!iX literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/ghost.png b/resources/sprites/halloween/ghost.png new file mode 100644 index 0000000000000000000000000000000000000000..15603066be004d68dc216236fd40cc09403a6f9a GIT binary patch literal 246 zcmVPx#ut`KgR7i>4l{*r{APhvY2Xa?&AnC4gL7Fg;_#_J^g}se{d18eM;oMEM%_I>~ z%4-qn-hpx}N-Y-UP+yoMqNJshdQ6W+In)>CMhgtyn|PL6(U@H)JVG$B zr{{5)c$Pzbzj5XvsPSs8Xw2T=FR7u2h{zUWtj?LankWd@6Uu3M_Zem7xODHm8Jn3c wm`Wu#%b@j{S={Qvua7L}{QJXmll5IrFMA+KrN&-EGXMYp07*qoM6N<$g4#)DPyhe` literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/miniPumpkin.png b/resources/sprites/halloween/miniPumpkin.png new file mode 100644 index 0000000000000000000000000000000000000000..33274a1effeec94b110bbb1cb9f71bf96e77623b GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRM!3HF?&tBaMq!^2X+?^QKos)S9_j$TFhG+z*_8W3FI|#Vmk7E5Mb4pB!ZBL8h((9jiEF0fG6B3gOVhQ4` zYPn+HyIJDXY{`E%Y0nO?`&lLCtk~vcSaI}0>gF>It1@Tg->bQ0blf5RK(fqAzeoRS zE>HXEf3|@o=P%2FYyO-b&-)rqI^6glDZXUgv|Yc}`!gneh!USv`G#@MT6;IM*f@Fi a53Ca|#YFzB{p1XE8H1;*pUXO@geCxuuviuV literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/minifireGreen.png b/resources/sprites/halloween/minifireGreen.png new file mode 100644 index 0000000000000000000000000000000000000000..8de5aa2ec6322601b3edd73f03c4996886351051 GIT binary patch literal 204 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 literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/shark.png b/resources/sprites/halloween/shark.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce0a22754e664571e2ac82e68c29c74899f8d52 GIT binary patch literal 553 zcmV+^0@nSBP)Px$<4Ht8RA_#MlqLeK#7aTr#G^{zdqkt?@z4R zic*)GOE;kKA|)7`+wVWS%fwM5*6gx6P_Zi&Q1LcQtYWmeX__I=x7cjHS^D?0mx~eF zov}zZXWwoOG$3~6Z=vG#P%-|_MbY!?O9zADM`)|1*=d^X*1Nqqd-ifM!eE%4-grhG zX|Y46={<;uj4>zAq3ZuGL3HAk7UMdZU^+|e^3{vc_RB38w`VKeJm0cryE5m_Mse0) zlDS_4B_9oLVx6W>2`^NLRrg-2bRi*LDKQcewL4?+iO~v%b7EX46V_=F#d!eONf(TQ zvFBlPt;}1k+h9SKNtZj@mEptv9Uv@ruIyuVVw$FnG3Jn5uXze>5;pNlew~Skrn6)> zVQ^hSSLWQ4iz`O%sm^BmG7puP&4s{}=;n8ObF5aWShfqN6s6AHuOW3O{W>V_r@PE4 z-#Y964c3WtFP!O+%d$CY9Lo)@Q8oLV{5sin^Xq2U$&WSr+!~ViCiLBsd|wacbJnqw r^P%Smovi)+ZXJJJKPHNzC=u`j+za_o@P@Dl00000NkvXXu0mjf`7;GG literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/skull.png b/resources/sprites/halloween/skull.png new file mode 100644 index 0000000000000000000000000000000000000000..73d9ecacddb1b8cbcf50ca9e7d6026fcca1bc5c0 GIT binary patch literal 1168 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 literal 0 HcmV?d00001 diff --git a/resources/sprites/halloween/tentacle.png b/resources/sprites/halloween/tentacle.png new file mode 100644 index 0000000000000000000000000000000000000000..9fb590a66a64a0faa0296ed7c4d2da96b456526e GIT binary patch literal 2088 zcmV+@2-o+CP)Px+;z>k7RCt{2oxf`wM-<23hH$Ek4q=0WTqv&6D2Oz6AuuYgaiQuU`U?&O0#$1C z2dGgc5D4xsP;pfZE_{U%sF0c<;zpIC!XW_(qu|QdYzpaJ=EnPDX7|0@o!jrHI-ghH z+k12Ko%d#DcZmQ10001HoT%y(0O8YZbz*)!7!C280syE3-vPdSSM>>iuwm1A^K8B9 zQvm=p1o#dp!uM6500^Ih?R`2v>3jd3S)rwY$_;>eQ&m4M>N}vhAmIU`bX%R+#oW5B zPWL=V5UfX0H_~z>Bp|V1DXvI9w5exr^|GGcawXZZIZwI@G~vVFVgeX zWx6;$r{DknV?y)u*L&)I@i(-z$`i&YgI0V)(+v%&I83V_=i%x*05qzj19`fwPTXDD zpqH;-(eX*2uJ3L#jng#At<4@05$zuBO&qhc)}!aE%S1#IQ`ULfWSKdy@7vWUn`0T{ zO&T;LjJ)o;TJg1YlV%L+q?`3Q%q+K?c0YFcd>`KdfROM23A(LLytCG$w^#3TO_PoC z-R+0*d-kzx&IjB3M21;@{(4XMU+#0Y^QPBLt*moR(&yJnpHp<;3`JKfzM<)w`uw_S z?WWm}UGec900;?BGhri=GKX%f6Pp_dU1oV)t4OnoqYSf8GIg#zFHX@`brJEzGr@ z_A7*@YidcxH#A+e+XLGDxJv5alRzFMJPpNVdfSJK({oWhljp0;w6)svx&-y`tWR`i zneq|EL`2<{4cglD(=)O6EWCXEs?>lSqOMkaL(?U+n=?iFaUPn!Lkd0#ss#y816lvI zLs!D4wlu#uaaD#CgV8XeBZ_$+K$5{HZJ?xt3UvJM$7++!y~u3A;aUHGJ%ItE&bnIh z4NX@ozFNA|j6)tS{kRBPzC%hr391EmT5cd_RpfHhFcqQeexRSCAII-y#f(kgG_f4$u0uwb`Q=PnR8z&Sx+hM!QFQ>ic+H zI6mo*FN4j4r|*5ps*=kL7@_ED#Wyrvrs?hGi)%l2LECqveG*g;5}p9i*f^(Q5}FlJ z-uZGhdwqA~G<8po=IdJ}ljDF9s;*XiL(^?~yA@^DdzGg?bpT0RM?0|}1++?lm>HL9(*SMP})pP5rv*nmyb zkvd{3}KB+ZcfP5O2@Mx}=YVRwM=y2MJ86$0Gk~c%+ zCoC_`FRCPxp$*8=x?1rKO_ynUyO~Je)KJTJrjd|f=BOGPvxjH=FgW1{!P!sjt-G$4 zp=k_6JiRV;AB=CN?5{**$J#qd z_9ijSXl=XC zl2i5?gft*)=xW6`G+n0Y?M6!d*w)sXDUtR`QXDTxXxz+8BzzMMBBCgYoW7syalXge z$Jc5}OJmu|>==?iTzY(JF>h*3B+x>>e5rpGmZiD__dFRt38 zt9f2xkR&8st@wtfOK7(VZRvh&Bk4P&=#!e`1qqIuQ4~dS9LGrsMcVtJQ7GZ*wmPEw zU`Q!rH)l#DD~p}A-o(8sB+P+d+cA*pZ1$RT+2oIP&E$-XSQOPX_Yz1}g<6;KQa}T; z<^ZR4Ide$5XtxJ6`>}@akg`uoj~BMS2ll2Uv_(?z?b>y|~^cQkxb zdc3gprN_-#$2&mgI-XS4XRi&G(dDVPr1i$EDZ3))X=_Vs7S%StW1hZiOnfxWbM}e1 z%elJf_-Gc<_Fc<%(a!qarfKHI*8YFAn_G;1d_tq$l0L&l*HzC|(^pqBzOLt7vX}IA?x`vSWRcPFZbV|Dz%a4*&oF0A?4Bi46b%0000m1^xr|i+d`< SMA}IJ0000Px?g-Jv~RCt{2U0q0=R~mlO?N+E_E+iD=&xIrdgNQOD2wsT7XpvFW4WS$3nvnJ; zfrJ<~Y$Y2gq{Z$EJ3%42X(dTb+Oh-`8#R(qW@3Q@wUhwV~cdj@KP=f@dr1;&!xW5IkJD-*(ojYw^eUssH%S-cs zM~+OKoG%iY1^|3=>Lbj~&H(`0+k@g~f|vY+&d`S_dhZ?GGj}KNd&ZZIpYS?}B#%72 z6c65Kult!yy-4R%=w26bwYu2nqP^UQNgGt$RzEN6gJzt^Ev&2h61ppiIE#2?8?mWOiUz-pT5-z&}B8$~m0h9_p)|{u;hWVnvf@rjB4D0!_FerD{%ug9M92V|Zj7Ll;kp z=XjLGMT;UIyHSrU&|H`)sw4dT{1@@_Kwld+;#)#QoEZ7diRm;6F2N|}YEV0dQHbe`Z4!#5x#>}8KUJ%u&C2_C-3W=HJRGM z%E~kGyWd}np3X)7L7<`8lg~^=-}|kH~`@Ap@8oB zWNHT`#YONPtiq$mQ4I98iFVi#ELp7Rz0f9^CYbn=sT}|i{pJQ@*T_k%xG0eT)42cq z{1=p#mLiczV4$x}$w#o`Tr|%lROygbS4spIPaFjN3^h%TptH5$5x~5#Q3; z5j0yOTeM@xvS{%BQbYv+(Zw}@iOAsjGrBff<&`5V>f58oQM5D%1V8yGaq`T?PK3u( zM;c#Q90LspbbSQ#88{HGca1t;SKlN$O-|!GScT}~8WM>FDk`eP^NBZN&X#J7}DCx=q72&9(Osp`ry#8x+vNB}?mlv&5BsHhSv2c>3mh;0Sj`AC7O z4RUlx;HhG^8jKO-TpKKee)2S$@%+%mQ@ZD!2nRIhqau|IpuawV@$%sQ$ZtpatmM0UPRae#A|aU z#YMu04j&4jq__yfBjY%JtQ*io?61Rr%-G7fsBs& z{k149Efvuf5u5EOW&=+{DYPspE)tz2aN%$&Rx)J4QT3M)iA-nIf9xU@>VofJ6|RpC z38zY?b~1!=W#t*BW)`r#G>_`avX{}0i!tV6HPF|F{pI^~>B7p&GYpT6V`^prSH1}A z`Wgy#A-2AaBfTA#w$3^DZu0)}eJCj|5_~Hw&*1mh!tbxe@nhW>9vMeVa{%2(FQB@z z?A1n$4X5VwbL-9nOwBCl1d@1TtDErqYq1gELZIP*uGZrOJgVbjMR@WwD!BP`F!3Fu z!>qE+@+^hYFfNXeYFT{O9S$;w*!ng?p)RyE2SijCU0g#lwWH(Z!gc%Gdq}2s5NvJ0 z?Cc!mI<5?5geA7EHI;@IuJbUjy0T1{i$V(R2~M{A$q=a+c;$;Qz(lLMvP?u&d}F{@ zlUdiX%6p=}OYE-DM2D|l6ZJ7jx%WnV>s9#8b_wBf7wz=9VO$>_62^D5mC!A%R3-3WT;KmW}TNm`gVCwJiE$GQ<+T+^kf z&>Y)J#G^u>;Q(T*n;8-Nlc!Pm{k4cLt_f$>i_WXhFpBVKCsK~Kr)Cy}Sjkxe{hdT3 zeDxZ92djj5@qSvZQSze%6tQx#^_^UmwXR>zn6ObY|Ahw&(u`b{Yz-@M8uRxpdO z?oQr^uVybop)Q0%UD$|k39*7E6!O1;zBaLA#v5!0C;Geg&?GG{&0~3K9zC6n=;>_4 zqsLJ^dK}diENR83T8yd)ZHJqF_SNjg_0gf1;rZ$&qKj*~6`7(NT2*A@Or~C>tz7Hi z{iP_2(9_w7WNJr58eFVs9B6*{=UFvqTG2=_Xk3%2os7*5Zs=5$=FyH-%tU?=Ka&8F zlbUhTVpUh)POM{|set#`0Dyl@?d!Vlk z*G4ai4Z7LcIa5x{`9I%v;NZ@xf}3+msxx3<`MFse-125S&cOwlcC83JEwv&Z@+|^d z;h?Rw1bJtY+Tis37x8j~<3 zw|lff-c^=&lQ~pp7zswawzf)nL(IU*-5fCF;=v1;^7b?b@lt!eI7q2l<>ZJ;?x)?; z!m6uJ#BuuEFd&^{;Ri^)Tom|OG6EMCxgAv0wX@yNZwhdsByetOAKy8X7Y8ST#kbt~ zA!M?f)8~eD+wFD_R2m%@QI$<7qKd6ppPt;~)jhX#IxRlucgHRxkw}O%=9{lS z%gG%v-cQxF27*^tIgGAA5qNknN1brE`t#G++;9o0<#o5!@h$FonIq9QHAUP;KRi)gp;l#4Im_@HV zC6?jE)e$HPyhcZG+$;=65eHql;-Y1AZ#9?SK%%lS<(4x~QBU=O}b8}uk9$xh~+tCkx0v&mnZVy%BD&>-g$a>E zS(Pw4{cJNnUVwyFq|Al!@^M!gaIQF2M1xhcz;>3v84X2y$r&94we)oCK9rwzYH`4rK zZmvYqh+DR)eDxV@tS7(we2>$Es7|=8`jMBBPOf|@U%Zab?c~$AWnS71G<%PgNw!ks zu)}HfbFJ1^>~MMk>Tf> = { [FxType.MiniFire]: { - url: miniFire, + url: minifireGreen, frameWidth: 7, frameCount: 6, frameDuration: 100, @@ -37,28 +43,28 @@ const ANIMATED_SPRITE_CONFIG: Partial> = { originY: 11, }, [FxType.MiniSmoke]: { - url: miniSmoke, - frameWidth: 11, - frameCount: 4, - frameDuration: 120, + url: ghost, + frameWidth: 10, + frameCount: 5, + frameDuration: 100, looping: true, - originX: 2, + originX: 4, originY: 10, }, [FxType.MiniBigSmoke]: { - url: miniBigSmoke, - frameWidth: 24, - frameCount: 5, + url: bats, + frameWidth: 21, + frameCount: 6, frameDuration: 120, looping: true, originX: 9, originY: 14, }, [FxType.MiniSmokeAndFire]: { - url: miniSmokeAndFire, + url: miniSmokeAndFireGreen, frameWidth: 24, frameCount: 5, - frameDuration: 120, + frameDuration: 90, looping: true, originX: 9, originY: 14, @@ -90,15 +96,6 @@ const ANIMATED_SPRITE_CONFIG: Partial> = { originX: 9, originY: 9, }, - [FxType.BuildingExplosion]: { - url: buildingExplosion, - frameWidth: 17, - frameCount: 10, - frameDuration: 70, - looping: false, - originX: 8, - originY: 8, - }, [FxType.SinkingShip]: { url: sinkingShip, frameWidth: 16, @@ -108,14 +105,23 @@ const ANIMATED_SPRITE_CONFIG: Partial> = { originX: 7, originY: 7, }, - [FxType.Nuke]: { - url: nuke, - frameWidth: 60, - frameCount: 9, + [FxType.BuildingExplosion]: { + url: buildingExplosion, + frameWidth: 17, + frameCount: 10, frameDuration: 70, looping: false, - originX: 30, - originY: 30, + originX: 8, + originY: 8, + }, + [FxType.Nuke]: { + url: skullNuke, + frameWidth: 42, + frameCount: 19, + frameDuration: 50, + looping: false, + originX: 20, + originY: 21, }, [FxType.SAMExplosion]: { url: SAMExplosion, @@ -127,16 +133,51 @@ const ANIMATED_SPRITE_CONFIG: Partial> = { originY: 19, }, [FxType.Conquest]: { - url: conquestSword, - frameWidth: 21, - frameCount: 10, + url: skull, + frameWidth: 14, + frameCount: 14, frameDuration: 90, looping: false, - originX: 10, - originY: 16, + originX: 7, + originY: 23, + }, + [FxType.Tentacle]: { + url: tentacle, + frameWidth: 22, + frameCount: 26, + frameDuration: 90, + looping: false, + originX: 13, + originY: 28, + }, + [FxType.Shark]: { + url: shark, + frameWidth: 25, + frameCount: 14, + frameDuration: 90, + looping: false, + originX: 13, + originY: 8, + }, + [FxType.Bubble]: { + url: bubble, + frameWidth: 22, + frameCount: 13, + frameDuration: 80, + looping: false, + originX: 13, + originY: 8, + }, + [FxType.Tornado]: { + url: tornado, + frameWidth: 30, + frameCount: 10, + frameDuration: 80, + looping: true, + originX: 11, + originY: 22, }, }; - export class AnimatedSpriteLoader { private animatedSpriteImageMap: Map = new Map(); // Do not color the same sprite twice diff --git a/src/client/graphics/SpriteLoader.ts b/src/client/graphics/SpriteLoader.ts index 29d5b7791..fdc3a3c14 100644 --- a/src/client/graphics/SpriteLoader.ts +++ b/src/client/graphics/SpriteLoader.ts @@ -1,6 +1,6 @@ import { Colord } from "colord"; -import atomBombSprite from "../../../resources/sprites/atombomb.png"; -import hydrogenBombSprite from "../../../resources/sprites/hydrogenbomb.png"; +import miniPumpkin from "../../../resources/sprites/halloween/miniPumpkin.png"; +import pumpkin from "../../../resources/sprites/halloween/pumpkin.png"; import mirvSprite from "../../../resources/sprites/mirv2.png"; import samMissileSprite from "../../../resources/sprites/samMissile.png"; import tradeShipSprite from "../../../resources/sprites/tradeship.png"; @@ -26,8 +26,8 @@ const SPRITE_CONFIG: Partial> = { [UnitType.TransportShip]: transportShipSprite, [UnitType.Warship]: warshipSprite, [UnitType.SAMMissile]: samMissileSprite, - [UnitType.AtomBomb]: atomBombSprite, - [UnitType.HydrogenBomb]: hydrogenBombSprite, + [UnitType.AtomBomb]: miniPumpkin, + [UnitType.HydrogenBomb]: pumpkin, [UnitType.TradeShip]: tradeShipSprite, [UnitType.MIRV]: mirvSprite, [TrainTypeSprite.Engine]: trainEngineSprite, diff --git a/src/client/graphics/fx/ConquestFx.ts b/src/client/graphics/fx/ConquestFx.ts index 7fa8d0690..2c3f50413 100644 --- a/src/client/graphics/fx/ConquestFx.ts +++ b/src/client/graphics/fx/ConquestFx.ts @@ -26,7 +26,6 @@ export function conquestFxFactory( x, y, FxType.Conquest, - 2500, ); const fadeAnimation = new FadeFx(swordAnimation, 0.1, 0.6); conquestFx.push(fadeAnimation); diff --git a/src/client/graphics/fx/Fx.ts b/src/client/graphics/fx/Fx.ts index d4b206614..fa843de81 100644 --- a/src/client/graphics/fx/Fx.ts +++ b/src/client/graphics/fx/Fx.ts @@ -16,4 +16,8 @@ export enum FxType { UnderConstruction = "UnderConstruction", Dust = "Dust", Conquest = "Conquest", + Tentacle = "Tentacle", + Shark = "Shark", + Bubble = "Bubble", + Tornado = "Tornado", } diff --git a/src/client/graphics/fx/SpriteFx.ts b/src/client/graphics/fx/SpriteFx.ts index 2926121a8..ebe8d410c 100644 --- a/src/client/graphics/fx/SpriteFx.ts +++ b/src/client/graphics/fx/SpriteFx.ts @@ -19,6 +19,35 @@ function fadeInOut( return 1 - f * f; } } +/** + * Move a sprite around + */ +export class MoveSpriteFx implements Fx { + private originX: number; + private originY: number; + constructor( + private fxToMove: SpriteFx, + private toX: number, + private toY: number, + private fadeIn: number = 0.1, + private fadeOut: number = 0.9, + ) { + this.originX = fxToMove.x; + this.originY = fxToMove.y; + } + + renderTick(duration: number, ctx: CanvasRenderingContext2D): boolean { + const t = this.fxToMove.getElapsedTime() / this.fxToMove.getDuration(); + this.fxToMove.x = Math.floor(this.originX * (1 - t) + this.toX * t); + this.fxToMove.y = Math.floor(this.originY * (1 - t) + this.toY * t); + ctx.save(); + ctx.globalAlpha = fadeInOut(t, this.fadeIn, this.fadeOut); + const result = this.fxToMove.renderTick(duration, ctx); + ctx.restore(); + return result; + } +} + /** * Fade in/out another FX */ @@ -49,8 +78,8 @@ export class SpriteFx implements Fx { protected waitToTheEnd = false; constructor( animatedSpriteLoader: AnimatedSpriteLoader, - protected x: number, - protected y: number, + public x: number, + public y: number, fxType: FxType, duration?: number, owner?: PlayerView, diff --git a/src/client/graphics/layers/FxLayer.ts b/src/client/graphics/layers/FxLayer.ts index e5ddf3831..94a9c1040 100644 --- a/src/client/graphics/layers/FxLayer.ts +++ b/src/client/graphics/layers/FxLayer.ts @@ -13,7 +13,7 @@ import { AnimatedSpriteLoader } from "../AnimatedSpriteLoader"; import { conquestFxFactory } from "../fx/ConquestFx"; import { Fx, FxType } from "../fx/Fx"; import { nukeFxFactory, ShockwaveFx } from "../fx/NukeFx"; -import { SpriteFx } from "../fx/SpriteFx"; +import { FadeFx, MoveSpriteFx, SpriteFx } from "../fx/SpriteFx"; import { TargetFx } from "../fx/TargetFx"; import { TextFx } from "../fx/TextFx"; import { UnitExplosionFx } from "../fx/UnitExplosionFx"; @@ -21,6 +21,8 @@ import { Layer } from "./Layer"; export class FxLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; + private lastRandomEvent: number = 0; + private randomEventRate: number = 8; private lastRefresh: number = 0; private refreshRate: number = 10; @@ -40,6 +42,14 @@ export class FxLayer implements Layer { } tick() { + if (!this.game.config().userSettings()?.fxLayer()) { + return; + } + this.lastRandomEvent += 1; + if (this.lastRandomEvent > this.randomEventRate) { + this.lastRandomEvent = 0; + this.randomEvent(); + } this.manageBoatTargetFx(); this.game .updatesSinceLastTick() @@ -116,6 +126,72 @@ export class FxLayer implements Layer { this.allFx.push(textFx); } + randomEvent() { + const randX = Math.floor(Math.random() * this.game.width()); + const randY = Math.floor(Math.random() * this.game.height()); + const ref = this.game.ref(randX, randY); + if (this.game.isOcean(ref) && !this.game.isShoreline(ref)) { + const animation = Math.floor(Math.random() * 4); + if (animation === 0) { + const fx = new SpriteFx( + this.animatedSpriteLoader, + randX, + randY, + FxType.Shark, + ); + this.allFx.push(fx); + } else if (animation === 1) { + const fx = new SpriteFx( + this.animatedSpriteLoader, + randX, + randY, + FxType.Bubble, + ); + this.allFx.push(fx); + } else if (animation === 2) { + const fx = new MoveSpriteFx( + new SpriteFx( + this.animatedSpriteLoader, + randX, + randY, + FxType.Tornado, + 6000, + ), + randX - 40, + randY, + 0.1, + 0.8, + ); + this.allFx.push(fx); + } else if (animation === 3) { + const fx = new FadeFx( + new SpriteFx( + this.animatedSpriteLoader, + randX, + randY, + FxType.Tentacle, + ), + 0.1, + 0.8, + ); + this.allFx.push(fx); + } + } else { + const ghost = new FadeFx( + new SpriteFx( + this.animatedSpriteLoader, + randX, + randY, + FxType.MiniSmoke, + 4000, + ), + 0.1, + 0.8, + ); + this.allFx.push(ghost); + } + } + onUnitEvent(unit: UnitView) { switch (unit.type()) { case UnitType.TransportShip: { diff --git a/src/core/Util.ts b/src/core/Util.ts index c5cbe044e..41bac4163 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -289,17 +289,17 @@ export function createRandomName( } export const emojiTable = [ - ["😀", "😊", "🥰", "😇", "😎"], + ["😀", "😊", "😇", "😎", "😈"], ["😞", "🥺", "😭", "😱", "😡"], - ["😈", "🤡", "🖕", "🥱", "🤦‍♂️"], - ["👋", "👏", "🤌", "💪", "🫡"], + ["⏳", "🥱", "🤦‍♂️", "🖕", "🤡"], + ["👋", "👏", "👻", "💪", "🎃"], ["👍", "👎", "❓", "🐔", "🐀"], - ["🤝", "🆘", "🕊️", "🏳️", "⏳"], + ["🆘", "🤝", "🕊️", "🏳️", "🛡️"], ["🔥", "💥", "💀", "☢️", "⚠️"], ["↖️", "⬆️", "↗️", "👑", "🥇"], ["⬅️", "🎯", "➡️", "🥈", "🥉"], ["↙️", "⬇️", "↘️", "❤️", "💔"], - ["💰", "⚓", "⛵", "🏡", "🛡️"], + ["💰", "🏭", "🚂", "⚓", "⛵"], ] as const; // 2d to 1d array export const flattenedEmojiTable = emojiTable.flat(); diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index d40509e1c..5664c41bb 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -18,7 +18,7 @@ export class PastelTheme implements Theme { private nationColorAllocator = new ColorAllocator(nationColors, nationColors); private background = colord({ r: 60, g: 60, b: 60 }); - private shore = colord({ r: 204, g: 203, b: 158 }); + private shore = colord({ r: 223, g: 187, b: 132 }); private falloutColors = [ colord({ r: 120, g: 255, b: 71 }), // Original color colord({ r: 130, g: 255, b: 85 }), // Slightly lighter @@ -26,8 +26,8 @@ export class PastelTheme implements Theme { colord({ r: 125, g: 255, b: 75 }), // Warmer tint colord({ r: 115, g: 250, b: 68 }), // Cooler tint ]; - private water = colord({ r: 70, g: 132, b: 180 }); - private shorelineWater = colord({ r: 100, g: 143, b: 255 }); + private water = colord({ r: 80, g: 76, b: 179 }); + private shorelineWater = colord({ r: 100, g: 110, b: 255 }); private _selfColor = colord({ r: 0, g: 255, b: 0 }); private _allyColor = colord({ r: 255, g: 255, b: 0 }); @@ -97,15 +97,15 @@ export class PastelTheme implements Theme { } case TerrainType.Plains: return colord({ - r: 190, - g: 220 - 2 * mag, - b: 138, + r: 216, + g: 205 - 2 * mag, + b: 127, }); case TerrainType.Highland: return colord({ - r: 200 + 2 * mag, - g: 183 + 2 * mag, - b: 138 + 2 * mag, + r: 223 + 2 * mag, + g: 187 + 2 * mag, + b: 132 + 2 * mag, }); case TerrainType.Mountain: return colord({ diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index 868d55f74..2b914db6a 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -20,7 +20,7 @@ const EMOJI_ASSIST_ACCEPT = (["👍", "⛵", "🤝", "🎯"] as const).map(emoji const EMOJI_RELATION_TOO_LOW = (["🥱", "🤦‍♂️"] as const).map(emojiId); const EMOJI_TARGET_ME = (["🥺", "💀"] as const).map(emojiId); const EMOJI_TARGET_ALLY = (["🕊️", "👎"] as const).map(emojiId); -export const EMOJI_HECKLE = (["🤡", "😡"] as const).map(emojiId); +export const EMOJI_HECKLE = (["👻", "🎃"] as const).map(emojiId); export class BotBehavior { private enemy: Player | null = null;