Downloads containing 1-Tweedle.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Tweedle WheedleFeatured Download Bloody_Body Single player 8.9 Download file

File preview

//Hello, seems you're mad enough to open .j2as file! Let's see if you can read it to the end... 
//Unfortunately my English isn't perfect but I hope it's good enough so you will be able to understand my hints
//I've spent some time learning how to use Angel Skript and actually, it's my first level.
//I was inspired by the brilliant levels like Ozimandius, plusHeaven, plusEnscripted, ect- somehow I used some concepts from these levels, but I tried to adopt them to my own level
//I also used some code snippets from JJ2 online. I wrote the names of their author near them, so as not to be accused of plagiarism. I'm sorry if I had forgotten someone.
//Probably 60% of the features were created by some other levelmakers, but the remaining 40% are my ideas.
//As for the layout of the level... I took someones (I'm sorry, I don't remember the author) level based on Far Out (unfinished official level) and developed it a lot more
//Now it's really huge and full of secrets, different enemies and deadly pits (Yeah, I'm sadistic a bit :D)
//This skript isn't finished though... I am planning to add several new things here like the menu which allows you to buy ammo and ammunition
//instead of warping into the bonus area after paying the certain amount of coins, NPC (gunless Spaz if you play as Jazz or gunless Jazz otherwise)
//Anyway, Tweedle kidnappes your bro, stoles his gun and uses it against you in the final fight. I also want to add chatting with bro and some enemies 
//(probably with an animation of your interlocutor, some similar concept was used in Ozimandius, remember?)
//I also want to make bombs appear only when you release the fire button, and make Bubbas not to get stuck when being caught into the radius of explosion, and, well... Tweedle has the same problem if you set isBlastable to true.
//I guess that the new version of JJ2+ allows to make vertically-rotated anim of Hatter's spittle (I wanna use it for spitgun)
//I simply don't have time for that now, and it's difficult to create something like that alone, but I hope I'll make some update of this code when I am in a good mood and have some free time.
//Now I'll have some rest from writing code and looking forward commentaries ;P

jjPAL myPal;
const int UP  = 0x26;
const int SHOOT  = 0x20;
int i,g=0,z=0,v=0,x=0,b=0,u=1,shootpressed=0,m,lastTile = 0,killedBUBBAs=0, killedcats=0, killedbombs=0, killedsmallbombs=0,
catgoal,bombgoal,smbombgoal;
uint8 elapsed=0;
jjOBJ@ spawnedObject;
jjOBJ@ spawnedObject2;
jjOBJ@ spawnedObject3;
bool hueShift = false; 
bool normal = false; 
bool dark = false; 
bool bombs = false;
bool cats = false;
bool scene = true;
bool boss = false;
bool stoned = false;
bool start = true;
bool paused = false;
jjPAL Twilight,FineDay,Golden,Bloody,Grim;
const float cBombSpeed = 5; //xSpeed of the bomb
const float cBombPlayerSpeed = 2; //xSpeed the bomb can gain by player speed (if a player is running full speed it will add 6 xSpeed)
const int cBombLifeTime = 70*2; 

const array<string> Shop = {
"Great Carrot"
"Ammo"
};

const array<string> Hints = {
	"Hint: Bubba's spirits are only affected by physical attacks",
	"Hint: Blue ghosts aren't affected by physical attacks at all",
	"Hint: The best weapon against Spiky balls are seeker missiles",
	"Hint: You have to collect 200 coins to get access to the bonus area",
	"Hint: Difficulty changes lots of things",
	"Hint: Cheshire's flame won't chase you if you move vertically",
	"Hint: Tweedle is immune to bombs",
	"Hint: Fastfeet temporary makes your common jump higher than special jump",
};

void onLevelLoad() {
jjTileSet(4, 332, 28, jjTileGet(4, 332, 28) | TILE::VFLIPPED);	
jjTileSet(4, 307, 28, jjTileGet(4, 307, 28) | TILE::VFLIPPED);
jjTileSet(4, 426, 53, jjTileGet(4, 426, 53) | TILE::VFLIPPED);
jjTileSet(4, 432, 53, jjTileGet(4, 432, 53) | TILE::VFLIPPED);	
jjTileSet(4, 81, 19, jjTileGet(4, 81, 19) | TILE::VFLIPPED);		
jjTileSet(4, 84, 19, jjTileGet(4, 84, 19) | TILE::VFLIPPED);	
jjTileSet(4, 96, 19, jjTileGet(4, 96, 19) | TILE::VFLIPPED);	
jjTileSet(4, 99, 19, jjTileGet(4, 99, 19) | TILE::VFLIPPED);	
jjTileSet(4, 382, 23, jjTileGet(4, 382, 23) | TILE::VFLIPPED);	
jjTileSet(4, 381, 24, jjTileGet(4, 381, 24) | TILE::VFLIPPED);	
jjTileSet(4, 380, 25, jjTileGet(4, 380, 25) | TILE::VFLIPPED);	
jjTileSet(4, 379, 26, jjTileGet(4, 379, 26) | TILE::VFLIPPED);	
jjTileSet(4, 378, 27, jjTileGet(4, 378, 27) | TILE::VFLIPPED);	
jjTileSet(4, 377, 26, jjTileGet(4, 377, 26) | TILE::VFLIPPED);	
jjTileSet(4, 376, 25, jjTileGet(4, 376, 25) | TILE::VFLIPPED);	
jjTileSet(4, 387, 23, jjTileGet(4, 387, 23) | TILE::VFLIPPED);	
jjTileSet(4, 388, 24, jjTileGet(4, 388, 24) | TILE::VFLIPPED);	
jjTileSet(4, 389, 25, jjTileGet(4, 389, 25) | TILE::VFLIPPED);	
jjTileSet(4, 390, 26, jjTileGet(4, 390, 26) | TILE::VFLIPPED);	
jjTileSet(4, 391, 27, jjTileGet(4, 391, 27) | TILE::VFLIPPED);	
jjTileSet(4, 392, 26, jjTileGet(4, 392, 26) | TILE::VFLIPPED);	
jjTileSet(4, 393, 25, jjTileGet(4, 393, 25) | TILE::VFLIPPED);	

		
catgoal=4*(jjDifficulty+1);
bombgoal=10*(jjDifficulty+1);
smbombgoal=75*(jjDifficulty+1);

	FineDay.gradient(0, 0,0,             0, 0,0,         0, 10, 1.0);
	FineDay.gradient(255, 255,255,             255, 255,255,         10, 6, 1.0);
	FineDay.gradient(199, 255,0,             199, 255,0,         16, 1, 1.0);
	FineDay.gradient(143, 219,0,             0, 11,0,         17, 7, 1.0);
	FineDay.gradient(255, 0,0,             163, 0,0,         24, 4, 1.0);
	FineDay.gradient(135, 0,0,             11, 0,0,         28, 4, 1.0);
	FineDay.gradient(187, 227,255,             0, 139,255,         32, 4, 1.0);
	FineDay.gradient(0, 107,203,             0, 7,11,         36, 4, 1.0);
	FineDay.gradient(255, 255,0,             255, 199,0,         40, 2, 1.0);
	FineDay.gradient(255, 147,0,             255, 95,0,         42, 2, 1.0);
	FineDay.gradient(203, 55,0,             11, 0,0,         44, 4, 1.0);
	FineDay.gradient(251, 139,183,       239, 0,99,         48, 4, 1.0);            
	FineDay.gradient(191, 0,71,      55, 0,19,         52, 4, 1.0);
	FineDay.gradient(220, 165,113,             154, 129,100,         56, 3, 1.0);
	FineDay.gradient(219, 195,0,             11, 7,0,         59, 5, 1.0);
	FineDay.gradient(255, 243,211,             255, 243,211,         64, 1, 1.0);
	FineDay.gradient(219, 207,175,             11, 7,7,         65, 7, 1.0);
	FineDay.gradient(211, 231,255,             211, 231,255,         72, 1, 1.0);
	FineDay.gradient(171, 195,219,             107, 127,155,         73, 3, 1.0);
	FineDay.gradient(75, 95,119,             7, 7,11,         76, 4, 1.0);
	FineDay.gradient(0, 255,195,             0, 11,7,         80, 8, 1.0);
	FineDay.gradient(231, 119,255,             11, 0,7,         88, 8, 1.0);
	
	FineDay.gradient(207, 235,23,             207, 235,23,         96, 1, 1.0);
	FineDay.gradient(147, 207,15,             147, 207,15,         97, 1, 1.0);
	FineDay.gradient(91, 179,7,               91, 179,7,           98, 1, 1.0);
	FineDay.gradient(47, 151,0,               47, 151,0,           99, 1, 1.0);
	FineDay.gradient(15, 127,0,               0, 43, 23,           100, 4, 1.0);
	FineDay.gradient(243, 163, 95, 			43, 15, 7, 			 104, 8, 1.0);
	FineDay.gradient(255, 216, 59, 			199, 30, 0, 		 112, 8, 1.0);
	FineDay.gradient(194, 26, 0, 			    43, 0, 0, 		     120, 8, 1.0);
	FineDay.gradient(229, 131, 11,            66, 8, 3, 			 128, 8, 1.0);
	FineDay.gradient(255, 220, 12,            122, 105, 6,         136, 8, 1.0);
	FineDay.gradient(240, 240, 173,           179, 139, 59,        144, 8, 1.0);
	FineDay.gradient(168, 119, 50,            64, 21, 0,           152, 8, 1.0);
	FineDay.gradient(126, 242, 205,           0, 26, 25,           160, 16, 1.0);
	FineDay.gradient(231, 251, 255,           51, 155, 203,        176, 16, 1.0);
	FineDay.gradient(47, 147, 199,            0, 47, 115,          192, 16, 1.0);
	FineDay.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	
	Golden.gradient(0, 0,0,             0, 0,0,         0, 10, 1.0);
	Golden.gradient(255, 255,255,             255, 255,255,         10, 6, 1.0);
	Golden.gradient(199, 255,0,             199, 255,0,         16, 1, 1.0);
	Golden.gradient(143, 219,0,             0, 11,0,         17, 7, 1.0);
	Golden.gradient(255, 0,0,             163, 0,0,         24, 4, 1.0);
	Golden.gradient(135, 0,0,             11, 0,0,         28, 4, 1.0);
	Golden.gradient(187, 227,255,             0, 139,255,         32, 4, 1.0);
	Golden.gradient(0, 107,203,             0, 7,11,         36, 4, 1.0);
	Golden.gradient(255, 255,0,             255, 199,0,         40, 2, 1.0);
	Golden.gradient(255, 147,0,             255, 95,0,         42, 2, 1.0);
	Golden.gradient(203, 55,0,             11, 0,0,         44, 4, 1.0);
	Golden.gradient(251, 139,183,       239, 0,99,         48, 4, 1.0);            
	Golden.gradient(191, 0,71,      55, 0,19,         52, 4, 1.0);
	Golden.gradient(220, 165,113,             154, 129,100,         56, 3, 1.0);
	Golden.gradient(219, 195,0,             11, 7,0,         59, 5, 1.0);
	Golden.gradient(255, 243,211,             255, 243,211,         64, 1, 1.0);
	Golden.gradient(219, 207,175,             11, 7,7,         65, 7, 1.0);
	Golden.gradient(211, 231,255,             211, 231,255,         72, 1, 1.0);
	Golden.gradient(171, 195,219,             107, 127,155,         73, 3, 1.0);
	Golden.gradient(75, 95,119,             7, 7,11,         76, 4, 1.0);
	Golden.gradient(0, 255,195,             0, 11,7,         80, 8, 1.0);
	Golden.gradient(231, 119,255,             11, 0,7,         88, 8, 1.0);

	Golden.gradient(247, 102,23,             247, 102,23,            96, 1, 1.0);
	Golden.gradient(199,88, 27,             40,17, 6,           97, 7, 1.0);
	Golden.gradient(36,14, 41,             0,0, 15,           104, 8, 1.0);
	Golden.gradient(242, 173,30,  			138, 27,55,  		 112, 8, 1.0);
	Golden.gradient(93, 23, 38, 			    7, 2, 2, 		     120, 8, 1.0);
	Golden.gradient(179, 73, 108,            50, 20, 30, 	          128, 8, 1.0);
	Golden.gradient(44, 18, 27,            1, 0, 0, 	          136, 8, 1.0);
	Golden.gradient(255, 190, 23,                241, 172, 25,             144, 2, 1.0);
	Golden.gradient(235, 158, 23,                186, 92, 37,             146, 6, 1.0);
	Golden.gradient(173, 81, 42,                50, 7, 21,             152, 8, 1.0);
	Golden.gradient(150, 174, 183,            107, 77, 56,         160, 8, 1.0);
	Golden.gradient(98, 65, 47,            1, 1, 1,         168, 8, 1.0);
	Golden.gradient(22, 30, 77,            0, 0, 3,           176, 32, 1.0);

	Bloody.gradient(0, 0,0,             0, 0,0,         0, 10, 1.0);
	Bloody.gradient(255, 255,255,             255, 255,255,         10, 6, 1.0);
	Bloody.gradient(199, 255,0,             199, 255,0,         16, 1, 1.0);
	Bloody.gradient(143, 219,0,             0, 11,0,         17, 7, 1.0);
	Bloody.gradient(255, 0,0,             163, 0,0,         24, 4, 1.0);
	Bloody.gradient(135, 0,0,             11, 0,0,         28, 4, 1.0);
	Bloody.gradient(187, 227,255,             0, 139,255,         32, 4, 1.0);
	Bloody.gradient(0, 107,203,             0, 7,11,         36, 4, 1.0);
	Bloody.gradient(255, 255,0,             255, 199,0,         40, 2, 1.0);
	Bloody.gradient(255, 147,0,             255, 95,0,         42, 2, 1.0);
	Bloody.gradient(203, 55,0,             11, 0,0,         44, 4, 1.0);
	Bloody.gradient(251, 139,183,       239, 0,99,         48, 4, 1.0);            
	Bloody.gradient(191, 0,71,      55, 0,19,         52, 4, 1.0);
	Bloody.gradient(220, 165,113,             154, 129,100,         56, 3, 1.0);
	Bloody.gradient(219, 195,0,             11, 7,0,         59, 5, 1.0);
	Bloody.gradient(255, 243,211,             255, 243,211,         64, 1, 1.0);
	Bloody.gradient(219, 207,175,             11, 7,7,         65, 7, 1.0);
	Bloody.gradient(211, 231,255,             211, 231,255,         72, 1, 1.0);
	Bloody.gradient(171, 195,219,             107, 127,155,         73, 3, 1.0);
	Bloody.gradient(75, 95,119,             7, 7,11,         76, 4, 1.0);
	Bloody.gradient(0, 255,195,             0, 11,7,         80, 8, 1.0);
	Bloody.gradient(231, 119,255,             11, 0,7,         88, 8, 1.0);

	Bloody.gradient(255, 20,20,             255, 20,20,           96, 1, 1.0);
	Bloody.gradient(240,14, 14,             64,0, 02,           97, 7, 1.0);
	Bloody.gradient(55, 51, 50, 		     	10, 10, 9, 			 104, 8, 1.0);
	Bloody.gradient(255, 100,0,  			26, 10,0,  		 112, 8, 1.0);
	Bloody.gradient(255, 255, 20, 			    199, 84, 8, 		     120, 8, 1.0);
	Bloody.gradient(255, 19, 18,            12, 0, 0, 	          128, 16, 1.0);
	Bloody.gradient(255, 0, 0,                19, 0, 0,             144, 16, 1.0);
	Bloody.gradient(155, 80, 103,            3, 0, 1,         160, 16, 1.0);
	Bloody.gradient(255, 24, 18,            150, 12, 10,         176, 16, 1.0);
	Bloody.gradient(144, 7, 7,            30, 0, 0,           192, 16, 1.0);
	Bloody.gradient(247, 132, 20,             10, 5, 2,         208, 16, 1.0);

	Grim.gradient(0, 0,0,             0, 0,0,         0, 10, 1.0);
	Grim.gradient(255, 255,255,             255, 255,255,         10, 6, 1.0);
	Grim.gradient(199, 255,0,             199, 255,0,         16, 1, 1.0);
	Grim.gradient(143, 219,0,             0, 11,0,         17, 7, 1.0);
	Grim.gradient(255, 0,0,             163, 0,0,         24, 4, 1.0);
	Grim.gradient(135, 0,0,             11, 0,0,         28, 4, 1.0);
	Grim.gradient(187, 227,255,             0, 139,255,         32, 4, 1.0);
	Grim.gradient(0, 107,203,             0, 7,11,         36, 4, 1.0);
	Grim.gradient(255, 255,0,             255, 199,0,         40, 2, 1.0);
	Grim.gradient(255, 147,0,             255, 95,0,         42, 2, 1.0);
	Grim.gradient(203, 55,0,             11, 0,0,         44, 4, 1.0);
	Grim.gradient(251, 139,183,       239, 0,99,         48, 4, 1.0);            
	Grim.gradient(191, 0,71,      55, 0,19,         52, 4, 1.0);
	Grim.gradient(220, 165,113,             154, 129,100,         56, 3, 1.0);
	Grim.gradient(219, 195,0,             11, 7,0,         59, 5, 1.0);
	Grim.gradient(255, 243,211,             255, 243,211,         64, 1, 1.0);
	Grim.gradient(219, 207,175,             11, 7,7,         65, 7, 1.0);
	Grim.gradient(211, 231,255,             211, 231,255,         72, 1, 1.0);
	Grim.gradient(171, 195,219,             107, 127,155,         73, 3, 1.0);
	Grim.gradient(75, 95,119,             7, 7,11,         76, 4, 1.0);
	Grim.gradient(0, 255,195,             0, 11,7,         80, 8, 1.0);
	Grim.gradient(231, 119,255,             11, 0,7,         88, 8, 1.0);

	Grim.gradient(24, 255,253,             0, 57, 56,           96, 8, 1.0);
	Grim.gradient(0, 14, 71, 		     	0, 0, 15, 			 104, 8, 1.0);
	Grim.gradient(20, 253, 120, 			10, 137, 65, 		 112, 8, 1.0);
	Grim.gradient(9, 132, 62, 			    0, 49, 12, 		     120, 8, 1.0);
	Grim.gradient(190, 255, 18,            5, 5, 0, 	          128, 8, 1.0);
	Grim.gradient(0, 11, 8,                0, 5, 0,             136, 8, 1.0);
	Grim.gradient(25, 150, 123,            33, 238, 177,         144, 5, 1.0);
	Grim.gradient(28, 225, 168,            24, 144, 117,         149, 3, 1.0);
	Grim.gradient(23, 138, 112,            0, 22, 11,           152, 8, 1.0);
	Grim.gradient(0, 255, 255,             10, 155, 155,         160, 8, 1.0);
	Grim.gradient(8, 144, 144,             0, 2, 2,             168, 8, 1.0);
	Grim.gradient(0, 0, 3,                 0, 83, 83,             176, 32, 1.0);
	Grim.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	
    jjPalette.gradient(207, 235,23,             207, 235,23,         96, 1, 1.0);
	jjPalette.gradient(147, 207,15,             147, 207,15,         97, 1, 1.0);
	jjPalette.gradient(91, 179,7,               91, 179,7,           98, 1, 1.0);
	jjPalette.gradient(47, 151,0,               47, 151,0,           99, 1, 1.0);
	jjPalette.gradient(15, 127,0,               0, 43, 23,           100, 4, 1.0);
	jjPalette.gradient(243, 163, 95, 			43, 15, 7, 			 104, 8, 1.0);
	jjPalette.gradient(255, 216, 59, 			199, 30, 0, 		 112, 8, 1.0);
	jjPalette.gradient(194, 26, 0, 			    43, 0, 0, 		     120, 8, 1.0);
	jjPalette.gradient(229, 131, 11,            66, 8, 3, 			 128, 8, 1.0);
	jjPalette.gradient(255, 220, 12,            122, 105, 6,         136, 8, 1.0);
	jjPalette.gradient(240, 240, 173,           179, 139, 59,        144, 8, 1.0);
	jjPalette.gradient(168, 119, 50,            64, 21, 0,           152, 8, 1.0);
	jjPalette.gradient(126, 242, 205,           0, 26, 25,           160, 16, 1.0);
	jjPalette.gradient(231, 251, 255,           51, 155, 203,        176, 16, 1.0);
	jjPalette.gradient(47, 147, 199,            0, 47, 115,          192, 16, 1.0);
	jjPalette.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	jjSetFadeColors(0,40,80);	
	
	jjWeapons[WEAPON::BOUNCER].maximum = 9999;//The thing that had always irritated me in JJ2
	jjWeapons[WEAPON::TOASTER].maximum = 9999;//was that you can't collect more than 99 of ammo units.
	jjWeapons[WEAPON::TNT].maximum = 9999;// Now ammo count is potentially unlimited.
	jjWeapons[WEAPON::RF].maximum = 9999;//However it doesn't have any strong influence on gameplay, just for fun
	jjWeapons[WEAPON::SEEKER].maximum = 9999;
	jjWeapons[WEAPON::GUN9].maximum = 9999;
	jjWeapons[WEAPON::GUN8].maximum = 9999;
	jjWeapons[WEAPON::ICE].maximum = 9999;
	
	jjObjectPresets[OBJECT::BEES].behavior = NPC;
	jjObjectPresets[OBJECT::BEES].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::BEES].playerHandling = HANDLING::EXPLOSION;
	
	jjObjectPresets[OBJECT::APPLE].scriptedCollisions = true;
	jjObjectPresets[OBJECT::APPLE].behavior = GreatCarrot;
	jjObjectPresets[OBJECT::APPLE].light = 15;
	jjObjectPresets[OBJECT::APPLE].lightType = LIGHT::LASER;
	jjObjectPresets[OBJECT::APPLE].state=STATE::FLOAT;
	jjObjectPresets[OBJECT::APPLE].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::APPLE].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::APPLE].isBlastable = false;
	
	jjObjectPresets[OBJECT::FRIES].scriptedCollisions = true;
	jjObjectPresets[OBJECT::FRIES].behavior = Toadstool;
	jjObjectPresets[OBJECT::FRIES].state=STATE::FLOAT;
	jjObjectPresets[OBJECT::FRIES].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::FRIES].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::FRIES].points = 100;
		
	jjObjectPresets[OBJECT::GUN8AMMO3].determineCurAnim(ANIM::PICKUPS, 78, true);
	jjObjectPresets[OBJECT::TNTAMMO3].determineCurAnim(ANIM::AMMO, 1, true);
	
	jjObjectPresets[OBJECT::SEEKERBULLETPU].determineCurAnim(ANIM::AMMO, 57);
	jjObjectPresets[OBJECT::SEEKERBULLETPU].behavior=FlyingAmmo;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].playerHandling=HANDLING::PICKUP;
	
	jjObjectPresets[OBJECT::TOASTERBULLETPU].special = jjObjectPresets[OBJECT::TOASTERBULLETPU].determineCurAnim(ANIM::AMMO, 5);
	jjObjectPresets[OBJECT::TOASTERBULLETPU].behavior = DragonBreath;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].animSpeed = 1; 
	jjObjectPresets[OBJECT::TOASTERBULLETPU].lightType= LIGHT::RING;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].light =1;
	
	jjObjectPresets[OBJECT::FIREBALLBULLET].determineCurAnim(ANIM::HATTER, 3);
	jjObjectPresets[OBJECT::FIREBALLBULLET].behavior = SpitGun;
	jjObjectPresets[OBJECT::FIREBALLBULLET].lightType= LIGHT::POINT;
	jjObjectPresets[OBJECT::FIREBALLBULLET].light =55;
	jjWeapons[WEAPON::GUN8].style = WEAPON::MISSILE;
	
    jjObjectPresets[OBJECT::DRAGONFLY].energy = 2+jjDifficulty;
	jjObjectPresets[OBJECT::DRAGONFLY].special = 2+jjDifficulty;
	jjObjectPresets[OBJECT::DRAGONFLY].behavior = DragonflyX;
	jjObjectPresets[OBJECT::DRAGONFLY].points = 200;
	
	jjObjectPresets[OBJECT::FASTFEET].points = 100;
	jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
		
	jjObjectPresets[OBJECT::ROBOT].behavior = Tweedle;//Initially I used OBJECT::TWEEDLEBOSS but there was a small problem with it
	jjObjectPresets[OBJECT::ROBOT].points = 5000;//Tweedle doesn't behave like other bosses, his original "objecthit" function (or anything else that is responsible for collisions with players and bullets in the original code of JJ2) is the same as the common enemies have: 
	jjObjectPresets[OBJECT::ROBOT].energy = 125;//He receives too much damage from the special attacks and buttstomps.
	jjObjectPresets[OBJECT::ROBOT].isBlastable = false;//That wasn't good especially because I wanted him to steal player's ammo with a magnet so the player would be forced to use buttstomps and special attacks...
	//jjObjectPresets[OBJECT::ROBOT].scriptedCollisions = true;//It would be too easy to defeat him this way and I wanted to make this level and this fight really challenging. And probably I was too lazy to write onObjecthit for him
	jjObjectPresets[OBJECT::ROBOT].bulletHandling = HANDLING::HURTBYBULLET;//However, OBJECT::ROBOT had solved all of these problems
	jjObjectPresets[OBJECT::ROBOT].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::ROBOT].state = STATE::START;
	jjObjectPresets[OBJECT::ROBOT].xSpeed = 2;
	
	jjObjectPresets[OBJECT::CUCUMB].behavior = EvilSpaz;
	jjObjectPresets[OBJECT::CUCUMB].points = 1500;
	jjObjectPresets[OBJECT::CUCUMB].energy = 16;
	jjObjectPresets[OBJECT::CUCUMB].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::CUCUMB].playerHandling = HANDLING::ENEMY;
	jjObjectPresets[OBJECT::CUCUMB].state = STATE::START;
	jjObjectPresets[OBJECT::CUCUMB].xSpeed = 1;
	
	jjObjectPresets[OBJECT::HATTER].energy = 3+jjDifficulty;
	jjObjectPresets[OBJECT::HATTER].special = 3+jjDifficulty;
	jjObjectPresets[OBJECT::HATTER].behavior = HatterX;
	jjObjectPresets[OBJECT::HATTER].points = 500;
	jjObjectPresets[OBJECT::HATTER].triggersTNT=true;

	jjObjectPresets[OBJECT::SPARK].behavior = Flame;
	jjObjectPresets[OBJECT::SPARK].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::SPARK].playerHandling = HANDLING::ENEMYBULLET;
	jjObjectPresets[OBJECT::SPARK].state = STATE::FLOAT;
	jjObjectPresets[OBJECT::SPARK].lightType = LIGHT::POINT;
	jjObjectPresets[OBJECT::SPARK].light =55;
	jjObjectPresets[OBJECT::SPARK].isTarget=false;
	
	jjObjectPresets[OBJECT::STRAWBERRY].behavior = PlatFlame;
	jjObjectPresets[OBJECT::STRAWBERRY].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::STRAWBERRY].playerHandling = HANDLING::EXPLOSION;
	jjObjectPresets[OBJECT::STRAWBERRY].state = STATE::FLOAT;
	jjObjectPresets[OBJECT::STRAWBERRY].lightType = LIGHT::POINT;
	
	jjObjectPresets[OBJECT::BUBBA].energy = 7+jjDifficulty;
	jjObjectPresets[OBJECT::BUBBA].special = 7+jjDifficulty;
	jjObjectPresets[OBJECT::BUBBA].behavior = SpittingBubba;
	jjObjectPresets[OBJECT::BUBBA].points = 1000;
	jjObjectPresets[OBJECT::BUBBA].xSpeed = 1;
	jjObjectPresets[OBJECT::BUBBA].state = STATE::WALK;
	jjObjectPresets[OBJECT::BUBBA].deactivates = false;
	jjObjectPresets[OBJECT::BUBBA].isTarget = true;
	//jjObjectPresets[OBJECT::BUBBA].isBlastable = false;

	jjObjectPresets[OBJECT::UTERUS].energy = 4+jjDifficulty;
	jjObjectPresets[OBJECT::UTERUS].special = 4+jjDifficulty;
	jjObjectPresets[OBJECT::UTERUS].points = 800;
	jjObjectPresets[OBJECT::UTERUS].behavior = BubbaSpirit;
	jjObjectPresets[OBJECT::UTERUS].light = 15;
	jjObjectPresets[OBJECT::UTERUS].lightType = LIGHT::RING2;
    jjObjectPresets[OBJECT::UTERUS].playerHandling = HANDLING::ENEMY;
	jjObjectPresets[OBJECT::UTERUS].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::UTERUS].isTarget = true;
	jjObjectPresets[OBJECT::UTERUS].isBlastable = true;
	//jjObjectPresets[OBJECT::UTERUS].scriptedCollisions = true;
	
	jjObjectPresets[OBJECT::BANANA].energy = 11+jjDifficulty;
	jjObjectPresets[OBJECT::BANANA].special = 11+jjDifficulty;
	jjObjectPresets[OBJECT::BANANA].behavior = JumpyBall;
	jjObjectPresets[OBJECT::BANANA].points = 100;
	jjObjectPresets[OBJECT::BANANA].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::BANANA].isTarget = true;
	jjObjectPresets[OBJECT::BANANA].isBlastable = true;
	jjObjectPresets[OBJECT::BANANA].state = STATE::START;
	jjObjectPresets[OBJECT::BANANA].scriptedCollisions = true;
	jjObjectPresets[OBJECT::BANANA].playerHandling = HANDLING::SPECIAL;

	jjObjectPresets[OBJECT::MILK].energy = 1;
	jjObjectPresets[OBJECT::MILK].behavior = SmallJumpyBall;
	jjObjectPresets[OBJECT::MILK].points = 10;
	jjObjectPresets[OBJECT::MILK].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::MILK].isTarget = true;
	jjObjectPresets[OBJECT::MILK].isBlastable = true;
	jjObjectPresets[OBJECT::MILK].state = STATE::START;
	jjObjectPresets[OBJECT::MILK].scriptedCollisions = true;
	jjObjectPresets[OBJECT::MILK].playerHandling = HANDLING::SPECIAL;
	
	jjObjectPresets[OBJECT::PACMANGHOST].energy = 8+jjDifficulty;
	jjObjectPresets[OBJECT::PACMANGHOST].special = 8+jjDifficulty;
	jjObjectPresets[OBJECT::PACMANGHOST].behavior = BlueGhost;
	jjObjectPresets[OBJECT::PACMANGHOST].points = 300;
    jjObjectPresets[OBJECT::PACMANGHOST].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::PACMANGHOST].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::PACMANGHOST].isTarget = true;
	jjObjectPresets[OBJECT::PACMANGHOST].isBlastable = true;
	jjObjectPresets[OBJECT::PACMANGHOST].state = STATE::START;

	jjObjectPresets[OBJECT::CHESHIRE2].energy = 5+jjDifficulty;
	jjObjectPresets[OBJECT::CHESHIRE2].special = 5+jjDifficulty;
	jjObjectPresets[OBJECT::CHESHIRE2].behavior = FlamingCat;
	jjObjectPresets[OBJECT::CHESHIRE2].points = 800;
    jjObjectPresets[OBJECT::CHESHIRE2].playerHandling = HANDLING::ENEMY;
	jjObjectPresets[OBJECT::CHESHIRE2].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::CHESHIRE2].isTarget = true;
	jjObjectPresets[OBJECT::CHESHIRE2].isBlastable = true;
	jjObjectPresets[OBJECT::CHESHIRE2].state = STATE::FLOAT;
	
	jjObjectPresets[OBJECT::PINKPLATFORM].behavior = MovingPlatform;
	jjObjectPresets[OBJECT::PINKPLATFORM].state = STATE::WAIT;
	jjObjectPresets[OBJECT::PINKPLATFORM].determineCurAnim(ANIM::PINKPLAT,0);
	jjObjectPresets[OBJECT::PINKPLATFORM].isFreezable = false;
	jjObjectPresets[OBJECT::PINKPLATFORM].deactivates = false;
	
	//jjChat("/allowmouseaim on");
	//jjChat("/mouseaim on");
	jjChat("/fireball on");
}
const string MUSICFILENAME = "funkyg.j2b";
void onLevelReload() {
 jjAlert(Hints[jjRandom()%8]); 
elapsed=0;v=0;z=0;b=0;
cats=false; bombs=false; boss=false; normal=true;
killedcats=0; killedbombs=0;killedsmallbombs=0;
jjMusicLoad(MUSICFILENAME);
	jjPalette.gradient(207, 235,23,             207, 235,23,         96, 1, 1.0);
	jjPalette.gradient(147, 207,15,             147, 207,15,         97, 1, 1.0);
	jjPalette.gradient(91, 179,7,               91, 179,7,           98, 1, 1.0);
	jjPalette.gradient(47, 151,0,               47, 151,0,           99, 1, 1.0);
	jjPalette.gradient(15, 127,0,               0, 43, 23,           100, 4, 1.0);
	jjPalette.gradient(243, 163, 95, 			43, 15, 7, 			 104, 8, 1.0);
	jjPalette.gradient(255, 216, 59, 			199, 30, 0, 		 112, 8, 1.0);
	jjPalette.gradient(194, 26, 0, 			    43, 0, 0, 		     120, 8, 1.0);
	jjPalette.gradient(229, 131, 11,            66, 8, 3, 			 128, 8, 1.0);
	jjPalette.gradient(255, 220, 12,            122, 105, 6,         136, 8, 1.0);
	jjPalette.gradient(240, 240, 173,           179, 139, 59,        144, 8, 1.0);
	jjPalette.gradient(168, 119, 50,            64, 21, 0,           152, 8, 1.0);
	jjPalette.gradient(126, 242, 205,           0, 26, 25,           160, 16, 1.0);
	jjPalette.gradient(231, 251, 255,           51, 155, 203,        176, 16, 1.0);
	jjPalette.gradient(47, 147, 199,            0, 47, 115,          192, 16, 1.0);
	jjPalette.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	jjSetFadeColors(0,40,80);
}

void onMain() {
jjPLAYER@ play = jjLocalPlayers[0];
if (paused) {
play.keyUp = play.keyDown = play.keyRight = play.keyLeft = play.keyFire = play.keyRun = play.keyJump = false;
}
if (play.powerup[1] ==true)
{jjWeapons[1].spread == SPREAD::RFNORMAL;}
if (play.currWeapon == WEAPON::GUN8&&play.fly==0)
{play.keyUp=false;//This prevents you from shooting the spitgunbullets up. There is simply no animation of them flying vertically.
if (jjKey[UP]&&jjKey[SHOOT]&&shootpressed<=1){
shootpressed++;
play.showText("@@I can't fire up @@with this weapon@@because of the @@damned lack of animations!");}
}
if (!play.noFire&&jjKey[SHOOT]&&play.currWeapon == WEAPON::TNT&&g<=210) 
{g++;
float yPos = play.yPos - 25;
float xPos = play.xPos - 30;
for (int i = 0; i <= g/7; ++i) {
						jjDrawSprite(xPos, yPos, ANIM::BRIDGE, 0, 0, 0, SPRITE::RESIZED,16);
					xPos += 3;
				}
				
}
if(!play.noFire&&!jjKey[SHOOT]&&g>=0)
{g--;
float yPos = play.yPos - 25;
float xPos = play.xPos - 30;
for (int i = 0; i <= g/7; ++i) {
						jjDrawSprite(xPos, yPos, ANIM::BRIDGE, 0, 0, 0, SPRITE::RESIZED,16);
					xPos += 3;
				}
				}
				
 if (lastTile != play.currTile) { zoneExited(); }
		else if (dark) {
		
	jjSetFadeColors(x,-x/10,x/100);
jjPalette.apply();				
			}					
if (!play.noFire&&jjKey[SHOOT]&&play.currWeapon ==WEAPON::TNT&&g==211) 
			{
float yPos = play.yPos - 25;
float xPos = play.xPos - 30;
for (int i = 0; i <= g/7; ++i) {
						jjDrawSprite(xPos, yPos, ANIM::BRIDGE, 0, 0, 0, SPRITE::RESIZED,16);
					xPos += 3;
				}
			
			}	
  for (int i = 0;  i < jjObjectCount; i++)
    if (jjObjects[i].isActive && jjObjects[i].creatorType == CREATOR::PLAYER) {
      //Create bomb
      if (jjObjects[i].eventID == OBJECT::TNT && jjObjects[i].state != STATE::EXPLODE) {//This snippet was written by Foly.
        jjDeleteObject(i);                                                              //I modified it, though
        CreateBomb(i);                                                                  
        continue;
      }
   
      //Destroy bomb
      if (jjObjects[i].eventID == OBJECT::TACO ) {
        jjObjects[i].age++;
        if (jjObjects[i].age > cBombLifeTime)
          DestroyBomb(i);
        continue;
      }
    }
//if ((elapsed & 70) == 0)
//{jjAlert("g "+ formatInt(g, "1"));
//jjAlert("jjGameTicks "+ formatInt(jjGameTicks, "1"));
//jjAlert("elapsed "+ formatInt(elapsed, "1"));
//}
++elapsed;
if (start && //Switching from night to day at the very beginning of the level.
	(jjGameTicks & 3) == 0) { //only update the palette every fourth tick, to avoid making JJ2 run ridiculously slow in the meantime
		jjPalette.reset();
		jjPalette.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			FineDay,	//source
			jjGameTicks / 1000.0	//opacity
		);
		jjPalette.apply();
		jjSetFadeColors(0,jjGameTicks/25,jjGameTicks/12.5);
		jjLocalPlayers[i].lighting = 80+jjGameTicks/50;
		if (jjGameTicks == 1000) { //End this scene.
			start = false;
			normal=true;
		}
	}



  for(int i = 1; i < jjObjectCount; i++) {
    if(jjObjects[i].isActive && jjObjects[i].eventID == OBJECT::SMOKERING&&boss&&jjDifficulty<4) { //If you play EASY, MEDIUM or HARD Tweedle fires smokerings and they behave themselves
      jjObjects[i].ySpeed = 0;                                                                     //like common bullets not counting the fact that they make you dizzy instead of getting hurt and don't vanish after collision with player
      jjObjects[i].xPos = jjObjects[i].xPos+(jjObjects[i].direction*2);                            //but if you play on TURBO mode smoke rings move back and forth like boomerang.
       }                                                                                           //It is their initial way of motion and it is really hard to avoid them if there are lots of them
	 }                                                                                             //This effect doesn't influence Caterpillar's rings because it starts after you touch the ActivateBoss event
                                                                                                   //Based on "Smoke Ring Gun" snippet written by szmol96
  
if (play.stoned!=0)
{ stoned=true;
for (i = 0; i < 254; i++) {
				jjPalette.color[i+1].setHSL(
					myPal.color[i+1].getHue()/20 + jjGameTicks,
					myPal.color[i+1].getSat()/20+ 240,//before the release of the new version of JJ2 (dated by 6 April 2015) this thing worked perfectly without adding anything to saturation
					myPal.color[i+1].getLight()//but in the newest version there suddenly appeared some problems with it, so I had to add some number (240 seems to be the most suitable) to it otherwise half of colours stayed grey
				);}
				apply();
}
else if (play.stoned==0)
{stoned=false;}
		if(bombs&&(killedbombs<bombgoal||killedsmallbombs<smbombgoal))
		{onBombfall();}
		//if(cats&&(killedcats<catgoal))
		//{onCatAttack();}
		
		 if(bombs&&killedbombs<bombgoal&&killedsmallbombs<smbombgoal&& scene&&(x & 3) == 0)	{
		 normal=false;
		 
			v++;
			jjPalette.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			Bloody,	//source
			v/300.0	//opacity
				);
		jjPalette.apply();
		if (v==300){
		scene=false;
		jjSetFadeColors(40,0,0);
jjLocalPlayers[i].lighting = 80;}
	}
				 if(cats && killedcats<catgoal&&scene&&(!bombs&&(jjGameTicks & 10) == 0)&&(play.stoned==0))	{
	normal=false;
	bombs=false;
	if (z<=300)
	{z++;}
			jjPalette.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			Golden,	//source
			z/300.0	//opacity
			
		);
		jjSetFadeColors(0,40-z/7.5,80-z/3.75);
		jjPalette.apply();
			if (killedcats>=catgoal)	{scene=false;
jjLocalPlayers[i].lighting = 80;}
		}
		
				 if(boss&&(play.stoned==0))	{
				 jjObjectPresets[OBJECT::HATTER].isTarget==false;
				 jjObjectPresets[OBJECT::CHESHIRE2].isTarget==false;
	normal=false;
	cats=false;
	bombs=false;
	if (b<=1000)
	{b++;}
	if (b==100)
	{play.boss=jjAddObject(OBJECT::ROBOT, 381*32, 35*32);}
			jjPalette.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			Grim,	//source
			b/1000.0	//opacity
			
		);
		jjLocalPlayers[i].lighting = 100-b/20;
		jjSetFadeColors(0,40-b/25,80-b/12.5);
		jjPalette.apply();
		}
		
	if(((killedcats>=catgoal && !bombs&&cats)||(killedbombs>=bombgoal&&killedsmallbombs>=smbombgoal&&bombs)))
	//jjPalette.fill(255,255,255, elapsed/200);
	
	{cats=false;
	bombs=false;}
	
	
						 if((normal||(killedcats>=catgoal && !bombs)||(killedbombs>=bombgoal&&killedsmallbombs>=smbombgoal))&&(play.stoned==0)&&!boss&&jjGameTicks&70==0)	{
						 stoned=false;
						 z==0;
	jjPAL newPal=jjPalette;
			newPal.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			FineDay,	//source
			 elapsed/1000.0	//opacity
			);
			scene=true;
		bombs=false;
			
		newPal.apply();
		jjSetFadeColors(0,40,80);
jjLocalPlayers[i].lighting = 100;
jjMusicLoad("funkyg.j2b");
		}
		if (killedcats>=catgoal)
		{jjTriggers[1]=true;}
		}

		void zoneExited() {
	if (true) myPal = jjPalette;
	else apply(myPal);
}

		
void apply(jjPAL pal = jjPalette) {
	jjSetFadeColors(
		pal.color[207].red,
		pal.color[207].green,
		pal.color[207].blue
	);
	pal.apply();
}

void DisplayHealth(jjOBJ@ enemy) {
	int health = enemy.energy;
	int sp = enemy.special;
	float xPos = enemy.xPos - 0.5*(jjObjectPresets[enemy.eventID].energy);
	float xPos2 = enemy.xPos - 0.5*(jjObjectPresets[enemy.eventID].energy)-6;
	float yPos = enemy.yPos - 34;
		while (sp > 0) {
		jjDrawSprite(xPos2, yPos-6, ANIM::BRIDGE, 4, 0, 0,SPRITE::SINGLECOLOR, 0);//That's a pity that a sprite can't be
		xPos2 += 3;                                                               //singlecolor and resized at a same time.
		sp -= 1;}                                                                 //At least I failed to make it...
	while (health > 0) {
		jjDrawSprite(xPos+1, yPos, ANIM::PICKUPS, 41, 0, 0, SPRITE::RESIZED,16);
		xPos += 3;
		health -= 1;
	}
	}
	
void GreatCarrot (jjOBJ@ obj)	{
obj.behave(BEHAVIOR::PICKUP,false);
//obj.yPos = obj.yPos + jjSin(jjGameTicks*10)/2;
//obj.xPos = obj.xPos + jjCos(jjGameTicks*10)/5;
	switch (obj.state) {
		case STATE::FLOAT:	
jjDrawSprite(obj.xPos, obj.yPos, ANIM::PICKUPS, 21, 0, 0, SPRITE::RESIZED,54- abs(12*jjSin(jjGameTicks*5))); 	
			break;
		case STATE::ACTION:			
			obj.lightType = LIGHT::RING2;
			if (obj.light < 5) obj.light = 5;
			else obj.light += 2;
			if (obj.light % 15 == 0) jjSample(obj.xPos, obj.yPos, SOUND::COMMON_HARP1, 63 - obj.light, 4500 + (500*obj.light));
			if (obj.light > 100) obj.state = STATE::KILL;
			break;
		case STATE::KILL:
			obj.lightType = LIGHT::NONE;
			obj.light = 0;
			obj.delete();
			break;
	}
}
	void CreateBomb(int objectID) { //The modified version of Foly's code snippet
  int playerID = jjObjects[objectID].creator - 32768;//You can make bomb fly longer range by holding fire button. It also draws an indicator of strength above rabbit's head
  int bombID = jjAddObject(OBJECT::TACO, jjPlayers[playerID].xPos, jjPlayers[playerID].yPos, jjPlayers[playerID].playerID, CREATOR::PLAYER);
  jjObjects[bombID].objType = 10;
  jjObjects[bombID].determineCurAnim(ANIM::AMMO, 1);
  jjObjects[bombID].xPos = jjObjects[bombID].xPos + jjObjects[bombID].xSpeed+jjObjects[bombID].var[7]/65536;
  jjObjects[bombID].yPos = jjObjects[bombID].yPos + jjObjects[bombID].ySpeed+jjObjects[bombID].var[7]/65536;
  jjObjects[bombID].xSpeed = g/30*jjPlayers[playerID].direction+cBombSpeed*jjPlayers[playerID].direction;
  jjObjects[bombID].ySpeed = -g/30+ cBombPlayerSpeed*jjPlayers[playerID].xSpeed/4; 
}
 
void DestroyBomb(int bombID) {
  int explosionID = jjAddObject(OBJECT::TNT, jjObjects[bombID].xPos, jjObjects[bombID].yPos, jjObjects[bombID].creator, CREATOR::PLAYER);
  jjDeleteObject(bombID);
  jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 1, true);
  jjObjects[explosionID].killAnim = jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 5, false);
  jjObjects[explosionID].state = STATE::EXPLODE;
  jjSample(jjObjects[explosionID].xPos, jjObjects[explosionID].yPos, SOUND::COMMON_EXPL_TNT);
}

/*void onDrawLayer4(jjPLAYER@ p, jjCANVAS@ canvas) {
	for (uint i = 0; i < Shop[curScreen].length; ++i) {
		canvas.drawString(
			p.cameraX + (jjResolutionWidth - 455),
			
				p.cameraY + 192 + i*128 :
				p.cameraY + 87  + i*32,
			"#" + Shop[curScreen][i],
			STRING::MEDIUM,
			(i == curString) ? STRING::SPIN : STRING::NORMAL,
			10
		);
	}

}*/
	
	void Toadstool (jjOBJ@ obj)	{
obj.behave(BEHAVIOR::PICKUP,false);
obj.yPos = obj.yPos + 6*jjSin(jjGameTicks*10);
//obj.xPos = obj.xPos + jjCos(jjGameTicks*10)*2;
jjDrawTile(obj.xPos - 14, obj.yPos - 15, 133+4*abs(jjSin(jjGameTicks*10)));			
	}

	void JumpyBall(jjOBJ@ enemy)  {
	switch (enemy.state){
	case STATE::START: {
		enemy.state = STATE::FALL;
		enemy.xSpeed = ((jjRandom() & 15) - 8.5) / 3;
		enemy.ySpeed = 0;
		enemy.yAcc=0;
		break;
		
	} 
		case STATE::FREEZE:
			if (enemy.freeze > 0) {
				enemy.draw();
				enemy.freeze -= 2;
			}
			if (enemy.freeze < 2) {
				enemy.unfreeze(1);
				enemy.state = enemy.oldState;
			}
			break; 
	case  STATE::DEACTIVATE: {
		enemy.deactivate();
		break;
	} case STATE::KILL: {
	killedbombs++;
		enemy.grantPickup(jjLocalPlayers[0], 1);
		enemy.deactivate();
		break;
	} case STATE::FALL: {
	
	if (enemy.justHit != 0)
		@spawnedObject = jjObjects[jjAddObject(OBJECT::MILK, enemy.xPos, enemy.yPos)];
		enemy.determineCurAnim(ANIM::SPIKEBOLL,0);
		enemy.determineCurFrame();
		if (jjMaskedPixel(enemy.xPos + enemy.xSpeed, enemy.yPos)) {
			enemy.xSpeed = -1.01*enemy.xSpeed;
			enemy.xPos = enemy.xPos+enemy.xSpeed;
		} else if (jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed)) {
			enemy.ySpeed = -0.95*enemy.ySpeed;
			enemy.yPos = enemy.yPos+enemy.ySpeed;
			jjSample(enemy.xPos, enemy.yPos, SOUND::SPRING_BOING_DOWN);
		}
		else if (jjMaskedPixel(enemy.xPos+enemy.xSpeed, enemy.yPos + enemy.ySpeed)) {
			enemy.ySpeed = -0.95*enemy.ySpeed;
			enemy.xSpeed = -1.01*enemy.xSpeed;
			enemy.xPos = enemy.xPos+enemy.xSpeed;
			enemy.yPos = enemy.yPos+enemy.ySpeed;
			jjSample(enemy.xPos, enemy.yPos, SOUND::SPRING_BOING_DOWN);
		}
		enemy.xPos = enemy.xPos + enemy.xSpeed;
		enemy.yPos = enemy.yPos + enemy.ySpeed;
		enemy.ySpeed = enemy.ySpeed + .15;
	}
break;
	}
		DisplayHealth(enemy);
		enemy.draw();
	}
	
	
	void SmallJumpyBall (jjOBJ@ enemy)  {
		switch (enemy.state){
	case STATE::START: {
		enemy.state = STATE::FALL;
		enemy.xSpeed = ((jjRandom() & 15) - 7.5) / 3;

		break;
			
	}
	case STATE::FREEZE:
			if (enemy.freeze > 0) {
				enemy.draw();
				enemy.freeze -= 2;
			}
			if (enemy.freeze < 2) {
				enemy.unfreeze(3);
				enemy.state = enemy.oldState;
			}
			break; 
	case  STATE::DEACTIVATE: {
		enemy.deactivate();
		break;
	} case STATE::KILL: {
	++killedsmallbombs;
		enemy.deactivate();
		break;
	} case STATE::FALL: {
		enemy.determineCurAnim(ANIM::ROBOT,0);
		enemy.determineCurFrame();
		if (jjMaskedPixel(enemy.xPos + enemy.xSpeed, enemy.yPos)) {
			enemy.xSpeed = -0.99*enemy.xSpeed;
		} else if (jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed)) {
			enemy.ySpeed = -0.99*enemy.ySpeed;
			jjSample(enemy.xPos, enemy.yPos, SOUND::SPRING_BOING_DOWN);
		}
		enemy.xPos = enemy.xPos + enemy.xSpeed;
		enemy.yPos = enemy.yPos + enemy.ySpeed;
		enemy.ySpeed = enemy.ySpeed + .5;
	
	}
	break;
	}
		enemy.draw();
	}
	
	
		void BlueGhost (jjOBJ@ enemy)  {
		enemy.determineCurAnim(ANIM::ZSPARK,0);
		enemy.frameID = (jjGameTicks/10) & 31;
		enemy.determineCurFrame();	
		switch (enemy.state){
	case STATE::START: {
		enemy.state = STATE::FLOAT;
		enemy.xSpeed=1;
		enemy.ySpeed = 0.1;
		break;
			
	}
	case STATE::FREEZE:
			if (enemy.freeze > 0) {
				enemy.draw();
				enemy.freeze -= 2;
			}
			if (enemy.freeze < 2) {
				
				enemy.state = enemy.oldState;
			}
			break; 
	case  STATE::DEACTIVATE: {
		enemy.deactivate();
		break;
	} case STATE::KILL: {
	if (jjRandom() & 2 == 0)
	{jjAddObject(OBJECT::TNTAMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
		enemy.delete();
		break;
	} case STATE::FLOAT: {
	
		 if (jjLocalPlayers[0].xPos != enemy.xPos) {enemy.direction = -enemy.xSpeed;}
		 else if (jjLocalPlayers[0].xPos == enemy.xPos) {enemy.direction =1;}	
		if (jjMaskedPixel(enemy.xPos + enemy.xSpeed, enemy.yPos)) {
			enemy.xSpeed = -enemy.xSpeed;
			enemy.putOnGround(true);
		} else if (jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed)) {
			enemy.ySpeed = -0.95*enemy.ySpeed;
			enemy.putOnGround(true);
			jjSample(enemy.xPos, enemy.yPos, SOUND::SPRING_BOING_DOWN);
		}
		else if (!jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed)) {
		enemy.putOnGround(false);
			enemy.ySpeed == 1;
		}
		enemy.xPos = enemy.xPos + enemy.xSpeed;
		enemy.yPos = enemy.yPos + enemy.ySpeed;
		enemy.ySpeed = enemy.ySpeed + .05;
		
if (enemy.justHit != 0 )
{enemy.ySpeed = 1.1*enemy.ySpeed;
enemy.xSpeed = 1.1*enemy.xSpeed;
}
if (jjLocalPlayers[0].xPos > enemy.xPos && jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed) ){enemy.xSpeed =abs(enemy.xSpeed); }
else if (jjLocalPlayers[0].xPos < enemy.xPos && jjMaskedPixel(enemy.xPos, enemy.yPos + enemy.ySpeed) )
{enemy.xSpeed = -abs(enemy.xSpeed);}
		if (jjRandom() & 1 == 0)	{
				
			
				jjOBJ@ bullet = jjObjects[enemy.fireBullet(OBJECT::BOMB)];
				bullet.playerHandling = HANDLING::ENEMYBULLET;	
				bullet.animSpeed = 2;				
				bullet.xPos=enemy.xPos;
				bullet.yPos=enemy.yPos;
				if (bullet.age==0) {bullet.state = STATE::KILL;}
			}
	}

	break;
	}
	
	DisplayHealth(enemy);
		enemy.draw();
	}
	
	void SpittingBubba(jjOBJ@ enemy) {
	if (enemy.energy<=0)
	{enemy.state=STATE::KILL;}
	switch (enemy.state) {
		case STATE::WALK:
		enemy.behave(BEHAVIOR::WALKINGENEMY);
		enemy.determineCurAnim(ANIM::BUBBA, 5);	
										
			 if (enemy.findNearestPlayer(64*800) > -1 && ++enemy.counter > 36) enemy.state = STATE::IDLE;
				if (enemy.energy == 0)
					enemy.state = STATE::KILL;
			break;
			case STATE::IDLE:
			enemy.frameID = enemy.counter/5;
			enemy.determineCurFrame();
			
			switch (jjRandom() & 3) {
				
				case 0:  
				case 1:
				
					enemy.state = STATE::ACTION;
					enemy.determineCurAnim(ANIM::BUBBA, 0);
					enemy.counter = 0;
					break;
					
				case 2:
				
					enemy.state = STATE::WALK;
					enemy.determineCurAnim(ANIM::BUBBA, 5);
					enemy.counter = 0;
					
					break;
					
					}
			break;
			
			
		case STATE::ACTION:
		if (++enemy.counter < 36) {
			enemy.frameID = enemy.counter/5;
			enemy.determineCurFrame();
			enemy.direction = (jjLocalPlayers[0].xPos < enemy.xPos) ? -1 : 1;
				   if (enemy.justHit == 0)
			if (enemy.counter == 25-jjDifficulty*2+2*jjDifficulty*jjDifficulty||enemy.counter == 25 || enemy.counter == 25+jjDifficulty*2) {
			//if difficulty is easy Bubba spits once per every "state::action", if normal- twice, it hard or turbo- three times.
		jjOBJ@ bullet = jjObjects[enemy.fireBullet(OBJECT::BLASTERBULLET)];
				bullet.determineCurAnim(ANIM::HATTER, 3);
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.xPos = enemy.xPos;
				bullet.yPos = bullet.yPos - 12; 
				bullet.xSpeed = bullet.xSpeed*(jjDifficulty+1)/4;
				bullet.ySpeed = (-(jjRandom() & 7)+2)*(jjDifficulty+1)/4;
				bullet.animSpeed = 1;
				jjSample(enemy.xPos, enemy.yPos, SOUND::HATTER_PTOEI);
				
				
				
			}
		} else {
			enemy.frameID = enemy.counter = 0;
			enemy.determineCurAnim(ANIM::BUBBA, 5);
			enemy.state = STATE::IDLE;
		}
		break;
	
			
		case STATE::FREEZE:
			if (enemy.freeze > 0) {
				enemy.draw();
				enemy.freeze -= 4;
			}
			if (enemy.freeze < 4) {
				enemy.unfreeze(0);
				enemy.state = enemy.oldState;
			}
			break; 
	
			
		case STATE::KILL:
			killedBUBBAs++;
			if (jjRandom() & 2 == 0)
			{jjAddObject(OBJECT::GUN8AMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
			enemy.particlePixelExplosion(2);
			@spawnedObject = jjObjects[jjAddObject(OBJECT::UTERUS, enemy.xPos, enemy.yPos)];
			spawnedObject.determineCurAnim(ANIM::BUBBA, 1);
			jjSample(enemy.xPos, enemy.yPos, SOUND::RAPIER_GOSTRIP);
			enemy.delete();
			break;
			}
		
		enemy.draw();
		DisplayHealth(enemy);
		
	}
	
		void BubbaSpirit(jjOBJ@ enemy) {
		enemy.determineCurAnim(ANIM::BUBBA, 1);
		enemy.behave(BEHAVIOR::BEE);
		DisplayHealth(enemy);
		}
	
void NPC(jjOBJ@ obj) {
	if (obj.state == STATE::START) {
		
				if (jjIsTSF) obj.determineCurAnim(ANIM::SPAZ,101 );
				else obj.determineCurAnim(ANIM::SPAZ, 101);
				obj.xSpeed = 2.5;
	
		obj.state = STATE::WALK;
	}
	obj.behave(BEHAVIOR::WALKINGENEMY);
}

void FlyingAmmo (jjOBJ@ obj) {
u=(jjRandom() & 5);
obj.behave(BEHAVIOR::SEEKERBULLET);
if (obj.state == STATE::START) {
		obj.state = STATE::FLY;
	}
	if (u==0)
		{obj.determineCurAnim(ANIM::AMMO, 57);}
		if (u==1)
		{obj.determineCurAnim(ANIM::AMMO, 49);}
		if (u==2)
		{obj.determineCurAnim(ANIM::AMMO, 1);}
		if (u==3||u==4)
		{obj.determineCurAnim(ANIM::PICKUPS, 78);}
}
	
	void onFunction0(jjPLAYER@ play) {
	jjPalette.gradient(255, 255,0,              42, 42, 4,           96, 8, 1.0);
	jjPalette.gradient(171, 171, 160, 			10, 10, 9, 			 104, 8, 1.0);
	jjPalette.gradient(255, 191, 0, 			214, 94, 0, 		 112, 3, 1.0);
	jjPalette.gradient(180, 71, 0, 			    27, 0, 0, 		     115, 5, 1.0);
	jjPalette.gradient(255, 255, 20, 			199, 84, 8, 	     120, 8, 1.0);
	jjPalette.gradient(255, 109, 48,             210, 100, 38, 			 128, 3, 1.0);
	jjPalette.gradient(205, 79, 8,             0, 0, 0, 			 131, 5, 1.0);
	jjPalette.gradient(128, 0, 0,              0, 0, 0, 			 136, 8, 1.0);
	jjPalette.gradient(255, 0, 0,               19, 0, 0,            144, 16, 1.0);
	jjPalette.gradient(255, 204, 156,           3, 2, 2,             160, 16, 1.0);
	jjPalette.gradient(255, 0, 0,               30, 0, 0,            176, 32, 1.0);
	jjPalette.gradient(247, 132, 20,            4, 2, 0,             208, 16, 1.0);
	jjSetFadeColors(30,0,0);
	jjPalette.apply(); 
	jjLocalPlayers[i].lighting = 80;
	play.showText("@@@@Bloody", STRING::SMALL);
	}	
	
	void onFunction1(jjPLAYER@ play) {
	jjSetFadeColors(0,40,80);
	Twilight.apply(); 
jjLocalPlayers[i].lighting = 100;
play.showText("@@@@Fine Day", STRING::SMALL);
	}
		 
		void onPlayerTimerEnd(jjPLAYER@ play) {
	play.jumpStrength = play.jumpStrength + 8; 
}
	void onFunction2(jjPLAYER@ play) {
	jjPalette.gradient(247, 102,23,             40, 17, 6,           96, 8, 1.0);
	jjPalette.gradient(36, 14, 41, 		     	0, 0, 15, 			 104, 8, 1.0);
	jjPalette.gradient(242, 173, 30, 			138, 27, 55, 		 112, 8, 1.0);
	jjPalette.gradient(93, 22, 38, 			    7, 2, 2, 		     120, 8, 1.0);
	jjPalette.gradient(179, 73, 108,            50, 20, 31, 	     128, 8, 1.0);
	jjPalette.gradient(44, 18, 27,              3, 1, 1,             136, 8, 1.0);
	jjPalette.gradient(255, 190, 23,            196, 92, 37,         144, 8, 1.0);
	jjPalette.gradient(183, 81, 42,             60, 7, 21,           152, 8, 1.0);
	jjPalette.gradient(150, 174, 182,           107, 77, 56,         160, 8, 1.0);
	jjPalette.gradient(98, 65, 47,              9, 0, 0,             168, 8, 1.0);
	jjPalette.gradient(22, 30, 77,              0, 1, 1,             176, 32, 1.0);
	jjPalette.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	jjSetFadeColors(0,0,0);
jjPalette.apply(); 	
jjLocalPlayers[i].lighting = 80;
play.showText("@@@@Gold Mine", STRING::SMALL);
	}
	
	
	void onFunction3(jjPLAYER@ play) {
	jjPAL newPal;
    newPal.load("Psych1.j2t");
	newPal.apply();

	
	
	
	jjSetFadeColors(40,0,20);
    
	jjLocalPlayers[i].lighting = 100;
	play.showText("@@@@Psych1", STRING::SMALL);
	}
	
	void onFunction4(jjPLAYER@ play) {
	jjPAL newPal;
    newPal.load("Psych2.j2t");
    newPal.apply();
	jjSetFadeColors(0,0,20);
	jjLocalPlayers[i].lighting = 67;
	play.showText("@@@@Psych2", STRING::SMALL);
	}
	
	void onFunction5(jjPLAYER@ play) {
	jjPalette.gradient(24, 255,253,             0, 57, 56,           96, 8, 1.0);
	jjPalette.gradient(0, 14, 71, 		     	0, 0, 15, 			 104, 8, 1.0);
	jjPalette.gradient(20, 253, 120, 			10, 137, 65, 		 112, 8, 1.0);
	jjPalette.gradient(9, 132, 62, 			    0, 49, 12, 		     120, 8, 1.0);
	jjPalette.gradient(190, 255, 18,            5, 5, 0, 	          128, 8, 1.0);
	jjPalette.gradient(0, 11, 8,                0, 5, 0,             136, 8, 1.0);
	jjPalette.gradient(25, 150, 123,            33, 238, 177,         144, 5, 1.0);
	jjPalette.gradient(28, 225, 168,            24, 144, 117,         149, 3, 1.0);
	jjPalette.gradient(23, 138, 112,            0, 22, 11,           152, 8, 1.0);
	jjPalette.gradient(0, 255, 255,             10, 155, 155,         160, 8, 1.0);
	jjPalette.gradient(8, 144, 144,             0, 2, 2,             168, 8, 1.0);
	jjPalette.gradient(0, 0, 3,                 0, 83, 83,             176, 32, 1.0);
	jjPalette.gradient(255, 199, 139,           91, 79, 7,           208, 16, 1.0);
	jjSetFadeColors(0,0,0);
jjPalette.apply(); 	
jjLocalPlayers[i].lighting = 40;
play.showText("@@@@Grim Night", STRING::SMALL);
	}
	
	void onFunction7(jjPLAYER@ play){
	bombs = true;
	jjSetFadeColors(30,0,0); 
	jjLocalPlayers[i].lighting = 80;
	jjMusicLoad("Metal.mod");
	
	jjAddObject(OBJECT::BANANA,  180*32, 50*32);
	
		if (killedbombs==0&&killedsmallbombs==0)	
		{jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
		if (particle !is null) {
		particle.xPos = play.xPos;
		particle.yPos = play.yPos;
		particle.string.text = "|Alert!";
		particle.ySpeed = -0.4;
		play.showText("@@@BEWARE OF BOMBS!", STRING::SMALL);
		}
	}
	}

void onFunction9(jjPLAYER@ play) {
if (killedcats==0) {
jjMusicLoad("Metal.mod");
cats = true;
play.showText("@@@@Kill enough cats @@@@to open the barrier", STRING::SMALL);}
}

void onFunction10(jjPLAYER@ play) {
play.kill();
}
	
void onFunction12(jjPLAYER@ play) {
boss=true;
//jjTexturedBGTexture = TEXTURE::WTF;
//jjTexturedBGStyle = TEXTURE::TUNNEL;
play.activateBoss();
if (jjRandom() & 2==0)
{jjMusicLoad("boss2.j2b");}
else
{jjMusicLoad("boss1.j2b");}
jjOBJ@ boss = jjObjects[play.boss];
}
	void onFunction13(jjPLAYER@ play) {
	dark = true; 
	lastTile = play.currTile;
	Twilight.apply(); 
	play.showText("@@@@Dynamic", STRING::LARGE);
}

void onCatAttack() {

			uint16 randomTargetX = (44 + (jjRandom()&14)) * 32;
			uint16 randomTargetY = (15 + (jjRandom()&12)) * 32;
			jjAddObject(OBJECT::CHESHIRE2, randomTargetX, randomTargetY);
		
		}

void onBombfall() {
if (jjGameTicks % 350/((jjDifficulty+1)^(0.5) )== 0) {
			uint16 randomTarget = (160 + (jjRandom()&35)) * 32;
			jjAddObject(OBJECT::BANANA, randomTarget, 40*32);
		}
		}
		

	void onFunction15(jjPLAYER@ play) {
 jjTriggers[15]=true;
}

	void onFunction20(jjPLAYER@ play) {
 jjTriggers[20]=true;
}

	void onFunction27(jjPLAYER@ play) {
 if(bombs)
 {play.showText("@@Destroy bombs enough to@@ Activate this platform", STRING::SMALL);
 }
}

	void onFunction28(jjPLAYER@ play) {
jjTriggers[28]=true;
}
	void onFunction30(jjPLAYER@ play) {
 jjTriggers[30]=true;
}

	void onFunction31(jjPLAYER@ play) {
 jjTriggers[31]=true;
}

	void onFunction32(jjPLAYER@ play) {
 jjTriggers[32]=true;
}



	void onFunction34(jjPLAYER@ play) {
 jjTriggers[34]=true;
}
				
void DragonBreath (jjOBJ@ flame) {
	if (flame.state == STATE::START) 
	flame.state = STATE::FLY;
	jjPLAYER@ play = jjPlayers[flame.creatorID];
	flame.xPos = flame.xPos + flame.xSpeed/2+flame.var[7]/65536;;
	flame.yPos = flame.yPos + flame.ySpeed/2;
	if (jjMaskedPixel(flame.xPos, flame.yPos))
		flame.state = STATE::EXPLODE;
	if (flame.state == STATE::EXPLODE) {
		flame.behavior = BEHAVIOR::EXPLOSION2;
	}
	flame.frameID = (++flame.counter >> 1)/20 % 9;
	flame.determineCurFrame();
	flame.draw();
	jjDrawSpriteFromCurFrame(flame.xPos, flame.yPos, flame.curFrame, flame.direction, SPRITE::NEONGLOW,2);
	flame.light= ++flame.counter/70;
	if (flame.counter>350)
	{flame.state=STATE::EXPLODE;
	}
}

void SpitGun (jjOBJ@ spit) {
	if (spit.state == STATE::START)
	if (jjSoundEnabled) 
	{jjSample(spit.xPos, spit.yPos, SOUND::HATTER_PTOEI);}
	spit.state = STATE::FLY;
	if (jjGameTicks %6==0)// Causes damage every sixth tick
	{spit.animSpeed=1;}//otherwise this weapon would be too powerful
	else//and it would be too easy to defeat Tweedle with it
	{spit.animSpeed=0;}
	jjPLAYER@ play = jjPlayers[spit.creatorID];
	spit.xPos = spit.xPos + spit.xSpeed/2+spit.var[7]/65536-abs(g/40)*play.direction;
	if (jjMaskedPixel(spit.xPos, spit.yPos)||spit.xSpeed==0)
		spit.state = STATE::EXPLODE;
	if (spit.state == STATE::EXPLODE) {
		spit.behavior = BEHAVIOR::EXPLOSION2;
	}
	spit.determineCurFrame();
	spit.draw();
}

	void DragonflyX(jjOBJ@ enemy) {
		enemy.behave(BEHAVIOR::DRAGONFLY);
		DisplayHealth(enemy);
		}
				
	
		
	
	void HatterX(jjOBJ@ enemy) {
		enemy.behave(BEHAVIOR::HATTER);
	    DisplayHealth(enemy);
		if ((enemy.energy==0&&jjRandom() & 2 == 0)&&(boss=false))
			{jjAddObject(OBJECT::GUN8AMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
	    }
	
	void FlamingCat(jjOBJ@ enemy) {
	if (enemy.energy == 0) enemy.state = STATE::KILL;
	
		switch (enemy.state) {
		case STATE::FLOAT:
		enemy.bulletHandling = HANDLING::IGNOREBULLET;
		enemy.determineCurAnim(ANIM::CAT2, 3);	
		enemy.determineCurFrame();	
		
			if (enemy.findNearestPlayer(164*164) > -1) 
			{enemy.state = STATE::ATTACK;
			int u=((jjRandom() & 19) - 9.5);}
			break;
	 case STATE::ATTACK:
	 enemy.playerHandling = HANDLING::ENEMY;
	 enemy.bulletHandling = HANDLING::HURTBYBULLET;
	 ++enemy.counter;
	 if (enemy.counter == 1)
	 {jjSample(enemy.xPos, enemy.yPos, SOUND::INTRO_GREN1);}
	 
	 enemy.direction = (jjLocalPlayers[0].xPos < enemy.xPos) ? -1 : 1;
	 	if (jjRandom() & 2 == 0 && jjDifficulty<3) {
			jjOBJ@ obj = jjObjects[enemy.fireBullet(OBJECT::SPARK)];
			obj.determineCurAnim(ANIM::AMMO,55);
			obj.determineCurFrame();	
			obj.yPos = enemy.yPos;
			obj.xPos = enemy.xPos;
		}
		else if (jjRandom() & 2 == 0 && jjDifficulty>2){
	 
			jjOBJ@ obj = jjObjects[enemy.fireBullet(OBJECT::SPARK)];
			obj.determineCurAnim(ANIM::AMMO,0);
			obj.determineCurFrame();	
			obj.yPos = enemy.yPos;
			obj.xPos = enemy.xPos;
		}
		enemy.determineCurAnim(ANIM::CAT2,2);
		enemy.determineCurFrame();
		enemy.frameID = enemy.counter/50;
		enemy.counter += 5; 
		
		enemy.xPos = jjSin(enemy.counter/u)*u + enemy.xPos; 
		enemy.yPos = jjCos(enemy.counter/3*u)*2*u + enemy.yPos ;//Lissajous figures :D
	if (++enemy.counter > 3300) 
	{
	enemy.xAcc= enemy.yAcc =0;
	enemy.state = STATE::FADEOUT;
	enemy.counter =0;
	
						}
		
		
		
		DisplayHealth(enemy);
	break;
		case STATE::FADEOUT:
		enemy.playerHandling = HANDLING::PARTICLE;
		enemy.bulletHandling = HANDLING::IGNOREBULLET;
	if (++enemy.counter < 100) {
			enemy.determineCurAnim(ANIM::CAT2, 1);
			enemy.frameID = enemy.counter / 20;
			enemy.determineCurFrame();
			}
			else {
			enemy.state = STATE::FADEIN;
			enemy.determineCurAnim(ANIM::CAT2, 0);
			if (enemy.findNearestPlayer(2000*2000) > -1) 
			{{jjPLAYER@ play = jjLocalPlayers[0];			 
			enemy.xPos = play.xPos - (jjRandom() & 100)+50;
			enemy.yPos = play.yPos - (jjRandom() & 100)+50;}
			enemy.direction = (jjLocalPlayers[0].xPos < enemy.xPos) ? -1 : 1;
			enemy.determineCurFrame();
			enemy.counter = 0;
			DisplayHealth(enemy);}
			else {enemy.state = STATE::FLOAT;}
		}
		break;
		case STATE::FADEIN:
			enemy.bulletHandling = HANDLING::HURTBYBULLET;
		u=((jjRandom() & 5)-2.5);
		DisplayHealth(enemy);
		if (++enemy.counter < 100) {
			enemy.frameID = enemy.counter / 20;
			enemy.determineCurFrame();
		} else {
	 {enemy.state = STATE::ATTACK;}
				enemy.counter=0;
		}
		
		break;
		
	case STATE::FREEZE:
			if (enemy.freeze > 0) {
				enemy.draw();
				enemy.freeze -= 4;
			}
			if (enemy.freeze < 4) {
				enemy.unfreeze(0);
				enemy.state = enemy.oldState;
			}DisplayHealth(enemy);
			break;
	case STATE::DEACTIVATE:
		enemy.deactivate();
		break;		
	case STATE::KILL:
	if (cats==true)
	{onCatAttack();}
	if (jjRandom() & 2 == 0)
	
	{jjAddObject(OBJECT::TOASTERAMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
	killedcats++;
	enemy.delete();
		break;
	}
	enemy.draw();
	}
	
	void Flame(jjOBJ@ enemy) {
	if (enemy.state== STATE::FLOAT)
		enemy.behave(BEHAVIOR::SPARK);
		++enemy.counter;
		if (enemy.counter >150*jjDifficulty+100)
				enemy.delete();
	}
	
		void PlatFlame(jjOBJ@ flame) {
	if (flame.state== STATE::FLOAT)
		flame.behave(BEHAVIOR::PICKUP);
		++flame.counter;
		if (flame.counter >40)
				flame.delete();
	}
	
	
		void EvilSpaz(jjOBJ@ boss) {
	if ( boss.energy ==0) {boss.state = STATE::KILL; boss.counter == 0;}			
		switch (boss.state) {
	case STATE::START:
		boss.determineCurAnim(ANIM::SPAZ, 61);
		boss.determineCurFrame();
		boss.frameID = boss.counter/10;
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		boss.putOnGround(false);	
		if ((boss.findNearestPlayer(600*600) > -1) && ++boss.counter > 55) {boss.state = STATE::ATTACK; boss.counter == 0;}
		
		break;
	case STATE::WALK:
		if (++boss.counter < 60) {
			boss.determineCurAnim(ANIM::SPAZ, 54);
			
			boss.behave(BEHAVIOR::WALKINGENEMY);
			
		
			
		} else {
			boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;
		}
		break;
	case STATE::FREEZE:
			if (boss.freeze > 0) {
				boss.draw();
				boss.freeze -= 4;
			}
			if (boss.freeze < 4) {
				boss.unfreeze(0);
				boss.state = boss.oldState;
			}
			break;
	case STATE::DEACTIVATE:
		boss.deactivate();
		break;
	case STATE::KILL:
	
				boss.killAnim = boss.determineCurAnim(ANIM::SPAZ, 4);
			
		boss.determineCurFrame();
		boss.frameID = boss.counter/10;
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
	boss.delete();
		break;

	case STATE::IDLE:
		boss.frameID = boss.counter/10;
		boss.determineCurFrame();
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		 
			if (boss.var[0] == 0) { boss.var[0] = 1; }
			switch (jjRandom() & 3) {
				case 0:
				
				
				
					boss.state = STATE::ATTACK;
					boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
					boss.determineCurAnim(ANIM::SPAZ, 14);
					boss.counter = 0;
					break;
					
				case 1:
					boss.state = STATE::FADEOUT;
					boss.determineCurAnim(ANIM::SPAZ, 72);
					
					boss.counter = 0;
					 {
						jjPLAYER@ play = jjLocalPlayers[0];
						boss.xAcc = play.xPos;
						boss.yAcc = play.yPos;
					}
					break;
					
				case 2:case 3:
					boss.state = STATE::WALK;
					boss.determineCurAnim(ANIM::SPAZ, 54); 
					boss.counter = 0;
					break;
					
				
				
			}
		
		break;
	case STATE::FADEOUT:
	if(++boss.counter == 1) 
	{jjSample(boss.xPos, boss.yPos, SOUND::COMMON_TELPORT1);}
		else if (++boss.counter < 50) {
			boss.frameID = boss.counter / 10;
			
			jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
			
			boss.determineCurFrame();
			}
			else {
			boss.frameID = boss.counter = 0;
			boss.state = STATE::FADEIN;
			
			boss.determineCurAnim(ANIM::SPAZ, 76);
			boss.xPos = boss.xAcc;
			boss.yPos = boss.yAcc - 32;
			boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
			boss.determineCurFrame();
			boss.putOnGround(false);
			return;
		}
		break;
	case STATE::FADEIN:
	if(++boss.counter == 1) 
	{jjSample(boss.xPos, boss.yPos, SOUND::COMMON_TELPORT2);}
		if (++boss.counter < 40) {
			boss.frameID = boss.counter / 10;
			boss.determineCurFrame();
			jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		} else {
			boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;
			boss.yAcc=boss.xAcc=0;
		}
		break;
	case STATE::ATTACK:
		if (++boss.counter < 36) {
			boss.frameID = boss.counter / 10;
			boss.determineCurFrame();
			if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
			
			if (( boss.counter == 25||boss.counter == 30||boss.counter == 35))
			
		{jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::BLASTERBULLET)];
				
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos; 	
				bullet.animSpeed = 1;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_GUN3PLOP);}
			
			
	
		} else {
			boss.frameID = boss.counter = 0;
			boss.determineCurAnim(ANIM::SPAZ, 61);
			boss.state = STATE::IDLE;
		}
		break;
	}
	DisplayHealth(boss);
}
	

	void Tweedle(jjOBJ@ boss) {
	jjPLAYER@ play = jjLocalPlayers[0];
	if ( boss.energy <=0) 
	{	boss.state = STATE::DONE; 
	boss.counter == 0;}			
		switch (boss.state) {
	case STATE::START:
	u=(jjRandom() & 3);
		boss.determineCurAnim(ANIM::TWEEDLE, 6);
		boss.determineCurFrame();
		boss.frameID = boss.counter/5;
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		boss.putOnGround(true);	
		if (boss.energy < 125 && ++boss.counter <= 11*(jjDifficulty+2)) {
		++boss.energy;
		
		jjSample(boss.xPos, boss.yPos, SOUND::BILSBOSS_ZIP);
		boss.lightType = LIGHT::LASER;
		boss.light =55;

				jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
		if (particle !is null) {
		particle.xPos = boss.xPos-20;
		particle.yPos = boss.yPos;
		particle.string.text = "HEAL";
		
		particle.ySpeed = -0.4;
		}
		
		}
		if (++boss.counter >= 50)
		{boss.light =0;}
		
	if (++boss.counter == 55){
		jjAlert("Tweedle heals himself by "+ formatInt(11*(jjDifficulty+1), "1"));
	}	
		if ((boss.findNearestPlayer(600*600) > -1) && ++boss.counter > 55)
		{boss.state = STATE::IDLE; boss.counter == 0;}
		break;
	case STATE::WALK:
	boss.behave(BEHAVIOR::WALKINGENEMY);
	{
	
		boss.counter++;
		if (u==0||u==1)
		{if (++boss.counter < 110){
			boss.xSpeed= (jjDifficulty+3)*boss.direction;
			boss.determineCurAnim(ANIM::TWEEDLE, 1);
			if (boss.counter == 10){
			jjSample(boss.xPos, boss.yPos, SOUND::INTRO_GREN3);}
			}
			else
			{boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;}
			}
			else if (u==2||u==3)
			{if (++boss.counter < 120){
			boss.xSpeed= boss.direction;
			boss.determineCurAnim(ANIM::TWEEDLE, 8);}
			else
			{boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;}
			}
			if (boss.justHit == 0)
			{jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);}
			boss.determineCurFrame();
			boss.frameID = (boss.counter/10) & 63;
	
		break;
		
		}
	case STATE::FREEZE:
			if (boss.freeze > 0) {
				boss.draw();
				boss.freeze -= 4;
			}
			if (boss.freeze < 4) {
				boss.unfreeze(0);
				boss.state = boss.oldState;
			}
			break;
	case STATE::DEACTIVATE:
		boss.deactivate();
		break;
	case STATE::DONE:

		boss.determineCurAnim(ANIM::TWEEDLE, 5);
		boss.determineCurFrame();
		boss.frameID = boss.counter/20;
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
	++boss.counter;
	if (++boss.counter>89) {
	boss.energy = 125;}
			if (++boss.counter>90) {
	boss.state = STATE::START;
	boss.behavior = Tweedle2;
		boss.counter==0;			
		//jjEventSet(p.xPos / 32, p.yPos / 32, AREA::EOL);
		}
		break;

	case STATE::IDLE:
		boss.frameID = boss.counter/5;
		boss.determineCurFrame();
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		 
			if (boss.var[0] == 0) { boss.var[0] = 1; }
			switch (jjRandom() & 3) {
			
				case 0:
				
					boss.state = STATE::ATTACK;
					boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
					if (play.charCurr == CHAR::JAZZ)
					{boss.determineCurAnim(ANIM::TWEEDLE, 4);}
					else
					{boss.determineCurAnim(ANIM::TWEEDLE, 3);}
					boss.counter = 0;
					break;
	
				
				case 1:
					boss.state = STATE::WALK;
					boss.counter = 0;
					break;
					
				
				case 2:
					boss.state = STATE::START;
					boss.determineCurAnim(ANIM::TWEEDLE, 6); 
					boss.counter = 0;
					break;
			}
		
		break;

	case STATE::ATTACK:

		if (++boss.counter < 36) {
			boss.frameID = boss.counter / 5;
			boss.determineCurFrame();
			if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
			if ((u==0||u==1)&& ( boss.counter == 20|| boss.counter == 25||boss.counter == 30|| boss.counter == 35||boss.counter == 40))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::BOUNCERBULLET)];
				
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.ySpeed = (-(jjRandom() & 6)+3);
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				bullet.animSpeed = 1;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_SPZBL1);
			}
			else if ((u==2) && (boss.counter == 22|| boss.counter == 26||boss.counter == 30||boss.counter == 34||boss.counter == 38))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::BLASTERBULLET)];
				
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				bullet.animSpeed = 1;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_GUN3PLOP);
			}
			else if (u==3 && ( boss.counter == 30))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::ELECTROBULLETPU)];
				
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				
				bullet.animSpeed = 3;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_LASER2);
			}
			
		} else {
			boss.frameID = boss.counter = 0;
			boss.determineCurAnim(ANIM::TWEEDLE, 6);
			boss.state = STATE::IDLE;
		}
		break;
	}
	
}

	void Tweedle2(jjOBJ@ boss) {
	
	jjPLAYER@ play = jjLocalPlayers[0];
				
		switch (boss.state) {
	case STATE::START:
	 if (++boss.counter >= 0&&++boss.counter <= 400)
	 	{boss.determineCurFrame();
			boss.frameID = boss.counter/60;}
	boss.determineCurAnim(ANIM::TWEEDLE, 0);
	boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
	 if (++boss.counter > 400&&++boss.counter <= 2000)
{paused=false;
boss.determineCurFrame();
boss.frameID = boss.counter/60;
boss.determineCurAnim(ANIM::TWEEDLE, 7);}	
	if (++boss.counter > 500&& ++boss.counter < 700&&jjGameTicks%5==0){
	play.noFire=true;
	
	jjSample(boss.xPos, boss.yPos, SOUND::COMMON_SWISH2);
		@spawnedObject2 = jjObjects[jjAddObject(OBJECT::SEEKERBULLETPU, play.xPos, play.yPos)];
		++spawnedObject2.counter;		
				jjDrawSpriteFromCurFrame(spawnedObject2.xPos, spawnedObject2.yPos, spawnedObject2.curFrame, spawnedObject2.direction, SPRITE::NORMAL);
			}
		
		boss.determineCurFrame();
		boss.frameID = boss.counter/5;
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		boss.putOnGround(true);	
		
		if (++boss.counter > 690&&++boss.counter <= 700)
	{play.showText("@@#You are disarmed!@Use buttstomps @and special attacks!", STRING::SMALL);}
		if (++boss.counter > 2000&&++boss.counter <= 2200) {
		boss.determineCurAnim(ANIM::TWEEDLE, 2);
		boss.determineCurFrame();
		boss.frameID = -boss.counter/60;
		}
		
		if ((boss.findNearestPlayer(600*600) > -1) && ++boss.counter > 2200) {
		boss.state = STATE::ATTACK; 
		boss.counter == 0;}
		break;
		case STATE::STILL:
		
	u=(jjRandom() & 3);
//	if (boss.counter >= 10&&boss.counter <= 12&&u==2)
//		{jjAddObject(OBJECT::HATTER,boss.xPos,boss.yPos);}
		boss.determineCurAnim(ANIM::TWEEDLE, 6);
		boss.determineCurFrame();
		boss.frameID = boss.counter/5;
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		boss.putOnGround(true);	
		if (boss.energy < 125 && ++boss.counter <= 5*(jjDifficulty)) {
		++boss.energy;
		
		jjSample(boss.xPos, boss.yPos, SOUND::BILSBOSS_ZIP);
		boss.lightType = LIGHT::LASER;
		boss.light =55;

				jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
		if (particle !is null) {
		particle.xPos = boss.xPos-20;
		particle.yPos = boss.yPos;
		particle.string.text = "HEAL";
		
		particle.ySpeed = -0.4;
		}
		
		}
		if (++boss.counter >= 50)
		{boss.light =0;}
	if (++boss.counter == 55){
		jjAlert("Tweedle heals himself by "+ formatInt(3*(jjDifficulty), "1"));
	}	
		if ((boss.findNearestPlayer(600*600) > -1) && ++boss.counter > 55)
		{boss.state = STATE::IDLE; 
		boss.counter == 0;}
		break;
	case STATE::WALK:
	boss.behave(BEHAVIOR::WALKINGENEMY);
		 	if (u==0||u==1)
		{if (++boss.counter < 110){
			boss.xSpeed= (jjDifficulty+6)*boss.direction;
			boss.determineCurAnim(ANIM::TWEEDLE, 1);
			if (boss.counter == 10){
			jjSample(boss.xPos, boss.yPos, SOUND::INTRO_GREN3);}
			}
			else
			{boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;}
			}
			else if (u==2||u==3)
			{if (++boss.counter < 120){
			boss.xSpeed= boss.direction;
			boss.determineCurAnim(ANIM::TWEEDLE, 8);}
			else
			{boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;}
			}
                       
 
	else 
	{
			boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;
			boss.playerHandling = HANDLING::SPECIAL;
			boss.bulletHandling = HANDLING::HURTBYBULLET;
		}
		break;
	case STATE::FREEZE:
			if (boss.freeze > 0) {
				boss.draw();
				boss.freeze -= 4;
			}
			if (boss.freeze < 4) {
				boss.unfreeze(0);
				boss.state = boss.oldState;
			}
			break;
	case STATE::DEACTIVATE:
		boss.deactivate();
		break;
	case STATE::KILL:
	
			boss.determineCurAnim(ANIM::TWEEDLE, 5);
		boss.determineCurFrame();
		boss.frameID = boss.counter/20;
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
	
		
			@spawnedObject3 = jjObjects[jjAddObject(OBJECT::BOUNCEONCE, boss.xPos, boss.yPos)];
			jjSample(boss.xPos, boss.yPos, SOUND::MENUSOUNDS_SELECT0);
			if (play.charCurr == CHAR::JAZZ)
			{spawnedObject3.determineCurAnim(ANIM::AMMO, 19);}
			else
			{spawnedObject3.determineCurAnim(ANIM::AMMO, 18);}
			boss.delete();
			jjEventSet(play.xPos / 32, play.yPos / 32, AREA::EOL);
		
		break;

	case STATE::IDLE:
		boss.frameID = boss.counter/5;
		boss.determineCurFrame();
		if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
		 
			if (boss.var[0] == 0) { boss.var[0] = 1; }
			switch (jjRandom() & 3) {
				case 0:
				
				
				
					boss.state = STATE::ATTACK;
					boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
					if (play.charCurr == CHAR::JAZZ)
					{boss.determineCurAnim(ANIM::TWEEDLE, 4);}
					else
					{boss.determineCurAnim(ANIM::TWEEDLE, 3);}
					boss.counter = 0;
					break;
					
				case 1:
					boss.state = STATE::FADEOUT;
					boss.determineCurAnim(ANIM::TWEEDLE, 1);
					
					boss.counter = 0;
					if (jjDifficulty > 0) { 
						boss.playerHandling = HANDLING::PARTICLE;
						boss.bulletHandling = HANDLING::IGNOREBULLET;
					} {
						boss.xAcc = play.xPos;
						boss.yAcc = play.yPos;
					}
					break;
					
				case 2:
				boss.state = STATE::STILL;
					boss.counter = 0;
					break;
				case 3:
					boss.state = STATE::WALK;
					boss.counter = 0;
					break;
				
			}
		
		break;
	case STATE::FADEOUT:
	
	if(++boss.counter == 1) 
	{jjSample(boss.xPos, boss.yPos, SOUND::DEVILDEVAN_VANISH1);}
		else if (++boss.counter < 50) {
			boss.frameID = boss.counter / 5;
			
			jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::TRANSLUCENT);
			
			boss.determineCurFrame();
			}
			else {
			boss.frameID = boss.counter = 0;
			boss.state = STATE::FADEIN;
			
			boss.determineCurAnim(ANIM::TWEEDLE, 1);
			boss.xPos = play.xPos;
			boss.yPos = play.yPos;
			boss.direction = (jjLocalPlayers[0].xPos < boss.xPos) ? -1 : 1;
			boss.determineCurFrame();
			boss.putOnGround(true);
			return;
		}
		break;
	case STATE::FADEIN:
		if (++boss.counter < 40) {
			boss.frameID = boss.counter / 5;
			boss.determineCurFrame();
			jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::TRANSLUCENT);
		} else {
			boss.frameID = boss.counter = 0;
			boss.state = STATE::IDLE;
			boss.playerHandling = HANDLING::SPECIAL;
			boss.bulletHandling = HANDLING::HURTBYBULLET;
			boss.yAcc=boss.xAcc=0;
		}
		break;
	case STATE::ATTACK:

		if (++boss.counter < 36) {
			boss.frameID = boss.counter / 5;
			boss.determineCurFrame();
			if (boss.justHit == 0)
		jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
		else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15);
				if ((u==0)&& (jjGameTicks%2==0)&&( boss.counter >= 20&&boss.counter <= 40))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::BOUNCERBULLETPU)];
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.ySpeed = (-(jjRandom() & 6)+3);
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				bullet.animSpeed = 1;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_SPZBL1);
			}
		if ((u==1)&& (jjGameTicks%2==0)&&(  boss.counter >= 20&&boss.counter <= 40))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::FIRESHIELDBULLET)];
				bullet.determineCurAnim(ANIM::BUBBA, 4);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.ySpeed = (-(jjRandom() & 6)+3);
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				bullet.animSpeed = 2;
				if (boss.counter >= 20&&boss.counter <= 25)
				{jjSample(boss.xPos, boss.yPos, SOUND::BUBBA_SNEEZE2);}
			}
			if ((u==2)&&( boss.counter == 25||boss.counter == 30||boss.counter == 35))
			{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::SMOKERING)];
	            bullet.ySpeed = 0;
				bullet.yAcc = 0;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				jjSample(boss.xPos, boss.yPos, SOUND::INTRO_BLOW);
			}
			if ((u==3)&&(boss.counter == 20|| boss.counter == 25||boss.counter == 30||boss.counter == 35||boss.counter == 40))
					{
		jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::BLASTERBULLETPU)];
				
				bullet.killAnim = bullet.determineCurAnim(ANIM::AMMO, 4, false);
				bullet.playerHandling = HANDLING::ENEMYBULLET;
				bullet.state = STATE::FLY;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				bullet.animSpeed = 2;
				jjSample(boss.xPos, boss.yPos, SOUND::AMMO_GUN3PLOP);
			}
			
		} else {
			boss.frameID = boss.counter = 0;
			boss.determineCurAnim(ANIM::TWEEDLE, 6);
			boss.state = STATE::IDLE;
		}
		break;
	}
	
}

void MovingPlatform(jjOBJ@ plat) {// I had to use another behavior for horisontally-moving stone. If not, Jazz doesn't move with the platform and falls from it. 

switch (plat.state){// I was inspired by a moving platform in "plusEnscripted"
case STATE::WAIT:
plat.state = STATE::FADEIN;
break;
case STATE::DEACTIVATE:
		plat.xOrg = plat.xAcc;
		plat.yOrg = plat.yAcc;
break;		
case STATE::FADEIN:
//if (abs(jjLocalPlayers[0].xPos-plat.xOrg)<12*32||abs(jjLocalPlayers[0].yPos-plat.yOrg)<12*32){
if (plat.yOrg>56*32&&plat.yOrg<58*32&&plat.xOrg>423*32&&plat.xOrg<446*32&&jjTriggers[15])
	plat.xOrg = (430.5*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(7*32);
else if (plat.xOrg>23*32&&plat.xOrg<25*32)	
	plat.yOrg = (12*32) - jjSin(++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
else if (plat.xOrg>352*32&&plat.xOrg<373*32&&plat.yOrg<66*32)	
	{plat.xOrg = (362*32) + jjCos(++plat.counter)*(9.5*32);
	plat.yOrg = (58*32) - jjCos(++plat.counter*2)*(4*32);}
else if (plat.xOrg>300*32&&plat.xOrg<340*32&&plat.yOrg<30*32&&jjTriggers[34])	
	{plat.xOrg = (320*32) - jjCos(++plat.counter/2)*(18.5*32);
	plat.yOrg = (16*32) + jjCos(++plat.counter*2)*(6*32);}
//else if (plat.yOrg>11*32&&plat.yOrg<13*32)	
	//plat.xOrg = (27*32) - jjSin(++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
else if (plat.xOrg>43*32&&plat.xOrg<45*32&&jjTriggers[3])
	plat.yOrg = (62*32) - jjSin(++plat.counter*((jjDifficulty+1)^0.5))*(10*32);
else if (plat.yOrg>59*32&&plat.yOrg<61*32&&plat.xOrg>420*32&&plat.yOrg<485*32)
	plat.xOrg = (453*32) + jjSin(++plat.counter*((jjDifficulty+1)^0.5))*(29*32);
else if (plat.xOrg>249*32&&plat.xOrg<251*32&&plat.yOrg<32*32&&jjTriggers[31])
	plat.yOrg = (22.7*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(7*32);
else if (plat.xOrg>264*32&&plat.xOrg<266*32)
	plat.yOrg = (48*32) + jjSin(0.9*++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
else if (plat.xOrg>266*32&&plat.xOrg<268*32)
	plat.yOrg = (29*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(15*32);
else if (plat.xOrg>268*32&&plat.xOrg<270*32)
	plat.yOrg = (9*32) + jjSin(0.9*++plat.counter*((jjDifficulty+1)^0.5))*(6*32);	
else if (plat.xOrg>409*32&&plat.xOrg<411*32)
	plat.yOrg = (50*32) + jjSin(++plat.counter*((jjDifficulty+1)^0.5))*(6*32);	
else if (plat.xOrg>140*32&&plat.xOrg<142*32&&jjTriggers[28])	
	plat.yOrg = (21*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(15*32);
else if (plat.xOrg>176*32&&plat.xOrg<178*32&&killedbombs>=bombgoal&&killedsmallbombs>=smbombgoal)	
	plat.yOrg = (52*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(10*32);	
else if (plat.xOrg>443*32&&plat.xOrg<445*32)	
	plat.yOrg = (51*32) + jjSin(0.9*++plat.counter*((jjDifficulty+1)^0.5))*(5*32);	
else if (plat.yOrg>84*32&&plat.yOrg<86*32&&plat.xOrg<341*32&&plat.xOrg>322*32&&jjTriggers[32])	
	plat.xOrg = (332*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(7.5*32);
else if (plat.xOrg>320*32&&plat.xOrg<322*32&&plat.yOrg>73*32)
	plat.yOrg = (79*32) + jjSin(0.9*++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
else if (plat.xOrg>257*32&&plat.xOrg<259*32)
	plat.yOrg = (92*32) + jjSin(++plat.counter*((jjDifficulty+1)^0.5))*((jjDifficulty+3)*32);
else if (plat.xOrg>253*32&&plat.xOrg<255*32)
	plat.yOrg = (90*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*((jjDifficulty+3)*32);
else if (plat.xOrg>249*32&&plat.xOrg<251*32&&plat.yOrg>32*78)
	plat.yOrg = (88*32) + jjSin(++plat.counter*((jjDifficulty+1)^0.5))*((jjDifficulty+3)*32);
else if (plat.xOrg>245*32&&plat.xOrg<247*32)
	plat.yOrg = (86*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*((jjDifficulty+3)*32);	
else if (plat.xOrg>453*32&&plat.yOrg>45*32&&plat.xOrg<483*32&&plat.yOrg<58*32)
	{plat.yOrg = (51*32) + jjSin(0.5*++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
	plat.xOrg = (468*32) + jjSin(0.5*++plat.counter*((jjDifficulty+1)^0.5))*(12*32);}	
else if (plat.xOrg<316*32&&plat.yOrg>73*32&&plat.xOrg>290*32&&plat.yOrg<85*32&&jjTriggers[30])
	{plat.yOrg = (79.5*32) - jjCos(0.5*++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
	plat.xOrg = (302.7*32) + jjCos(0.5*++plat.counter*((jjDifficulty+1)^0.5))*(12*32);}	
else if (plat.xOrg>357*32&&plat.yOrg>65*32)
	{plat.yOrg = (77*32) + jjCos(++plat.counter*1.5)*(11*32);
	plat.xOrg = (363*32) + jjSin(++plat.counter*1.5)*(5*32);}
//	}
if (plat.xSpeed!=0||plat.ySpeed<0){
if (jjGameTicks%10==0)
{jjSample(plat.xOrg, plat.yOrg, SOUND::BUBBA_BUBBAEXPLO);}
if (jjGameTicks%2==0){
	 
			jjOBJ@ obj = jjObjects[plat.fireBullet(OBJECT::STRAWBERRY)];
			obj.light=55;
			obj.determineCurAnim(ANIM::AMMO,5);
			obj.determineCurFrame();	
			obj.yPos = plat.yPos+30;
			obj.xPos = plat.xPos-12;
			if (++obj.counter>15)
			{obj.light=0;}
		}	
		
		if (jjGameTicks%2==0){
	 
			jjOBJ@ obj = jjObjects[plat.fireBullet(OBJECT::STRAWBERRY)];
			obj.light=55;
			obj.determineCurAnim(ANIM::AMMO,5);
			obj.determineCurFrame();	
			obj.yPos = plat.yPos+30;
			obj.xPos = plat.xPos+10;
			if (++obj.counter>15)
			{obj.light=0;}
		}}
		break;
}
	plat.behave(BEHAVIOR::PLATFORM, true); //This is the main string of this behavior. It makes Jazz to obtain stone's acceleration and not to fall from it. Though it draws the plat's sprite which I desided to replace with an image of a stone
	jjDrawTile(plat.xPos - 15,  plat.yPos + 14, 160+ TILE::VFLIPPED);
	jjDrawTile(plat.xPos - 31, plat.yPos - 14, 220);//this is a little bit lengthened image of a stone. I had to do is to hide the sprite of a pink platform behind it
	jjDrawTile(plat.xPos + 1,  plat.yPos - 14, 221);//when I tried simply not to draw this platform, the platform turned to be not solid, so I was falling from it
	jjDrawTile(plat.xPos - 32, plat.yPos - 14, 220);//So many tiles have been drawn just to make the stone look better, with a smooth transition between two parts
	jjDrawTile(plat.xPos + 2,  plat.yPos - 14, 221);
	jjDrawTile(plat.xPos + 3,  plat.yPos - 14, 221);
	jjDrawTile(plat.xPos - 33, plat.yPos - 14, 220);
	jjDrawTile(plat.xPos + 4,  plat.yPos - 14, 221);
	jjDrawTile(plat.xPos - 34, plat.yPos - 14, 220);
	jjDrawTile(plat.xPos + 5,  plat.yPos - 14, 221);
	jjDrawTile(plat.xPos - 35, plat.yPos - 14, 220);
	jjDrawTile(plat.xPos + 6,  plat.yPos - 14, 221);
}


void onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
	if ((obj.eventID == OBJECT::ROBOT)&& obj.state != STATE::KILL) {
if (play !is null) {
	//no TNT or turtle shells in this level, so shouldn't be necessary, but can't hurt
			if (force == 0) //normal collision, not using any buttstomps or whatever
				play.hurt();
			else {
				//Here JJ2 would check to see if the object is frozen, and if so,
				//unfreeze it and (possibly; some objects do this and others don't)
				//alter the amount of damage it receives from the bullet. There's no
				//ice ammo in this level, so that's not required.
				if (force > 0) //probably a bullet
					obj.energy -= force/10;
				else //special attack
					obj.energy -= 1;
				if (obj.energy <= 0) {
					if (bullet !is null) {
						if ((bullet.var[6] & 2) == 2) { //toaster and its ilk
							obj.particlePixelExplosion(1); //burny explosion
							jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BURN);
						} else {
							obj.particlePixelExplosion(0);
						}
						obj.grantPickup(play, (bullet.eventID == OBJECT::BLASTERBULLET) ? 5 : 10);
							//JJ2 only ever calls grantPickup for enemies/crates destroyed
							//by bullets, but you can branch out a bit if you like
					} else {
						obj.particlePixelExplosion(2); //killed by physical contact
						jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SPLAT1);
					}
					obj.state = STATE::KILL; //let the object's behavior function take care of deleting it
						
					
				} else if (bullet is null)//not yet dead
					obj.energy -= 1;
					obj.justHit = 5; //flash white for five ticks
					
					
			}
		}
		if (bullet !is null&&bullet.objectID==0) {
		obj.justHit = 5;
		obj.energy -= 1;
		}
		if (bullet !is null && (bullet.var[6] & 16) == 0) { //JJ2 also checks for var[6] & 4, aka the laser shield blast, but eh whatever
			bullet.state = STATE::EXPLODE;	//EXPLODE, like START, means the bullet won't be checked for collisions with other objects/players
							//also, all normal bullet behaviors have code to dispose of themselves during EXPLODE, so that's nice
		}
	}
	else if (obj.eventID == OBJECT::FASTFEET) { 
	play.timerStart(2000/(jjDifficulty+1));
		play.jumpStrength = play.jumpStrength - 8;
		play.showText("@@#Heigth of Jumps @@ Temporarily Increased!", STRING::SMALL);
		obj.behavior = BEHAVIOR::EXPLOSION2; //this is ESSENTIAL. just like enemies die by getting their states set to STATE::KILL, and bullets die by getting their states set to STATE::EXPLODE, pickups die by getting their behavior set to BEHAVIOR::EXPLOSION2. yes, sometimes a little consistency is in fact too much to ask for.
		obj.scriptedCollisions = false; //or obj.playerHandling = HANDLING::EXPLOSION; or something like that
		obj.frameID = 0;
		jjSample(obj.xPos, obj.yPos, SOUND::BUBBA_BUBBABOUNCE2);
	}
	 else if (obj.eventID == OBJECT::APPLE) {
	 
				jjEventSet(obj.xOrg / 32, obj.yOrg / 32, 0);
		if (bullet is null&&obj.state == STATE::FLOAT) {
			obj.state = STATE::ACTION;
			//obj.behavior = BEHAVIOR::EXPLOSION2;
			jjChat("/smhealth " + formatInt(jjMaxHealth + 1, "1"));
			play.health = jjMaxHealth;
			play.showText("@@#Health Limit@@ Increased!", STRING::SMALL);
			jjSample(obj.xPos, obj.yPos, SOUND::COMMON_HARP1);
			jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
			if (particle !is null) {
				particle.xPos = play.xPos;
				particle.yPos = play.yPos;
				particle.string.text = "|1up";
				particle.ySpeed = -1;
				particle.xSpeed = 1.4;
			}
			}
		}
		else if (obj.eventID == OBJECT::FRIES) {
			obj.behavior = BEHAVIOR::EXPLOSION2;
			play.hurt();
			jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BLUB1);
			jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
			if (particle !is null) {
				particle.xPos = play.xPos;
				particle.yPos = play.yPos;
				particle.string.text = "|Poisoned!";
				particle.ySpeed = -1;
				particle.xSpeed = 1.4;
			}	
		}
	else if (obj.eventID == OBJECT::BANANA || obj.eventID == OBJECT::MILK) {
	if (bullet is null) {
				if (obj.freeze == 0||force==0) p.hurt();
				if (force<0)
				{obj.energy += force;
				obj.justHit = 5;
				}
				if (obj.energy<=0)
				{obj.state = STATE::KILL;
				obj.particlePixelExplosion(2);
			p.score += obj.points;
					jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
			if (particle !is null) {
				particle.xPos = obj.xPos;
				particle.yPos = obj.yPos;
			if (obj.eventID == OBJECT::BANANA)
				{particle.string.text = "100";}
				else 
				{particle.string.text = "10";}
				particle.ySpeed = -1;
				particle.xSpeed = -1.1;
			}				
						jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SPLAT1);}
			}
			
	else
	{
				bullet.ricochet();
	}
}	
	else if (obj.eventID == OBJECT::UTERUS)	
	{	
	if (bullet is null) {
				if (obj.freeze == 0||force==0) 
				p.hurt();
				if (force<0)
				{obj.energy += force;
				obj.justHit = 5;
				}}
				
				if (obj.energy<=0)
				{obj.state = STATE::KILL;
				obj.particlePixelExplosion(2); 
				p.score=p.score+800;
					jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
			if (particle !is null) {
				particle.xPos = obj.xPos;
				particle.yPos = obj.yPos;
				particle.string.text = "800";
				particle.ySpeed = -1;
				particle.xSpeed = -1.1;
			}
						jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SPLAT1);}
			
	}
}

bool onDrawScore(jjPLAYER@ player, jjCANVAS@ screen) { //replace the score with a tally of slain lizards during the surge
	if (cats && killedcats<catgoal) {
		if (player.localPlayerID == 0) {
			screen.drawString(40, 20, formatInt(killedcats, "1") + " / " + formatInt(catgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 232);
			screen.drawSprite(20, 30, ANIM::CAT2, 2, SPRITE::RESIZED,16); 
		
		}
		player.scoreDisplayed = player.score; //otherwise it'll have to rush to catch up when this scene is over, since JJ2 only changes .scoreDisplayed in its own onDrawScore code, which we're preventing from being called
		return true;}
		else if (bombs) {
		if (player.localPlayerID == 0) {
			screen.drawString(40, 10, formatInt(killedbombs, "1") + " / " + formatInt(bombgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 232);
			screen.drawSprite(20, 10, ANIM::SPIKEBOLL,0, SPRITE::NORMAL); 
			screen.drawString(40, 50, formatInt(killedsmallbombs, "1") + " / " + formatInt(smbombgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 232);
			screen.drawTile(5, 35, 748);//the tile with the small bomb. of course firstly I  tried to apply something like this: screen.drawSprite(20, 50, ANIM::ROBOT,0, SPRITE::NORMAL); 
			//but it caused an access violation! So I had to paste the image of robot's spiked ball into the tileset and then call the necessary tile.
			if (killedbombs>=bombgoal && killedsmallbombs<smbombgoal) {screen.drawString(40, 10, formatInt(killedbombs, "1") + " / " + formatInt(bombgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 16);}
			if (killedbombs<bombgoal && killedsmallbombs>=smbombgoal) {screen.drawString(40, 50, formatInt(killedsmallbombs, "1") + " / " + formatInt(smbombgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 16);}
		}
player.scoreDisplayed = player.score; //otherwise it'll have to rush to catch up when this scene is over, since JJ2 only changes .scoreDisplayed in its own onDrawScore code, which we're preventing from being called
		return true;}
		
	
	return false;
}

bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (play.currWeapon == WEAPON::TNT && !play.noFire) {

		canvas.drawSprite(
			jjSubscreenWidth - 90,
			jjSubscreenHeight - 14,
			ANIM::AMMO, 1, 
			(jjRenderFrame)/5,
			play.powerup[WEAPON::TNT] == true? 4:3,
			SPRITE::NORMAL
		);
		
		canvas.drawString(
			jjSubscreenWidth - 80,
			jjSubscreenHeight - 14,
			"x" + play.ammo[WEAPON::TNT],
			STRING::MEDIUM,
			STRING::NORMAL
		);
		return true;
	}
	else if (play.currWeapon == WEAPON::GUN8 && !play.noFire) {
		canvas.drawSprite(
			jjSubscreenWidth - 90,
			jjSubscreenHeight - 14,
			ANIM::PICKUPS, 78, 
			(jjRenderFrame)/5,
			play.powerup[WEAPON::GUN8] == true? 4:3,
			SPRITE::NORMAL
		);
		
		canvas.drawString(
			jjSubscreenWidth - 80,
			jjSubscreenHeight - 14,
			"x" + play.ammo[WEAPON::GUN8],
			STRING::MEDIUM,
			STRING::NORMAL
		);
		return true;
	}
	else return false;
}

//Thanks for reading!