`((.lVqÙÈ¿ù‚„°©ä¬Ìä³ãÚþªä‡¨‰°ë“éõÿæÆÞ£‹ÿÄÿ÷ ÿ÷ä((.lVq((.ù‚„°©ä¬Ìä³ãÚþªä‡¨‰°ë“éõÿæÆÞ£‹ÿÄÿ÷ ÿ÷ä 0ÿÿÿÿÿÿÿÿ2Tv˜ºÜþïÍ«‰gE#2Tv˜ºÜþ2Tv˜ºÜþ`UUUUeeVVUUUUeUUVeUUVUUUUeeVVUUUU""""22##""""2""#2""#""""22##""""ÌÌÌÌllÆÆÌÌÌÌlÌÌÆlÌÌÆÌÌÌÌllÆÆÌÌÌÌwwwwggvvwwwwgwwvgwwvwwwwggvvwwww ðððÿÿÿÿÿ?ÿóð?ÿóÿòÿ/ÿ/"ÿÿÿ?ÿ ?ÿó"ÿÿÿ"ÿÿ/ð""ÿÿÿÿÿÿÿÿÿ```fffff6fc`6fcfefVfVUfff6fP6fcUfffUffF`UUfffffffffpppwwwww7wsp7wswtwGwGDwww7w@7wsDwwwDwwGpDDwwwwwwwww   """""2"# 2"#","Â"ÂÌ """2"À2"#Ì"""Ì"" ÌÌ """""""""wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwÿðÿð?ÿóð?ÿóÿÿÿÿÿÿÿÿÿÿÿÿÿf`f`6fc`6fcfffffffffffffD@D@4DC@4DCDDDDDDDDDDDDD" " 2"# 2"#"""""""""""""wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww www wwwwwwðððÿòÿÿÿ?ÿóò?ÿóòòÿ/ÿ/"ÿÿÿwwwwpwwwpwwwpwwwpwwwpwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww?ÿ ?ÿó"ÿÿÿ"ÿÿÿð"""ÿÿÿÿÿÿÿÿÿðððÿòÿÿÿ?ÿóÿ?ÿóÿòÿ/ÿ/"ÿÿÿÿðÿð?ÿóð?ÿóÿÿÿÿÿÿÿÿÿÿÿÿÿwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww www wwwwwwðððÿòÿÿÿ?ÿóò?ÿóòòÿ/ÿ/"ÿÿÿwwwwpwwwpwwwpwwwpwwwpwwwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww€™˜Ù ™Ý ÙííÀÜÝÀÝ ÜÀ  à ############################################################ð ! #############'.///////////////  P01234 5 6 7 8 9:<=>????????????????ðàààð  000 #ð  tP p p ` ` P P @ @ 0 0! ! !""""ð$ð$à$à$Ð$Ð$À$À%°%°' ) **b  tPpppppppppppppr t t u v vwwwxÿxÿyÿzïzï{ï{ß|ß}ß}ß~ßߺpppŠpp†pppprttuvvwwwxxyzz{{||||}=àc c c cc c c cc c c cc cƒ c c c cc ccccc Ia  a  a @ " " " " " """"€P€Ñ€±€Ñ€€PøÑ€Ñ€±€Ñ€€P€Ñ€€±€Ñ€€PøÑ€Ñ€±€P€€±€P+cc c c c c c c c c c c c c c cc cc c#c " " " " " " " " " """ " " " "" """""€P€Ñ€P€Ñ€€PøÑ€Ñ€P€P€€P€Ñ€€P€Ñ€€PøÑ€Ñ€P€P€€±+cc c c c c c c c c c c c c c cc cc€P€Ñ€P€Ñ€€PøÑ€Ñ€P€P€€P€Ñ€€P€Ñ€€PøÑ€Ñ€±€P€€± Ia a a a a aa Ia a ` a ` `€ a/cc c c cc c c cc c c cc cƒ c$cƒ c c cƒ c c cƒ c c cƒ cƒ c&cƒ c c cƒ c c cƒ c c cƒ cƒƒ)cƒ c ƒ cƒ cc cƒ ccƒc tcc c c c c c c c cƒc cc c c c c c c c cƒc c&cƒ c c cƒ c c cƒ c c cƒ cƒƒ)cƒ c ƒ cƒ cc cƒ ccƒc tc&cƒ c c cƒ c c cƒ c c cƒ cƒƒ)cƒ c ƒ cƒ cc cƒ ccƒc tƒ€P€€Ñ€Ñ€±€€Ñ€Ñ€P€€Ñ€Ñ€±€€Ñ€Ñ€±€P€€Ñ€Ñ€±€€Ñ€Ñ€P€€Ñ€Ñ€±€€Ñ€Ñ€±€±˜000 000 ` `(` `(` `(` `(â x|â â À?UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÝÝÝÝÝÝÝÝÝÝÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU]UUÕÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUµ»»»ÛÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝUUUUUUUUUUUUUÕÝÝÝÝÝÝÝÝÝÝÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»»»»»ÛÝÝÝݽ»»»»»»»»»»»»»»»»»»»»»»»»»»[UUUUUUUUUUUUUUUUUUUUÕÝÝÝÝÝÝÝÝÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»»»»»»»»ÝÝ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»[UUUUUUUUUUUUUUUUUUUUUUÝÝÝÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUµ»»»»»»»»»»»»»»»»»»»Ýݽ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»UUUUUUUUUUUUUUUUUUUUUUUÕÝÝÝÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»»»»»»»»»»Ûݽ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»[UUUUUUUUUUUUUUUUUUUUUUUÝÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»»»»»»»»»»»ÝÝ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»[UUUUUUUUUUUUUUUUUUUUUUUÕÝÝÝÝUUUUUUUUUUUUUUUUUUUUUUUUUUUµ»»»»»»»»»»»»»»»»»»»»ÛÝ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»UUUUUUUUUUUUUUUUUUUUUUUUUÝÝÝ]UUUUUUUUUUUUUUUUUUUUUUUUUU»»»»»»»»»»»»»»»»»»»»»Ý½»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»[UUUUUUUUUUUUUUUUUUUUUUUUUÕÝÝUUUUUUUUUUUUUUUUUUUUUUUUUUµ»»»»»»»»»»»»»»»»»»»ÛÝ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»UUUUUUUUUUUUUUUUUUUUUUUUUUUÕÝUUUUUUUUUUUUUUUUUUUUUUUUUU"»»»»»»»»»»»»»»»»»»»Ý½»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»+RUUUUUUUUUUUUUUUUUUUUUUUUUUUÝ]UUUUUUUUUUUUUUUUUUUUUUUUU%"»»»»»»»»»»»»»»»»»ÛÝ»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»+"UUUUUUUUUUUUUUUUUUUUUUUUUUUUÕÝUUUUUUUUUUUUUUUUUUUUUUffff""²»»»»»»»»»»»»»»»Ý½»»;3333³;3333³;3333³»»;33³;33333333³»»;333333cff63333cff633c633333333cffÖÝffffffffffffffffffffffUUUUU""""»»»»»»»»»»»»»Ý½»»;DDDD³;DDDD³;DDDD³»»;DD³;DDDDDDDD³»»;DDDDDDSUU5DDDDSUU5DDS5DDDDDDDDSUUUÝ]UUUUUUUUUUUUUUUUUUUUUUUUUUU%"""""»»»»»»»»»ÛÝ»»1DDDD1DDDD1DDDD³»1DD1DDDDDDDD#"1DDDDDDSU1DDDDSU1DD1DDDDDDDDSUUUÕÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU""""""""»»»»Ý½»»1DDDD1DDDD1DDDD³»1DD1DDDDDDDD#"1DDDDDDSU1DDDDSU1DD1DDDDDDDDSUUUÕÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU""""""""ÒÝ""²1DDDD33DDDD1DDDD³»1DD1DDDDDDDDS533DDDDDD331DDDD331DD1DDDDDDDDSUUUÕÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"""Ý-"""1DDDDDDDDDD1DDDD#"1DD133DDDD33S5DDDD3333DD1DDDDDD1DD133DDDD33SUUUUÝ]UUUUUUUUUUUUUUUUUUUUUUUUUQUUUUUÕÝUUU%1DDDDDDDDDD1DDDD#"1DD1DDDDQ1DDDD1DD1DDDDDD1DD1DDDDQUUUUUÝ]UUUUUUUQUUUUUUUUUUU7wQU""QUUUUUÝ]UUUU1DDDDDDDDDD1DDDDSU1DD1DDDDQ1DDDD1DD1DDDDDD1DD1DDDDQUUUUUÕÝUUUUUUU1"#UUUUUUUUUUA7wsQU!!"QUUUUÕÝUUUUU1DDDDDDDDDD1DDDDSU1DDSU1DDDDSU1DDDDSU1DD1DDDDDD33DDSU1DDDDSUQUÝ]UUUUUU2"#QUUUffDwwwaf!""afffÖÝmfffff1DDDDDDDDDD1DDDDcf1DDcf1DDDDcf1DDDDcf1DD1DDDDDDDDDDcf1DDDDcfwwfÝmffffff"""Ì""fffUUDwwGQU!#2QUUUÝÝ]UUUUU1DDDDDDDDDD1DDDDSU1DDSU1DDDDSU1DDDDSU1DD1DDDDDDDDDDSU1DDDDSUwqUÝ]UUUUUU,""Ì"!UUUUUqDDQU!#2"UUÕÝÝUUUUUU1DDDDDDDDDD1DDDDSU1DDSU1DDDDSU1DDDDSU1DD1DDDDDDDDDDP1DDDDSUqwwUÝ]UUUUUUÁÌÌ!""UUUUUwwwUUÁ"",UUÝ]UUUUUUU1DDDDDDDDDD1DDDDSU1DDSU1DDDDSU1DDDD3333DD1DDDDDDDDDDó1DDDDSUqs7UÕÝUUUUUU!!"""!#2UUUUUwwwUUÌÌ"UUÝ]UUUUUUU1DD33DD33DD1DDDDSU1DDSU1DDDDSU1DDDDDDDDDD1DDDD33DDDDó1DDDDSUws7UÕÝUUUUUU!!""""#2UUUffwwwff"""ffÝmfffffff1DD1DD1DD1DDDDcf1DDcf1DDDDcf1DDDDDDDDDD1DDDD1DDDDó1DDDDcfqGwwfÐÝ!!"""!Â""fffUUUUUUÝ]UUUUUUU1DD1DD1DD1DDDDSU1DDSU1DDDDSU1DDDDDDDDDD1DDDD1DDDD31DDDDSUqwDDUÐÝðqq!"ÌÌUUUUUUUUUUUUUUUUUUUÝ]UUUUUUU1DD1DD1DD1DDDD3333DDSU1DDDDSU1DDDDDDDDDD1DDDD1DDDD31DDDDSUqwwwQUÐÝÿqwwQUUUU!"""UUUffffffffffffffffÝmfffffff1DD1331DD133DDDDDD33cf1DDDDcf1DDDD3333DD1DDDD133DDó1DDDDcfafÐÝÿÿwwwaffffaffUUUUUUUUUUUUUUUUÝ]UUUUUUU1DDQ1DD1DDDDDD!QU1DDDDSU1DDDD1DD1DDDD1DD#1DDDDSUUUUUUUÐÝÿó7wsQUUUU,"Â"QUUffffffffffffffffÝmfffffff1DDa1DD1DDDDDD!af1DDDDcf1DDDD1DD1DDDD1DDó`1DDDDcffffffðÝýq7wsaffffÁÌ,"affUUUUUUUUUUUUUUUUÝ]UUUUUUU1DDSUUU1DDS1DDDDDD##QU1DDDDSU1DDDDSU1DD1DDDDSU1DDP1DDDDSUUUUUUÿÝýwtwGQUUUUU!"""QUUffffffffffffffffÝmfffffff133cfff133cf1333333##af13333cf13333cf13313333cf133cf13333cffffffÿÝ-wGDafffffaffffffffffffffffffÝmfffffffaffffaff!"ÂafaffaffaaffaffafffffffÿßÝwwwfffffffffffffUUUUUUUUUUUUUUUÕÝUUUUUUUUQUUUUQUÁÌQUQUUQUUQQUUQUUQUUUUUUUÐÝUUUUUUUUUUUUUfffffffffffffffÖÝfFDDDDDDDDdffFDDDDdf@DDFDDDD$fFDDdFDDDDdffFDDdFDDDDDDDDdFDDDDDDDDDDdffFDDDDDDDDdÖÝfffffffffffffffffffffffffffffffffÖÝfF»»»»»»»»dffF»»»»dfO»»F»»»»fF»»dF»»»»dffF»»dF»»»»»»»»dF»»»»»»»»»»dffF»»»»»»»»dfÝmffffffffffffffffffffffffffffffffÝmA»»»»»»»»fA»»»»dfA»»A»»»»dfA»»A»»»»dfA»»A»»»»»»»»A»»»»»»»»»»dfA»»»»»»»»dfÝmffffffffffffffffffffffffffffffffÝmA»»»»»»»»fA»»»»dfA»»A»»»»dfA»»A»»»»dfA»»A»»»»»»»»A»»»»»»»»»»dfA»»»»»»»»dfÝmfffffffffffffffffUUUUUUUUUUUUUUÕÝUA»»»»»»»»DDA»»»»TUA»»A»»»»DDA»»A»»»»DDA»»A»»»»»»»»A»»»»»»»»»»TEDD»»»»»»»»TUÝ]UUUUUUUUUUUUUUUUUffffffffffffffÖÝfA»»»»DDDD»»A»»»»dfA»»A»»»»»»A»»A»»»»»»A»»ADD»»»»DDA»»»»DDDDDDdF»»»»»»DDDDdfÖÝfffffffffffffffffffffffffffffffÝmfA»»»»A»»A»»»»dfA»»A»»»»»»A»»A»»»»»»A»»A»»»»aA»»»»aA»»»»»»affÖÝfffffffffffffffffffffffffffffffÝmfA»»»»A»»A»»»»dfA»»A»»»»»»A»»A»»»»»»A»»A»»»»aA»»»»aA»»»»»»afffÝmffffffffffffffffffffffffffffffÝmfA»»»»DDDD»»A»»»»dfA»»A»»»»»»DD»»A»»»»»»DD»»dfA»»»»dfA»»»»DDDDdfA»»»»»»DDtafffÖÝfffffffffffffffffffffffffffffÖÝffA»»»»»»»»DDA»»»»dfA»»A»»»»»»»»»»A»»»»»»»»»»dfA»»»»dfA»»»»»»»»dfADD»»»»»»tafffÖÝfffffffffffffffffffffffffffffÖÝffA»»»»»»»»aA»»»»dfA»»A»»»»»»»»»»A»»»»»»»»»»dfA»»»»dfA»»»»»»»»dfA»»»»»»tafffÖÝfffffffffffffffffffffffffffffÖÝffA»»»»»»»»aA»»»»dfA»»A»»»»»»»»»»A»»»»»»»»»»dfA»»»»dfA»»»»»»»»dfA»»»»»»afffÖÝfffffffffffffffffffffffffffffÖÝffA»»»»»»»»DDA»»»»dfA»»A»»»»»»»»»»A»»»»»»»»»»dfA»»»»dfA»»»»»»»»dfffA»»»»»»DDdfffÝmfffffffffffffffUUUUUUUUUUUUUÕÝUUA»»»»DDDD»»A»»»»TUA»»A»»»»DD»»»»A»»»»DD»»»»TUA»»»»TUA»»»»DDDDTUUUADD»»»»»»TUUUÝ]UUUUUUUUUUUUUUUfffffffffffffÖÝffA»»»»A»»A»»»»dfA»»A»»»»A»»»»A»»»»A»»»»dfA»»»»dfA»»»»affffA»»»»»»dfffÝmffffffffffffffffffffffffffffÖÝffA»»»»A»»A»»»»dfA»»A»»»»A»»»»A»»»»A»»»»dfA»»»»dfA»»»»affffA»»»»»»dfffÝmffffffffffffffffffffffffffffÖÝffA»»»»DDDD»»A»»»»DDDD»»A»»»»A»»»»A»»»»A»»»»dFDD»»»»DDA»»»»DDDDDDdFDDDD»»»»»»dfffÝmffffffffffffffffffffffffffffÖÝffA»»»»»»»»DDADD»»»»»»DDA»»»»ADD»»A»»»»ADD»»dF»»»»»»»»A»»»»»»»»»»dF»»»»»»»»DDdfffÝmffffffffffffffffffffffffffffÖÝffA»»»»»»»»aA»»»»»»aA»»»»A»»A»»»»A»»A»»»»»»»»A»»»»»»»»»»A»»»»»»»»affffÝmffffffffffffffffafffffffÖÝffA»»»»»»»»aA»»»»»»aA»»»»A»»A»»»»A»»A»»»»»»»»A»»»»»»»»»»A»»»»»»»»affffÝmffffffffffffffff""fffffffÖÝffA»»»»»»»»dfffA»»»»»»dfA»»»»dfA»»A»»»»dfA»»A»»»»»»»»A»»»»»»»»»»A»»»»»»»»dfffffÝmffffffffffffffff"!fffffffÖÝffADDDDDDDDdfffADDDDDDdfADDDDdfADDADDDDdfADDADDDDDDDDADDDDDDDDDDADDDDDDDDffÖÝfffffffffffffffff!""fffffffÖÝffaffffaffaffaaffaaañðffÖÝfffffffffffffffff!#2fffffffÖÝffaffffaffaffaaffaaañÿffÝmffffffffffffffffU"#2UUUUUUUÕÝUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÿÿÿUUÝ]UUUUUUUUUUUUUUUUf!Â""fffffffÖÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff?ÿófÖÝffffffffffffffffff!"ÌÌfffffffÖÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff?ÿó`Ýmffffffffffffffffff!"""afffffffÖÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffòÿ/ÿÝÝmffffffffffffffffffafffffffÖÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff "ÒÝÝÝffffffffffffffffffffffffffffffffÝÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffÐÝÝÝÝfffffffffffffffffffffffffffffffffÖÝmffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffÝÝÝÝÝ`ffffffffffffffffffffffffffffffffffÝÝmffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffÝÝÝÝÝÝÝÝÝÝÝÝmfffffffffffffffffffffffffffffffffffffÝÝffffffffffffffffffffffffffffffffffffffffffffffffffffffÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝmfffffffffffffffffffffffffffffffffffffffÖÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝffffffffffffffffffffffÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝffffffffffffffffffffffffffffffffffffffffffÖÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝmffffffffffffffffÖÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝffffffffffffffffffffffffffffffffffffffffffffffffffffÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffÖÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝmfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™iffffffffffffffffffffffffffffffffffffffffffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™iffffffffffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™if™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™ªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ªªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ª™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™™™™™™™™™™™™™™™™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªš™ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªð𠪪ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªðÿÿ ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªÿÿÿ ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª?ÿ󠪪ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª ð?ÿ󠪪ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª ÿòÿ/ ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª ÿ/" ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª ÿÿÿªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ªªªªªªªªªªªªªªªª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™©ª™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ÿÿ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™qq‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ÿð™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™qww‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ðÿÿ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™www‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ðó?™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™7ws‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÿó?™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™q7ws‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ð/ÿÿ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™wtwG‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ðÿ""™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™wGD‘™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ðÿÿÿ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™www™™™™™™™™™™™™™#¤-- title: MUTANT BUNNIES -- author: nespi -- desc: Arcade game about capturing mutant bunnies with the mouse! -- site: nespi.itch.io -- license: MIT License (change this to your license of choice) -- version: 1 -- script: lua -- input: mouse c = { black = 0, magenta = 1, beige = 2, red = 3, purple = 4, blue = 5, cyan = 6, pink = 7, darkGreen = 8, green = 9, lightGreen = 10, ligthBrown = 11, brown = 12, orange = 13, yellow = 14, white = 15 } t=0 W,H = 240,136 SCORE = 0 HIGH_SCORE = 0 HIGH_LEVEL = 0 linePoints = {} MAX_LINE_POINTS = 60 MOUSE_OFF = false markDelay = 0 markDelayTime = 1 marked = false DEFAULT_MAX_BUN = 19 MAX_BUN = 20 COUNTDOWN_TIME = 20*60 TRANSITION_TIME = 2*60 TRANSITION = false ----- GAME_STATE = 'menu' START_DELAY = 0 START_DELAY_TIME = 60*6 MUSIC = true ----- function resetGame() LEVEL = 0 SCORE = 0 MAX_BUN = DEFAULT_MAX_BUN CIRC = 0 linePoints = {} buns = {} smokeTable = {} scoreGetTable = {} -- playingSfx = {} -- fireList = {} pMeter.value = PLAY_METER_SIZE pMeter.color = c.green extraPercentage.x = pMeter.size MUSIC = true HELP_COUNT = 0 GAME_STATE = 'menu' end function mouseOffCheck() if MOUSE_OFF and not mleft then MOUSE_OFF = false end end -- mouseOffCheck palette_map = 0x3FF0 function sprOutline(i,x,y,t,s,f,r,w,h,b,col) local col = col or 0 local t = t or 0 local s = s or 1 local f = f or 0 local r = r or 0 local w = w or 1 local h = h or 1 local b = b or 1 --converts to outline color for c=0,15 do poke4(palette_map*2+c,col) end --makes outline for dx=-b,b do for dy=-b,b do spr(i,x+dx,y+dy,t,s,f,r,w,h) end end --paints the colors in the sprite for c=0,15 do poke4(palette_map*2+c,c) end spr(i,x,y,t,s,f,r,w,h) end -- sprOutline function scoreGetHUD() if #scoreGetTable > 0 then local s = scoreGetTable[#scoreGetTable] if s.points > 0 then local total = s.points if s.combo > 0 then total = total * s.combo end printOutline('+'..total,6,8,c.red,c.magenta,false,1,true) end end end function printOutline(t, x, y, c1, c2, f, s, sm) local c1 = c1 or c.brown local c2 = c2 or 0 local f = f or false local s = s or 1 local sm = sm or false for dx = -1, 1 do for dy = -1, 1 do print(t, x + dx, y + dy, c2, f, s, sm) end print(t, x, y, c1, f, s, sm) end end -- sprOutline function thickLine(x0, y0, x1, y1, color, thickness) for i = 1, thickness do -- y for j = 1, thickness do -- x if i==1 and j==1 or i==1 and j==thickness or i==thickness and j==3 or i==thickness and j==1 then goto skip end local x0,y0 = x0+j-1, y0 -i -1 local x1, y1 = x1+j-1, y1 -i -1 line(x0, y0, x1,y1,color) ::skip:: end end end function drawHUD(inOVR) inOVR = inOVR or false if inOVR then c.black = BANK2_BLACK scoreGetHUD() else c.black = 0 end printMeterBonus() drawPlayMeter() drawExtraPercentageBar() printOutline('S: '..SCORE,1,1,c.red,c.magenta,false,1,true) if LEVEL > 0 then local levelSize = print('LVL: '..LEVEL,-100,-100,c.red,false,1,true) printOutline('LVL: '..LEVEL,W-levelSize,1,c.red,c.magenta,false,1,true) end c.black = 0 end function drawEndHUD() drawPlayMeter() --- Calculate centered positions local gameOverSize = print('GAME OVER',-100,-100,c.black,false,4,false) local levelSize = print('LVL: '..LEVEL,-100,-100,c.red,false,1,true) local scoreSize = print('SCORE: '..SCORE,-100,-100,c.red,false,1,true) local gameOverPosX = (W - gameOverSize)/2 local gameOverPosY = 40 local pointsPosX = (W - scoreSize)/2 local xOffset = math.cos(t/10)*1.5 -- Prints printOutline('LVL: '..LEVEL,W-levelSize,1,c.red,c.magenta,false,1,true) printOutline('GAME OVER',gameOverPosX+xOffset-2,gameOverPosY+2,c.black,c.black,false,4,false) printOutline('GAME OVER',gameOverPosX+xOffset,gameOverPosY,c.white,c.magenta,false,4,false) printOutline('SCORE: '..SCORE,pointsPosX,70,c.red,c.magenta,false,1,true) end function BOOT() HIGH_SCORE = pmem(0) HIGH_LEVEL = pmem(1) end function TIC() -- trace(pMeter.value) --HIDE_CURSOR -- poke(0x3FFB,0) mx,my,mleft,mmiddle,mright,scrollx,scrolly = mouse() if GAME_STATE == 'menu' then MENU_STATE() elseif GAME_STATE == 'play' then if START_DELAY > 0 then cls() drawBackground() drawCloudsShadow() drawClouds() checkMarked() -- map() drawFire() if START_DELAY > 60 then local displayedDelay = math.ceil(START_DELAY/60)-1 local startCounterSize = print(displayedDelay,-100,-100,12,true,10) local startCounterX = (W - startCounterSize)/2 printOutline(displayedDelay,startCounterX-2,40+2,c.black,c.black,true,10) printOutline(displayedDelay,startCounterX,40,c.white,c.magenta,true,10) else local startCounterSize = print('GO!',-100,-100,12,true,5) local startCounterX = (W - startCounterSize)/2 printOutline('GO!',startCounterX-2,50+2,c.black,c.black,true,5) printOutline('GO!',startCounterX,50,c.white,c.magenta,true,5) end --------- for OVR effect --- drawHUD() ----------------------------- if START_DELAY%60 == 0 then local roundedDelay = math.ceil(START_DELAY/60) if roundedDelay >= 2 and roundedDelay <= 4 then sfx(0,'G-3',20,1,15) elseif roundedDelay <= 1 then sfx(0,'G-4',20,1,15) end end START_DELAY = START_DELAY - 1 playSfxTable() else PLAY_STATE() end elseif GAME_STATE == 'game_over' then GAME_OVER_STATE() end t=t+1 end timer = { started = false, startTime=0, countdown = COUNTDOWN_TIME } function displayTime() if not timer.started then timer.started = true timer.startTime = time() end -- local elapsed_seconds = (time() - timer.startTime) // 1000 -- local minutes = elapsed_seconds // 60 -- local seconds = elapsed_seconds % 60 -- tPrint = string.format("%02d:%02d", minutes, seconds) -- -- tPrint = string.format("%4d",time()) -- print(tPrint, W-7*4,0,0) timer.countdown = timer.countdown - 1 local remaining_seconds = timer.countdown//60 local minutes = remaining_seconds // 60 local seconds = remaining_seconds % 60 tPrint = string.format("%02d:%02d", minutes, seconds) print(tPrint, W-7*4,0,c.red) end HELP_COUNT = 0 MAX_HELP_COUNT = 10*60 function MENU_STATE() if MUSIC then music(2) MUSIC = false end HELP_COUNT = HELP_COUNT + 1 mouseOffCheck() checkMarked() cls() local startSize = print('START GAME', -100, -100, 12, true) local startPosX = (W - startSize) / 2 local startPosY = 100 local radius = 3 local radius1 = (t//10+2)%5 local radius2 = (t//10)%5 local circAngularSpeed = 0.06 -- Adjust the speed as needed local circOffsetX = radius * math.cos(circAngularSpeed * t) -- t is the time variable local circOffsetY = radius * math.sin(circAngularSpeed * t) local circX = W / 2 + circOffsetX*14 local circY = startPosY + 2 + circOffsetY * 4 circb(circX, circY, radius1, c.red) circb(circX, circY, radius2, c.pink) printOutline('START GAME', startPosX, startPosY+math.sin(t/10), c.white,c.magenta,true) if mget(startPosX/8, startPosY/8) == 2 and mget(startPosX/8+8, startPosY/8) == 2 then addBunnySfx() for i=1, 9 do local fire_target = { x = startPosX+((i-1)*7), y = startPosY } if i == 6 then goto skip end addFire(fire_target) ::skip:: end music() MUSIC = true START_DELAY = START_DELAY_TIME pMeter.value = PLAY_METER_SIZE extraPercentage.x = PLAY_METER_SIZE GAME_STATE = 'play' end local titleSize = print('MUTANT\nBUNNIES',-200,-200,c.white,false,4) local titlePosX = (W-titleSize)/2 local titleOffset1 = math.sin(t/10)*1.5 local titleOffset2 = math.cos(t/10)*1.5 printOutline('\tMUTANT',titlePosX-2+titleOffset1,30+2,c.magenta,c.magenta,false,4) printOutline('\nBUNNIES',titlePosX+titleOffset2-2,30+2,c.magenta,c.magenta,false,4) printOutline('\tMUTANT',titlePosX+titleOffset1,30,c.purple,c.red,false,4) printOutline('\nBUNNIES',titlePosX+titleOffset2,30,c.ligthBrown,c.purple,false,4) screenShake() mouseFunc() mouseBound() drawLines() drawFire() playSfxTable() printOutline("nespi", 222, 129, c.red,c.magenta,false,1,true) if HELP_COUNT > MAX_HELP_COUNT then local cursorTextSize = print("Drag the cursor!",-100,-100,0,false,1,true) local cursorTextX = (W-cursorTextSize)/2 printOutline("Drag the cursor!", cursorTextX, H-10, c.beige,c.magenta,false,1,true) end end function PLAY_STATE() -- update if MUSIC then music(0) MUSIC = false end -- spawnBuns() screenShake() mouseOffCheck() mouseBound() checkMarked() smokeCollision() updateBuns() mouseFunc() if not TRANSITION then playMeter() end local smokePositions = updateSmoke() -- draw cls() drawBackground() drawCloudsShadow() drawClouds() -- map() drawBuns() drawSmokeShadow(smokePositions) drawSmoke(smokePositions) drawLines() drawFire() drawScoreGet() addSfx() playSfxTable() if TRANSITION then transitionAnimation() end if pMeter.value <= 0 then MUSIC = true GAME_STATE = 'game_over' elseif #buns == 0 and LEVEL > 0 then TRANSITION = true sfxTransition() spawnBuns() checkMarked() elseif #buns == 0 then checkMarked() spawnBuns() end -- print('mx: '..(mx//8)..'- my: '..my//8) end function newMeterBonus(bonus, last) initExtraPercentageBar() -- get the position before updating meterBonus.counter = meterBonus.counterMax meterBonus.value = bonus meterBonus.y = meterBonus.startY if last then meterBonus.color = c.green -- ! else meterBonus.color = c.yellow end end extraPercentage = {y = 5, x = 100} function initExtraPercentageBar() extraPercentage.x = pMeter.value extraPercentage.counter = extraPercentage.counterMax end function drawExtraPercentageBar() local oldValue = extraPercentage.x local x = pMeter.x + oldValue -- old value local w = math.ceil(pMeter.value) -- current value rect(x,pMeter.y, w-oldValue, 5, c.white) end meterBonus = {y = 2, targetY = 9,startY = 2, counter = 0, counterMax = 2*60, value = 0, color = c.yellow} function printMeterBonus() local size = print('+'..meterBonus.value..'%',-100, -100, c.black,false,1,true) local startPosY = 2 local speed = 0.5 local posX = (W - size)/2 if meterBonus.y < meterBonus.targetY then meterBonus.y = meterBonus.y + speed elseif meterBonus.y >= meterBonus.targetY then meterBonus.counter = meterBonus.counter - 1 end if meterBonus.counter > 0 then printOutline('+'..meterBonus.value..'%',posX, meterBonus.y, meterBonus.color, c.black,false,1,true) else meterBonus.y = startPosY meterBonus.counter = 0 end end function addSfx() if #removeBuns > 0 then shake.value = shake.amount * #removeBuns addRemovalSfx() addBunnySfx() end end function addRemovalSfx() local sfxId = 9 local genNote = (72-(#removeBuns*3)) table.insert(playingSfx, {id = sfxId, note = genNote, channel = sfx1_channel, duration = 80, delay = 0}) end function GAME_OVER_STATE() if MUSIC then music(1) sfxGameOver() MUSIC = false end mouseOffCheck() checkMarked() mouseFunc() updateBuns() cls() drawBackground() drawCloudsShadow() drawClouds() drawBuns() drawLines() drawEndHUD() drawFire() if SCORE > HIGH_SCORE then HIGH_SCORE = SCORE pmem(0, HIGH_SCORE) end if LEVEL > HIGH_LEVEL then HIGH_LEVEL = LEVEL pmem(1, HIGH_LEVEL) end local restartSize = print('RETURN TO MENU', -100, -100, 12, true) local startPosX = (W - restartSize) / 2 local startPosY = 100 local radius = 3 local radius1 = (t//10+2)%5 local radius2 = (t//10)%5 local circAngularSpeed = 0.06 -- Adjust the speed as needed local circOffsetX = radius * math.cos(circAngularSpeed * t) -- t is the time variable local circOffsetY = radius * math.sin(circAngularSpeed * t) local circX = W / 2 + circOffsetX*17 local circY = startPosY + 2 + circOffsetY * 4 circb(circX, circY, radius1, c.red) circb(circX, circY, radius2, c.pink) printOutline('RETURN TO MENU', startPosX, startPosY+math.sin(t/10), c.white,c.magenta,true) if mget(startPosX/8, startPosY/8) == 2 and mget(startPosX/8+restartSize//8, startPosY/8) == 2 then music() addBunnySfx() playSfxTable() for i=1, 14 do ---!! ADJUST local fire_target = { x = startPosX+((i-1)*7), y = startPosY } if i == 7 or i == 10 then goto skip end addFire(fire_target) ::skip:: end checkMarked() resetGame() end end BANK2_BLACK = 02 -- actual balck is transparent CIRC = 0 function OVR() if GAME_STATE == 'play' then drawHUD(true) if CIRC < 300 then cls(BANK2_BLACK) CIRC = CIRC + 1 circ(W/2, H/2, CIRC, 0) drawFire() end -- drawPlayMeter() -- displayTimer() else printOutline('HIGH SCORE: '..HIGH_SCORE,1,1,c.red,c.magenta,false,1,true) printOutline('MAX LVL: '..HIGH_LEVEL,1,9,c.red,c.magenta,false,1,true) end end function checkMarked() if marked then if markDelay > 0 then markDelay = markDelay - 1 elseif markDelay <= 0 then unmarkMap() marked = false end end end function totalDistance() local totalDistance = 0 if #linePoints > 1 then for i=1, #linePoints do if i == #linePoints then break end p1 = linePoints[i] p2 = linePoints[i+1] local pointDistance = distance(p1.x,p1.y,p2.x,p2.y) totalDistance = totalDistance + pointDistance end else totalDsitance = 0 end print('Length ='..totalDistance) end function randomCloudMove() return math.random(30,40) end function randomCloudX() return math.random(-320,-80) end function randomCloudY() return math.random(10, 28) end function randomCloudW() return math.random(40,70) end function randomCloudH() return math.random(8,12) end clouds = { {x=randomCloudX(),y=randomCloudY(),w=randomCloudW(), h=randomCloudH(), move = randomCloudMove()}, {x=randomCloudX(),y=randomCloudY(),w=randomCloudW(), h=randomCloudH(), move = randomCloudMove()}, {x=randomCloudX(),y=randomCloudY(),w=randomCloudW(), h=randomCloudH(), move = randomCloudMove()} } function drawCloudsShadow() for _, cloud in ipairs(clouds) do elli(cloud.x,cloud.y+2+math.cos(t/cloud.move)*2,cloud.w,cloud.h,c.beige) end end -- drawClouds function drawClouds() local speed = 0.5 local limit = W + 80 for _, cloud in ipairs(clouds) do elli(cloud.x,cloud.y+math.cos(t/cloud.move)*2,cloud.w,cloud.h,c.ligthBrown) cloud.x = cloud.x + speed if cloud.x > limit then cloud.x = randomCloudX() cloud.y = randomCloudY() cloud.w = randomCloudW() cloud.h = randomCloudH() cloud.move = randomCloudMove() end end end -- drawClouds function drawBackground() local sky1 = c.blue local sky2 = c.cyan local ground1 = c.green local ground2 = c.lightGreen rect(0,0,W,H,sky1) rect(0,93,W,20,sky2) rect(0,78,W,14,sky2) rect(0,67,W,10,sky2) rect(0,58,W,8,sky2) rect(0,53,W,4,sky2) rect(0,50,W,2,sky2) line(0,48,W,48,sky2) line(0,46,W,46,sky2) line(0,43,W,43,sky2) line(0,38,W,38,sky2) line(0,29,W,29,sky2) line(0,14,W,14,sky2) -- 57-9-5-3-2-2-3-5-9-15 local size = print(#buns,-100,-100,12,true,10) local tx = (W - size)/2 if START_DELAY <= 0 then print(#buns,tx,40,c.blue,true,10) end elli(120,120,240,20,ground1) elli(120,122,240,20,ground2) elli(120,124,240,20,ground1) elli(120,126,240,20,ground2) elli(120,140,240,20,ground1) end -- drawBackground function distance(x1, y1, x2, y2) return math.sqrt((x2 - x1)^2 + (y2 - y1)^2) end function resetTransition() transition = { count = TRANSITION_TIME, num1Offset = 0, num2Offset = 50, textOffsetX = 241, blinkFlag = false } end transition = { count = TRANSITION_TIME, num1Offset = 0, num2Offset = 50, textOffsetX = 241, blinkFlag = false } function transitionAnimation() local numDistance = 90 local blink = t//2%2 local ySpeed = 5 local xSpeed = 6 local num1 = LEVEL - 1 local num2 = LEVEL local textSize = print('LEVEL: '..num2,-100,-100,12,false,3) local numSize = print(num2,-100,-100,12,false,3) local textX = (W - textSize)/2+transition.textOffsetX local textY = 50 if textX <= (W - textSize)/2 then textX = (W - textSize)/2 transition.count = transition.count - 1 else transition.textOffsetX = transition.textOffsetX - xSpeed end local numX = textX + textSize - numSize local num1Y = textY + transition.num1Offset if transition.count <= TRANSITION_TIME/2 then transition.num2Offset = transition.num2Offset + ySpeed transition.num1Offset = transition.num1Offset + ySpeed end local num2Y = transition.num2Offset - numDistance if num2Y > textY then num2Y = textY end if num1Y > 280 then transition.blinkFlag = true end if transition.blinkFlag then if blink == 0 then printOutline('LEVEL: ',textX-2,50+2,c.black,c.black,false,3) printOutline('LEVEL: ',textX,50,c.white,c.magenta,false,3) printOutline(num1,numX-2,num1Y+2,c.black,c.black,true,3) printOutline(num1,numX,num1Y,c.white,c.magenta,true,3) printOutline(num2,numX-2,num2Y+2,c.black,c.black,true,3) printOutline(num2,numX,num2Y,c.white,c.magenta,true,3) end else printOutline('LEVEL: ',textX-2,50+2,c.black,c.black,false,3) printOutline('LEVEL: ',textX,50,c.white,c.magenta,false,3) printOutline(num1,numX-2,num1Y+2,c.black,c.black,true,3) printOutline(num1,numX,num1Y,c.white,c.magenta,true,3) printOutline(num2,numX-2,num2Y+2,c.black,c.black,true,3) printOutline(num2,numX,num2Y,c.white,c.magenta,true,3) end if num1Y > 400 then resetTransition() TRANSITION = false elseif num1Y > 380 then sfxTransition2() end end function mouseBound() if mx > W then resetLineTables() end if my > H then resetLineTables() end if mx < 0 then resetLineTables() end if my < 0 then resetLineTables() end end -- mouseBound HOLD_COUNT = 0 MAX_HOLD = 5 * 60 IDLE = 0 MAX_IDLE = 3*60 function mouseFunc() local maxDistance = 3 if checkLineLength() then MOUSE_OFF = true closeLine() IDLE = 0 elseif mleft and not MOUSE_OFF then IDLE = 0 HOLD_COUNT = HOLD_COUNT + 1 if #linePoints == 0 then linePoints[1] = {x=mx, y=my} playLineSfx() else local lastP = linePoints[#linePoints] local mPoints = {x=mx, y=my} local pDistance = distance(lastP.x, lastP.y, mPoints.x, mPoints.y) --print(pDistance, 8, 8, 12) if pDistance > maxDistance then splitLine(linePoints, lastP, mPoints) end end else if #linePoints ~= 0 then HOLD_COUNT = 0 closeLine() elseif #linePoints == 0 and pMeter.value > 1 and GAME_STATE == 'play' and not TRANSITION then IDLE = IDLE + 1 if IDLE > MAX_IDLE then pMeter.value = pMeter.value - 0.1 end end end -- trace(IDLE) end -- mouseFunc function closeLine() p1, p2 = linePoints[#linePoints], linePoints[1] splitLine(linePoints, p1, p2,nil,true) if p1.x == p2.x and p1.y == p2.y and not marked then markMap() local center = findCenter() if GAME_STATE == 'play' then table.insert(scoreGetTable, center) end -- if center then -- trace('Center of the circle: x:' .. (center.x // 8) .. '- y: ' .. (center.y // 8)) -- end -- trace('fillpoint' .. ' x:' .. (p2.x // 8) .. '- y: ' .. ((p2.y // 8) + 1)) floodFill((center.x//8), (center.y//8), 1, 2) -- trace('flooded') marked = true markDelay = markDelayTime end end scoreGetTable = {} function drawScoreGet() local floatSpeed = 0.25 if #scoreGetTable > 0 then for i = #scoreGetTable, 1, -1 do local center = scoreGetTable[i] -- Check if 'center' is not nil if center then if center.count == nil then center.count = 60 center.points = 0 center.combo = 0 end if center.count <= 0 then table.remove(scoreGetTable, i) else center.count = center.count - 1 center.y = center.y - floatSpeed if center.points > 0 then if center.combo <= 1 then printOutline(center.points, center.x, center.y) else local printSize = print(center.points, -100, -100) printOutline(center.points, center.x, center.y) printOutline('x'..center.combo,center.x+printSize-1,center.y,c.red,c.black,false,1,true) end end end else -- Handle the case where 'center' is nil trace('Error: center is nil at index: '..i) end end end end function splitLine(tab, p1,p2, maxDistance, silence) local silence = silence or false local pDistance = distance(p1.x, p1.y, p2.x, p2.y) local maxDistance = maxDistance or 3 local numAdditionalPoints = math.floor(pDistance / (2 * maxDistance)) local deltaX = (p2.x - p1.x) / (numAdditionalPoints + 1) local deltaY = (p2.y - p1.y) / (numAdditionalPoints + 1) for i = 1, numAdditionalPoints do table.insert(tab, {x = p1.x + i * deltaX, y = p1.y + i * deltaY}) if not silence then playLineSfx() end end table.insert(tab, {x=p2.x,y=p2.y}) if not silence then playLineSfx() end end -- splitLine function playLineSfx() if not TRANSITION then sfx(10, (23+#linePoints),10,1,15) end end ---UNUSED function checkMouseHold() if HOLD_COUNT > MAX_HOLD then linePoints = {} HOLD_COUNT = 0 end end -- checkMouseHold function drawLines() local color1 = c.red local color2 = c.orange local color3 = c.yellow local lineColor = color1 local lineThreshold = 30 if #linePoints > 1 then autoLine() -- trace('threshold: '..(lineThreshold*1.50)..' #lpoints'..#linePoints..' lineColor'..lineColor) if #linePoints > math.floor(lineThreshold * 1.50) then if (time()//25)%4==0 then lineColor = color3 else lineColor = color2 end elseif #linePoints > lineThreshold then lineColor = color2 elseif #linePoints < lineThreshold then lineColor = color1 end if HOLD_COUNT > MAX_HOLD then resetLineTables() MOUSE_OFF = true HOLD_COUNT = 0 elseif HOLD_COUNT >= MAX_HOLD/1.5 then if (time()//25)%4==0 then lineColor = color3 else lineColor = color2 end end for i=1, #linePoints do if i < #linePoints then p1 = linePoints[i] p2 = linePoints[i+1] thickLine(p1.x,p1.y,p2.x,p2.y,lineColor,3) -- pix(p1.x,p1.y,12) end -- if not the last end -- for points end -- if more than 1 end --drawLine function resetLineTables() linePoints = {} autoLinePoints = {} end autoLinePoints = {} function autoLine() autoLinePoints = {} local p1,p2 = linePoints[#linePoints], linePoints[1] table.insert(autoLinePoints, p1) table.insert(autoLinePoints, p2) thickLine(p1.x,p1.y,p2.x,p2.y,c.pink,3) splitLine(autoLinePoints, p1, p2, nil, true) end -- autoLine function checkLineLength() if (#linePoints)+(#autoLinePoints) > MAX_LINE_POINTS then return true end end -- checkLineLength function markMap() for _, point in ipairs(linePoints) do mset(point.x//8, point.y//8,2) end -- for end -- markMap mapTable = {} function unmarkMap() for mapY = 0, H/8 do for mapX = 0, W/8 do mset(mapX,mapY,1) end end resetLineTables() end -- unmarkMap function findCenter() local sumX, sumY = 0, 0 local numPoints = #linePoints for _, point in ipairs(linePoints) do sumX = sumX + point.x sumY = sumY + point.y end if numPoints > 0 then local centerX = sumX / numPoints local centerY = sumY / numPoints return { x = centerX, y = centerY } else return nil end end function floodFill(x, y, targetTile, fillTile) -- Check if the target tile at (x, y) is the one we want to fill if mget(x,y) == targetTile then -- Set the tile to the fill tile mset(x,y,fillTile) -- Recursively call floodFill for neighboring tiles floodFill(x + 1, y, targetTile, fillTile) floodFill(x - 1, y, targetTile, fillTile) floodFill(x, y + 1, targetTile, fillTile) floodFill(x, y - 1, targetTile, fillTile) end end PLAY_METER_SIZE = 100 pMeter = { size = PLAY_METER_SIZE, color = c.green, x = (W - PLAY_METER_SIZE)/2, y = 2, value = 100, } function playMeter() local defaultSpeed = 0.06 local pMeterSpeed = (LEVEL*0.01) local finalSpeed = math.max(defaultSpeed, pMeterSpeed) if pMeter.value > pMeter.size then pMeter.value = pMeter.size end pMeter.value = pMeter.value - finalSpeed -- trace('pMeterSpeed: '..pMeterSpeed..' - pMeter.value: '..pMeter.value) end function drawPlayMeter() if pMeter.value <= pMeter.size/4 then pMeter.color = c.red elseif pMeter.value <= pMeter.size/2 then pMeter.color = c.orange else pMeter.color = c.green end rect(pMeter.x-1, pMeter.y-1,pMeter.size+2,7,c.magenta) rect(pMeter.x, pMeter.y,pMeter.value,5,pMeter.color) end buns = {} LEVEL = 0 DEFAULT_ACT_TIME = 60*3 -- action for bun function spawnBuns() if #buns == 0 then LEVEL = LEVEL + 1 MAX_BUN = MAX_BUN + 1 local normalRatio = 1.0 -- 100% normal bunnies for LEVEL 1 local smokerRatio = 0.0 -- 0% smoker bunnies for LEVEL 1 local shieldRatio = 0.0 -- 0% shield bunnies for LEVEL 1 if LEVEL == 2 then -- Adjust ratios based on level for LEVEL 2 normalRatio = 0.75 - (LEVEL - 2) * 0.01 shieldRatio = 0.25 + (LEVEL - 2) * 0.01 -- Ensure ratios don't go below 0 or exceed 1 normalRatio = math.max(0, math.min(1, normalRatio)) shieldRatio = math.max(0, math.min(1, smokerRatio)) elseif LEVEL >= 3 then -- Adjust ratios based on level for LEVEL 3 onwards normalRatio = 0.5 - (LEVEL - 2) * 0.01 smokerRatio = 0.25 + (LEVEL - 2) * 0.01 shieldRatio = 0.25 + (LEVEL - 2) * 0.01 -- Ensure ratios don't go below 0 or exceed 1 normalRatio = math.max(0, math.min(1, normalRatio)) smokerRatio = math.max(0, math.min(1, smokerRatio)) shieldRatio = math.max(0, math.min(1, shieldRatio)) end for i = 1, MAX_BUN do local rand = math.random() local bunType, bunBorder if rand <= normalRatio then bunType = 'normal' bunBorder = c.black elseif rand <= normalRatio + smokerRatio then bunType = 'smoker' bunBorder = c.magenta else bunType = 'shield' bunBorder = c.magenta end table.insert(buns, { type = bunType, border = bunBorder, w = 10, h = 10, x = math.random(0, W), y = (H + 8) - math.random(0, 128), f = 0, vx = 0, vy = 0, behindSmoke = false, actionCounter = DEFAULT_ACT_TIME + math.random(0, 60) }) end end end GRAV = 0.1 * 0.75 JUMP_FORCE = -5 * 0.75 sfx1_channel = 1 -- notesTable = {60,64,67,69} notesTable = {48,52,55,57} bunTypeDic = {normal=257,hitShield=259,shield=261,smoker=263,mark=278} function drawBuns() for _, b in ipairs(buns) do local bunSpr = bunTypeDic[b.type] if b.vy < 0 then bunSpr = bunSpr + 1 end sprOutline(bunSpr, b.x, b.y, 0, 1, b.f,nil,nil,nil,nil,b.border) end end function updateBuns() removeBuns = {} local score = 0 for i = 1, #buns do local b = buns[i] local flagCount = 0 if GAME_STATE ~= 'play' or TRANSITION then goto skip_collision end if mget((b.x//8)+1,(b.y//8)) == 2 then flagCount = flagCount + 1 end if mget((b.x//8)-1,(b.y//8)) == 2 then flagCount = flagCount + 1 end if mget((b.x//8),(b.y//8)+1) == 2 then flagCount = flagCount + 1 end if mget((b.x//8),(b.y//8)-1) == 2 then flagCount = flagCount + 1 end if not b.behindSmoke and flagCount >= 3 then table.insert(removeBuns, i) end ::skip_collision:: if b.y > 128 then -- If the bun has reached the bottom, make it jump again b.y = 128 b.vy = JUMP_FORCE if b.x < 8 then -- condition to not get stuck too close to the sides b.vx = 1 elseif b.x+b.w > W-8 then b.vx = -1 else b.vx = math.random(-1, 1) end else -- Apply gravity b.vy = b.vy + GRAV b.y = b.y + b.vy end -- Update horizontal position if b.vx < 0 then b.f = 1 else b.f = 0 end b.x = b.x + b.vx -- Bounce off the walls if b.x > W - 8 then b.x = W - 8 b.vx = b.vx * -1 elseif b.x < 0 then b.x = 0 b.vx = b.vx * -1 end if b.y < 0 then b.y = 0 end -- Check type, action if TRANSITION then goto skip_action end if b.type == 'hitShield' then b.actionCounter = b.actionCounter - 1 if b.actionCounter < 60 then if time()//100%2==0 then b.border = c.pink else b.border = c.black end end if b.actionCounter <= 0 then b.type = 'shield' b.border = c.magenta end elseif b.type == 'smoker' then if b.actionCounter > 0 then b.actionCounter = b.actionCounter - 1 if b.actionCounter < 60 then if time()//100%2==0 then b.border = c.white else b.border = c.magenta end end elseif b.actionCounter <= 0 and b.behindSmoke == false then spawnSmoke(b.x, b.y) b.border = c.magenta b.actionCounter = DEFAULT_ACT_TIME + math.random(0,60) elseif b.actionCounter <= 0 then b.border = c.magenta b.actionCounter = DEFAULT_ACT_TIME + math.random(0,60) end end ::skip_action:: end local bonusCounter = 0 local comboThreshold = 2 -- Number of bunnies needed for combo local comboBonus = 5 -- Multiplier for combo bonus local bonusDecayRate = 0.1 -- Rate at which bonus counter decays per frame local totalBonus = 0 for i = #removeBuns, 1, -1 do local b = buns[removeBuns[i]] addFire(buns[removeBuns[i]]) if b.type == 'shield' then b.type = 'hitShield' b.border = c.black b.actionCounter = 5 * 60 else table.remove(buns, removeBuns[i]) score = score + 100 -- addBunnySfx() bonusCounter = bonusCounter + 1 end end local comboMultiplier = 0 -- Combo Bonus Calculation totalBonus = bonusCounter -- if no combo if bonusCounter >= comboThreshold then comboMultiplier = math.floor(bonusCounter / comboThreshold) + 1 totalBonus = bonusCounter + (comboBonus * comboMultiplier) end -- Decay Bonus Counter -- totalBonus = math.max(0, bonusCounter - decay )--- bonusDecayRate local function addToScore() if #scoreGetTable > 0 then scoreGetTable[#scoreGetTable].points = scoreGetTable[#scoreGetTable].points + 100 * bonusCounter if comboMultiplier > 0 then scoreGetTable[#scoreGetTable].combo = comboMultiplier end SCORE = SCORE + totalBonus*100 end end local levelBonus = 0.1--LEVEL*0.1 -- trace('lvlbonus: '..levelBonus..'totalbonus'..totalBonus) local percentageBonus = totalBonus*(math.ceil(levelBonus)) if bonusCounter > 0 and bonusCounter < 20 and #buns == 0 and pMeter.color == c.red then addToScore() local plusMeter = 20*percentageBonus newMeterBonus(math.ceil(plusMeter),c.green) trace('before: '..pMeter.value) pMeter.value = pMeter.value + plusMeter --testing trace('after: '..pMeter.value) -- Add the Bonus to the Player's score elseif bonusCounter > 0 then addToScore() newMeterBonus(percentageBonus) if pMeter.value + percentageBonus >= pMeter.size then pMeter.value = pMeter.size else pMeter.value = pMeter.value + percentageBonus --testing end -- trace('bcounter: '..bonusCounter..' - decay: '..bonusDecayRate..'.') end end playingSfx = {} sfxDelay = 0 sfxDelayTime = 1 function addBunnySfx() local genNote = notesTable[math.random(1,#notesTable)] -- sfx(8, notesTable[note], 60, sfx1_channel, 13) local sfxId = 8 if GAME_STATE ~= 'play' then sfxId = 12 genNote = 48 end table.insert(playingSfx, {id = sfxId, note = genNote, channel = sfx1_channel, duration = 80, delay = 10}) end function sfxGameOver() sfx(13, 'A-2', 80, 0, 15) end function sfxTransition() table.insert(playingSfx, {id = 12, note = 'G-6', duration = 80, channel = 1, delay = 0}) end function sfxTransition2() table.insert(playingSfx, {id = 14, note = 'C-6', duration = 30, channel = 1, delay = 0}) end function playSfxTable() local removeSfx = {} for index, s in ipairs(playingSfx) do if s.delay <= 0 and index == 1 then sfx(s.id, s.note, s.duration, s.channel, 15) table.insert(removeSfx, index) -- trace(s.id..' n: '..#playingSfx) elseif index == 1 then -- trace('ifindexone: '..s.id..' n: '..#playingSfx) s.delay = s.delay-1 end end for i=#removeSfx, 1, -1 do -- trace(playingSfx[i].id..' n: '..#playingSfx) table.remove(playingSfx, i) end end function playSmokeSfx(removeSmoke) removeSmoke = removeSmoke or 5 sfx(9,(72-(removeSmoke*3)),80,1,10) end -- Maximum number of fires on screen (make local later) maxFires = 10 -- Function to update fire logic fireCount = 0 function updateFireParticles(target) -- Iterate over the fire list in reverse to safely remove fires for i = #fireList, 1, -1 do local fire = fireList[i] -- Update fire logic fire.size = fire.size - 0.2 * fire.speed fire.y = fire.y - fire.speed -- Check if the fire should be removed if fire.y < fire.maxY or fire.size < fire.minSize then table.remove(fireList, i) end end fireCount = fireCount + 1 if fireCount > 60 then fireCount = 0 end end -- Function to draw the fires in the list function drawFire(target) updateFireParticles(target) for _, fire in ipairs(fireList) do circ(fire.x, fire.y, fire.size, fire.color) end end fireList = {} function addFire(target) local default = {c.red,c.yellow} local tColor = default[math.random(1,#default)] if target.type == 'shield' then tColor = c.pink end -- Adds fire particle local newFire = { x = target.x, --+ math.sin(time() * 0.1) * 4 + math.random(-1, 1), y = target.y, size = 4, speed = 0.4, maxY = 10, minSize = 1, color = tColor, counter = 10 } table.insert(fireList, newFire) end shake = { flag = true, value = 0, amount = 3, speed = 0.3, maxAmount = 8, maxValue = 20 } screen_offset=0x3FF9 maxRecord = 0 function screenShake() -- trace('maxRecord = '..maxRecord) if shake.flag then if shake.value > shake.maxValue then shake.value = shake.maxValue end if shake.value > 0 then t=time()/20 d=math.random()*math.pi*2 amountx = shake.value*math.cos(d)*math.sin(t) amounty = shake.value*math.sin(d)*math.sin(t) if math.abs(shake.value) > maxRecord then maxRecord = math.abs(shake.value) end if math.abs(amountx) > shake.maxAmount then if amountx > 0 then amountx = shake.maxAmount else amountx = -shake.maxAmount end end if math.abs(amounty) > shake.maxAmount then if amountx > 0 then amounty = shake.maxAmount else amounty = -shake.maxAmount end end -- trace('x'..amountx..' - y'..amounty) poke(screen_offset,amountx) poke(screen_offset+1,amounty) shake.value=math.max(0,(shake.value-shake.speed)) end end -- flag end -- screenShake smokeTable = {} function spawnSmoke(posX,posY) local circR = 8 local smokeAmount = 4 local newSmoke = {} for i = 1, smokeAmount do table.insert(newSmoke, { x = posX, y = posY, r=0, maxR = circR, indexOffsetX = 0, indexOffsetY = 0, removing = false } ) end table.insert(smokeTable, newSmoke) end function approachTarget(current, target, speed) local difference = target - current if math.abs(difference) <= speed then return target else return current + math.sign(difference) * speed end end -- Utility function to get the sign of a number function math.sign(x) return x > 0 and 1 or x < 0 and -1 or 0 end function updateSmoke() local updatedPositions = {} if #smokeTable > 0 then for groupIndex, groupSmoke in ipairs(smokeTable) do local updatedGroup = {} local removeSmoke = {} for index, smoke in ipairs(groupSmoke) do local flagCount = 0 if TRANSITION then goto skip_collision end if mget((smoke.x // 8), (smoke.y // 8)) == 2 then --center flagCount = flagCount + 1 end if mget((smoke.x // 8) + 1, (smoke.y // 8)) == 2 then --right flagCount = flagCount + 1 end if mget((smoke.x // 8) - 1, (smoke.y // 8)) == 2 then --left flagCount = flagCount + 1 end if mget((smoke.x // 8), (smoke.y // 8) + 1) == 2 then --down flagCount = flagCount + 1 end if mget((smoke.x // 8), (smoke.y // 8) - 1) == 2 then--up flagCount = flagCount + 1 end if mget((smoke.x // 8)-1, (smoke.y // 8) - 1) == 2 then --upleft flagCount = flagCount + 1 end if mget((smoke.x // 8), (smoke.y // 8) - 1) == 2 then --uprigth flagCount = flagCount + 1 end if mget((smoke.x // 8) - 1, (smoke.y // 8) + 1) == 2 then --downleft flagCount = flagCount + 1 end if mget((smoke.x // 8) + 1, (smoke.y // 8) - 1) == 2 then --downright flagCount = flagCount + 1 end ::skip_collision:: if flagCount >= 6 then smoke.removing = true else local speed = 0.5 local growSpeed = 0.5 local targetX, targetY = 0, 0 if index == 1 then --left targetX = -12 targetY = 0 elseif index == 2 then --right targetX = 12 targetY = 0 elseif index == 3 then --up targetX = 0 targetY = 4 elseif index == 4 then -- down targetX = 0 targetY = -4 else targetX = 0 targetY = 0 end if not smoke.removing then -- grow if smoke.r < smoke.maxR then smoke.r = smoke.r + growSpeed else smoke.r = smoke.maxR end else smoke.r = smoke.r - 1.5 if smoke.r <= 0 then table.insert(removeSmoke, index) end end smoke.indexOffsetX = approachTarget(smoke.indexOffsetX, targetX, speed) smoke.indexOffsetY = approachTarget(smoke.indexOffsetY, targetY, speed) -- Adjust position if reaching screen boundaries if smoke.x-16 < 0 then smoke.x = smoke.x + 16 -- move towards the center elseif smoke.x+16 > W then smoke.x = smoke.x - 16 -- move towards the center end if smoke.y-16 < 0 then smoke.y = smoke.y + 16 -- move towards the center elseif smoke.y+16 > H then smoke.y = smoke.y - 16 -- move towards the center end local smokePosX = smoke.indexOffsetX + smoke.x local smokePosY = smoke.indexOffsetY + smoke.y table.insert(updatedGroup, { x = smokePosX, y = smokePosY, r = smoke.r }) end end -- Remove the specified smokes for i = #removeSmoke, 1, -1 do local removedIndex = removeSmoke[i] table.remove(groupSmoke, removedIndex) end -- if #removeSmoke > 1 then -- playSmokeSfx(#removeSmoke) -- end table.insert(updatedPositions, updatedGroup) end end return updatedPositions end function drawSmokeShadow(positions) if #positions > 0 then for _, groupPositions in ipairs(positions) do for _, smoke in ipairs(groupPositions) do local radius = 2.5 local offsetX = radius * math.cos(t / 20) local offsetY = radius * math.sin(t / 20) circ(smoke.x+offsetX, smoke.y+offsetY, smoke.r + 2, c.magenta) end end end end function drawSmoke(positions) if #positions > 0 then for _, groupPositions in ipairs(positions) do for _, smoke in ipairs(groupPositions) do local radius = 1--2 local offsetX =radius * math.cos(t / 20) local offsetY = radius * math.sin(t / 20) circ(smoke.x+offsetX, smoke.y+offsetY, smoke.r, c.beige) -- pix(smoke.x,smoke.y,c.black) end end end end function smokeCollision() if #smokeTable > 0 then for _, b in ipairs(buns) do local behindAnySmoke = false for _, smokeGroup in ipairs(smokeTable) do for _, smoke in ipairs(smokeGroup) do if isCollision(smoke, b) then behindAnySmoke = true break end end if behindAnySmoke then break -- No need to check other smoke groups if behind one end end b.behindSmoke = behindAnySmoke if behindAnySmoke then b.spr = 273 else b.spr = 257 end end end end function isCollision(circle, sprite) local distanceX = circle.x - (sprite.x + sprite.w / 2) local distanceY = circle.y - (sprite.y + sprite.h / 2) local distanceSquared = distanceX^2 + distanceY^2 local radiusSumSquared = (circle.r + sprite.w / 2)^2 -- print("Distance squared: " .. distanceSquared) -- print("Radius sum squared: " .. radiusSumSquared) return distanceSquared < radiusSumSquared end