Downloads containing Psychomondus.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: PsychomondusFeatured Download Bloody_Body Single player 8.5 Download file

File preview

//Задача - собрать N монет. Вместо очков - кол-во собранных монет. Изначальный цвет - psych2. С каждой собранной монетой становится теплее и светлее. Когда все монеты собраны, открывается дорога к выходу.
//Уровень замкнутый. Из любой его точки можно попасть в любую другую точку. Враги возрождаются и они, сцука, сложные. Респаунов нет.
//Враги - Шляпник, Стрекоза, Кот, Твидл. Твидл пуляется дымовыми кольцами и прыгунами. Телепортируется на небольшие расстояния.
//Из врагов вываливаются патроны. Есть слюноган.
//Доп.механики, как превращение в жабу и обувь-попрыгобувь. 
//Добавить текстур из других летних миров. Грибочки, цветочки, камушки.
//Когда всё собрано, появляется куча врагов
//Блоки с колбами
//За 10 синих даётся 1 фиолетовый.
//How Psychodilicus would be called if there were loads of diamonds? Absolutely right! Psychomondus!
//This planet suffers of a continious solar eclipse. Obviously, only you can save it. 
//Your task is to collect ten especially rare purple diamonds. Each diamond you collect will make the planet a little bit more sunny and firendly!
//It's a hybrid of SP, Treasure hunt and jailbreak! Have fun!

bool stoned=false, Disarmed=false, Boss=false; 
int i,u=1,c=1,s=1,b=0, m=0,g=0,q=0, f,gemgoal=25;
jjPAL myPal, newPal, Golden;
jjOBJ@ spawnedObject;
jjOBJ@ spawnedObject2;
jjOBJ@ spawnedObject3;

void onMain() {
jjPLAYER@ play = jjLocalPlayers[0];

if (jjLocalPlayers[i].lighting >=100) 
{jjLocalPlayers[i].lighting = 100;}


if (play.gems[GEM::RED]>=5)
{play.gems[GEM::GREEN] = play.gems[GEM::GREEN]+1;
play.gems[GEM::RED] = 0;
}

if (play.gems[GEM::GREEN]>=2)
{play.gems[GEM::BLUE] = play.gems[GEM::BLUE]+1;
play.gems[GEM::GREEN] = 0;
}
if (play.gems[GEM::BLUE]>=10)
{play.gems[GEM::PURPLE] = play.gems[GEM::PURPLE]+1;
play.gems[GEM::BLUE] = 0;
}



//jjAlert("nhj "+ formatInt(1000*play.gems[GEM::PURPLE] / 25.0, "1"));

if (play.stoned==0) {

	//jjPalette.reset();
		jjPalette.copyFrom(
			1,		//start
			254,		//length (It's best to leave colors 0 and 255 alone.)
			1,		//start2
			newPal,	//source
			play.gems[GEM::PURPLE] / 500.0	//opacity
		);
if	(play.gems[GEM::PURPLE]  < 25)		
		{jjPalette.apply();}
else if	(play.gems[GEM::PURPLE]  == 25)	
{q++;
if (q == 1)
{play.showText("@@That's it! Now find the exit!", STRING::LARGE);
newPal.apply();}}
		jjSetFadeColors(0,40*play.gems[GEM::PURPLE] / gemgoal,80*play.gems[GEM::PURPLE] / gemgoal);
		jjLocalPlayers[i].lighting = 50 + 2*play.gems[GEM::PURPLE];
}


//	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 (play.gems[GEM::PURPLE] >= gemgoal) {
	jjTriggers[10]=true;}

updateGems();

  for(int i = 1; i < jjObjectCount; i++) {
    if(jjObjects[i].isActive && jjObjects[i].eventID == OBJECT::SMOKERING) { //If you play EASY or MEDIUM 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 HARD or 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

//jjAlert("boss.var[1] "+ formatInt(boss.var[1], "1"));
//jjPLAYER@ play = jjLocalPlayers[0];


if (play.stoned!=0)
{ stoned=true;
jjTexturedBGStyle = TEXTURE::TUNNEL;
s=0;
if (stoned=true && (jjGameTicks & 10)==0 && jjColorDepth == 16)
{b=0; m=0;
for (i = 0; i < 254; i++) {
				jjPalette.color[i+1].setHSL(
					jjPalette.color[i+1].getHue()/20 + jjGameTicks,
					jjPalette.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
					jjPalette.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;
jjTexturedBGStyle = TEXTURE::WARPHORIZON;

if (s==0&&m==0)//sobering up


{
		m++;
		jjSetFadeColors(0,40*play.gems[GEM::PURPLE] / gemgoal,80*play.gems[GEM::PURPLE] / gemgoal);
		jjLocalPlayers[i].lighting = 50 + 2*play.gems[GEM::PURPLE];
		jjPalette.reset();
		jjPalette.copyFrom(
			1,		
			254,		
			1,		
			newPal,	
			play.gems[GEM::PURPLE] / 400.0
		);
		jjPalette.apply();
		}
		
if (play.gems[GEM::PURPLE] >=25)
{newPal.apply();}


}


}



void onLevelReload() {
jjPLAYER@ play = jjLocalPlayers[0];
play.jumpStrength = -10; 
jjMusicLoad("funkyg.j2b");
b=0;
Boss=false;
Disarmed=false;
jjPalette.reset();
jjSetFadeColors(0,40,80);
jjLocalPlayers[i].lighting = 50;
}

void onLevelLoad() {

newPal.load("Psych2c10.j2t");

//jjTexturedBGTexture = TEXTURE::WISETYNESS;
				//jjTexturedBGStyle = TEXTURE::TUNNEL;
		for (int weaponID = WEAPON::BLASTER; weaponID <= WEAPON::GUN9; ++weaponID) {
		jjWEAPON@ weaponProfile = jjWeapons[weaponID];
		weaponProfile.comesFromBirds = weaponProfile.comesFromBirdsPowerup = true; 
	}
	
	jjObjectPresets[OBJECT::PURPLEGEM].points = 2000;
	
	jjObjectPresets[OBJECT::HATTER].behavior = HatterX;
	//jjObjectPresets[OBJECT::DRAGONFLY].behavior = DragonflyX;
	jjObjectPresets[OBJECT::NORMTURTLE].behavior = TurtleX;
	
	jjObjectPresets[OBJECT::GUN8AMMO3].determineCurAnim(ANIM::PICKUPS, 78, true);
	jjObjectPresets[OBJECT::FIREBALLBULLET].determineCurAnim(ANIM::HATTER, 3);
	//jjObjectPresets[OBJECT::FIREBALLBULLET].behavior = SpitGun;
	jjObjectPresets[OBJECT::FIREBALLBULLET].lightType= LIGHT::POINT;
	jjObjectPresets[OBJECT::FIREBALLBULLET].light =55;
	//jjObjectPresets[OBJECT::FIREBALLBULLET].jjSample(spit.xPos, spit.yPos, SOUND::HATTER_PTOEI);
	jjObjectPresets[OBJECT::FIREBALLBULLET].causesRicochet = true;
	jjWeapons[WEAPON::GUN8].style = WEAPON::NORMAL;	
		
	jjObjectPresets[OBJECT::APPLE].points = 0;
	jjObjectPresets[OBJECT::APPLE].scriptedCollisions = true;		
	jjObjectPresets[OBJECT::APPLE].behavior = WITCHSPELL;	
	jjObjectPresets[OBJECT::APPLE].state = STATE::ACTION;	
		
	jjObjectPresets[OBJECT::FASTFEET].points = 100;
	jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;	
		
	jjObjectPresets[OBJECT::TNTAMMO3].behavior = PlatFlame;
	jjObjectPresets[OBJECT::TNTAMMO3].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::TNTAMMO3].playerHandling = HANDLING::EXPLOSION;
	jjObjectPresets[OBJECT::TNTAMMO3].state = STATE::FLOAT;
	jjObjectPresets[OBJECT::TNTAMMO3].lightType = LIGHT::POINT;	
	
	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;
	
	jjObjectPresets[OBJECT::BILSY].behavior = Tweedle;
	jjObjectPresets[OBJECT::BILSY].points = 1000;
	jjObjectPresets[OBJECT::BILSY].energy = 40;
	jjObjectPresets[OBJECT::BILSY].isBlastable = false;
	//jjObjectPresets[OBJECT::BILSY].scriptedCollisions = true;
	jjObjectPresets[OBJECT::BILSY].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::BILSY].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::BILSY].state = STATE::START;
	jjObjectPresets[OBJECT::BILSY].xSpeed = 1;
	//jjObjectPresets[OBJECT::BILSY].deactivates = true;
	
	
	jjObjectPresets[OBJECT::SPARK].behavior = Flame;
	jjObjectPresets[OBJECT::SPARK].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::SPARK].playerHandling = HANDLING::ENEMYBULLET;
	jjObjectPresets[OBJECT::SPARK].animSpeed = 1; //damage done to player
	jjObjectPresets[OBJECT::SPARK].state = STATE::FLOAT;
	jjObjectPresets[OBJECT::SPARK].lightType = LIGHT::POINT;
	jjObjectPresets[OBJECT::SPARK].points =0;
	jjObjectPresets[OBJECT::SPARK].light =55;
	jjObjectPresets[OBJECT::SPARK].isTarget=false;
	jjObjectPresets[OBJECT::SPARK].scriptedCollisions=true;
	
	jjObjectPresets[OBJECT::CHESHIRE2].energy = 4;
	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;
	
	jjChat("/fireball on");
	}
	

	
	void updateGems()
{
  for(int i=1;i<jjObjectCount;i++)
  {
    if(jjObjects[i].isActive)
    {
      if(jjObjects[i].eventID==OBJECT::SUPERGEM)
      {
        jjObjects[i].var[0]=jjParameterGet(jjObjects[i].xOrg/32,jjObjects[i].yOrg/32,0,2)+1;
      }
      if(jjObjects[i].eventID==OBJECT::FLICKERGEM)
      {
        if(jjEventGet(jjObjects[i].xOrg/32,jjObjects[i].yOrg/32)==OBJECT::SUPERGEM)
        {
          jjObjects[i].var[0]=jjParameterGet(jjObjects[i].xOrg/32,jjObjects[i].yOrg/32,0,2)+1;
        }
        else if(jjEventGet(jjObjects[i].xOrg/32,jjObjects[i].yOrg/32+1)==OBJECT::GEMSTOMP)
        {
          jjObjects[i].var[0]=jjParameterGet(jjObjects[i].xOrg/32,jjObjects[i].yOrg/32+1,0,2)+1;
        }
        if(jjObjects[i].var[0]==2||jjObjects[i].var[0]==3)
        {
          jjObjects[i].points=500*(jjObjects[i].var[0]-1);
        }
      }
    }
  }
}

		void onFunction10(jjPLAYER@ play) {
		jjTriggers[10]=true;

	}
	
	void HatterX(jjOBJ@ enemy) {
		enemy.behave(BEHAVIOR::HATTER);
	   		if (enemy.energy==0&&jjRandom() & 2 == 0)
			{jjAddObject(OBJECT::GUN8AMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
	    }	
		
	void DragonflyX(jjOBJ@ enemy) {
		enemy.behave(BEHAVIOR::DRAGONFLY);
	   		if (enemy.energy==0&&jjRandom() & 5 == 0)
			{jjAddObject(OBJECT::CARROT, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
			else if (enemy.energy==0)
			{enemy.state = STATE::KILL;}
	    }	

		void TurtleX(jjOBJ@ enemy) {
		enemy.behave(BEHAVIOR::NORMTURTLE );
	   		if (enemy.energy==0&&jjRandom() & 2 == 0)
			{jjAddObject(OBJECT::GUN8AMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
	    }		
	
void FlamingCat(jjOBJ@ enemy) { 
	
	
		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 c=((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+15;
			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+15;
			obj.xPos = enemy.xPos;
		}
		enemy.determineCurAnim(ANIM::CAT2,2);
		enemy.determineCurFrame();
		enemy.frameID = enemy.counter/50;
		enemy.counter += 5; 
		
		enemy.xPos = jjSin(enemy.counter/c)*c + enemy.xPos; 
		enemy.yPos = jjCos(enemy.counter/3*c)*2*c + enemy.yPos ;//Lissajous figures :D
	if (++enemy.counter > 3300) 
	{
	enemy.xAcc= enemy.yAcc =0;
	enemy.state = STATE::FADEOUT;
	enemy.counter =0;
	
						}
		
		
		
		
	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;
			}
			else {enemy.state = STATE::FLOAT;}
		}
		break;
		case STATE::FADEIN:
			enemy.bulletHandling = HANDLING::HURTBYBULLET;
		c=((jjRandom() & 5)-2.5);

		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;
			}
			break;
	case STATE::DEACTIVATE:
		enemy.deactivate();
		break;		
	case STATE::KILL:
	if (jjRandom() & 2 == 0)
	{jjAddObject(OBJECT::TOASTERAMMO3, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);}
	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();
	} else
		enemy.delete();
	}
	
								
	
	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 (plat.yOrg>13*32&&plat.yOrg<14*32&&plat.xOrg>23*32&&plat.xOrg<45*32)
	plat.xOrg = (34*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(10*32);
if (plat.yOrg>26*32&&plat.yOrg<38*32&&plat.xOrg>93*32&&plat.xOrg<95*32)
	plat.yOrg = (32*32) + jjCos(++plat.counter*((jjDifficulty+1)^0.5))*(5*32);
if (plat.yOrg>47*32&&plat.yOrg<93*32&&plat.xOrg>30*32&&plat.xOrg<32*32)
	plat.yOrg = (70*32) + jjCos(++plat.counter*1)*(22*32);	
if (plat.yOrg>47*32&&plat.yOrg<93*32&&plat.xOrg>33*32&&plat.xOrg<35*32)
	plat.yOrg = (70*32) + jjCos(++plat.counter*1)*(22*32);		
if (plat.yOrg>76*32&&plat.yOrg<94*32&&plat.xOrg>134*32&&plat.xOrg<136*32)
	plat.yOrg = (85*32) + jjCos(++plat.counter*1)*(8*32);		
if (plat.yOrg>56*32&&plat.yOrg<78*32&&plat.xOrg>142*32&&plat.xOrg<144*32)
	plat.yOrg = (68*32) + jjCos(++plat.counter*1)*(9*32);	
if (plat.yOrg>43*32&&plat.yOrg<75*32&&plat.xOrg>130*32&&plat.xOrg<132*32)
	plat.yOrg = (59*32) + jjCos(++plat.counter*1)*(15*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::TNTAMMO3)];
			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::TNTAMMO3)];
			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 PlatFlame(jjOBJ@ flame) {
	if (flame.state== STATE::FLOAT)
		flame.behave(BEHAVIOR::PICKUP);
		++flame.counter;
		if (flame.counter >40)
				flame.delete();
	}

	
	
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:
	boss.var[1]=(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.findNearestPlayer(600*600) > -1) && ++boss.counter > 55)
		{boss.state = STATE::IDLE; boss.counter = 0;}
		break;
 case STATE::WALK:
        boss.behave(BEHAVIOR::WALKINGENEMY);
        {
		if (boss.counter >= 180)
		{boss.counter = 0; }
       //jjAlert("boss.counter "+ formatInt(boss.counter, "1"));
	   //jjAlert("boss.frameID "+ formatInt(boss.frameID, "1"));
                boss.counter++;
                if (boss.var[1]==0||boss.var[1]==1)
                {if (++boss.counter < 165){
                        boss.xSpeed= (jjDifficulty+3)*boss.direction;
                        boss.determineCurAnim(ANIM::TWEEDLE, 1);
                        if (boss.counter == 10){
                        jjSample(boss.xPos, boss.yPos, SOUND::INTRO_GREN3);}
                        if (boss.justHit == 0)
                        {jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);}
                        boss.determineCurFrame();
                        //boss.frameID = boss.counter/10;
						}
                        else
                        {boss.frameID = boss.counter = 0;
                        boss.state = STATE::IDLE;}
                        }
                        else if (boss.var[1]==2||boss.var[1]==3)
                        {if (++boss.counter < 180){
                        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;
                        }

       
                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:

			if (++boss.counter == 5){
					jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
			if (particle !is null) {
				particle.xPos = boss.xPos;
				particle.yPos = boss.yPos;
				particle.string.text = "1000";
				particle.ySpeed = -1.2;
				particle.xSpeed = -1.1;
				play.score += 1000;
			}}
	
		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 = 100;}
			if (++boss.counter>90) {
	boss.state = STATE::KILL;
			boss.counter==0;			
		//jjEventSet(p.xPos / 32, p.yPos / 32, AREA::EOL);
		}
		break;
	case STATE::KILL:
	jjAddParticlePixelExplosion(boss.xPos, boss.yPos, boss.curFrame, 0, 2);
	if (jjRandom() & 2 == 0)	
	{jjAddObject(OBJECT::BOUNCERAMMO3, boss.xPos, boss.yPos, play.playerID, CREATOR::PLAYER);
	boss.delete();}
	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 ((boss.var[1]==0||boss.var[1]==1)&& ((jjDifficulty > 1 && boss.counter == 25)||boss.counter == 30|| (jjDifficulty > 1 && boss.counter == 35)))
			{
		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 ((boss.var[1]==2) && ((jjDifficulty > 1 && boss.counter == 25)||boss.counter == 30|| (jjDifficulty > 1 && boss.counter == 35)))
			{
				jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::SMOKERING)];
				//bullet.behave(BEHAVIOR::BULLET);
				//bullet.xSpeed = bullet.direction*2;   
	            bullet.ySpeed = 0;
				bullet.yAcc = 0;
				//bullet.xAcc = 0;
				bullet.xPos = boss.xPos;
				bullet.yPos = boss.yPos-7; 	
				jjSample(boss.xPos, boss.yPos, SOUND::INTRO_BLOW);
			}
			else if (boss.var[1]==3 && ( boss.counter == 30))
			{
		//jjOBJ@ bullet = jjObjects[boss.fireBullet(OBJECT::ELECTROBULLETPU)];
				
				jjSample(boss.xPos, boss.yPos, SOUND::WITCH_MAGIC);
			int spell = OBJECT::APPLE;
			jjOBJ@ obj = jjObjects[boss.fireBullet(OBJECT::APPLE)];
			obj.killAnim = obj.determineCurAnim(ANIM::AMMO, 4, false);
			obj.determineCurAnim(ANIM::WITCH,3);
			obj.determineCurFrame();	
			obj.yPos = boss.yPos;
			obj.xPos = boss.xPos+32*(boss.direction);
			}
			
		} else {
			boss.frameID = boss.counter = 0;
			boss.determineCurAnim(ANIM::TWEEDLE, 6);
			boss.state = STATE::IDLE;
		}
		break;
	}
	
}

							void WITCHSPELL(jjOBJ@ enemy) {
		jjPLAYER@ play = jjLocalPlayers[0];
		
		if (enemy.xOrg > play.xPos)
				enemy.xPos = enemy.xPos - (2+jjDifficulty/4); 
		else if (enemy.xOrg < play.xPos) 
				enemy.xPos = enemy.xPos + (2+jjDifficulty/4);
		//if (enemy.yPos > play.yPos)
		//		enemy.yPos = enemy.yPos - (2+jjDifficulty/4); 
		//else if (enemy.yPos < play.yPos) 
		//		enemy.yPos = enemy.yPos + (2+jjDifficulty/4);
		enemy.determineCurAnim(ANIM::WITCH,3);
		enemy.determineCurFrame();
		enemy.frameID = enemy.counter/8;
		//enemy.draw();
		++enemy.counter;
		enemy.counter += 1; 
		 if (jjMaskedPixel (enemy.xPos + enemy.xSpeed, enemy.yPos))
		{enemy.delete();
		  int explosionID = jjAddObject(OBJECT::BLASTERBULLET, enemy.xPos, enemy.yPos, enemy.creator, CREATOR::OBJECT);
		jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 4, true);
		jjObjects[explosionID].state = STATE::EXPLODE;
		}
	enemy.draw();}



		void onPlayerTimerEnd(jjPLAYER@ play) {
	play.jumpStrength = -10; 
}


void SpitGun (jjOBJ@ spit) {
	jjPLAYER@ play = jjPlayers[spit.creatorID];
	
	//spit.behave(BEHAVIOR::BULLET, true); 
	if (spit.state == STATE::START)
	if (jjSoundEnabled) 
	{jjSample(spit.xPos, spit.yPos, SOUND::HATTER_PTOEI);}
	spit.state = STATE::FLY;
	//if (jjGameTicks %2==0)
	//spit.animSpeed=1;
	//else
	//{spit.animSpeed=0;}
	
	if (play.keyUp = true &&play.fly==0)
	{spit.ySpeed = -10;
	spit.determineCurAnim(ANIM::HATTER, 3);
	}
	spit.xPos = spit.xPos + spit.xSpeed/2+spit.var[7]/(65536*2);
	spit.yPos = spit.yPos + spit.ySpeed/2+spit.var[7]/(65536*2);
	if (jjMaskedPixel(spit.xPos, spit.yPos)||((spit.xSpeed==0)&&(spit.ySpeed==0)))
		spit.state = STATE::EXPLODE;
	if (spit.state == STATE::EXPLODE) {
		spit.behavior = BEHAVIOR::EXPLOSION2;
	}
	spit.determineCurFrame();
	spit.draw();
}

void NPC(jjOBJ@ obj) {
jjPLAYER@ play = jjLocalPlayers[0];
	if (obj.state == STATE::START) {
					if (play.charCurr == CHAR::JAZZ)
					
				{obj.determineCurAnim(ANIM::SPAZ, 102);
				obj.xSpeed = 2;}
				else 
				{obj.determineCurAnim(ANIM::JAZZ, 101);}
				obj.xSpeed = 2;
		
		
		obj.state = STATE::WALK;
	}
	obj.behave(BEHAVIOR::WALKINGENEMY);
}
	
	
	void apply(jjPAL pal = jjPalette) {
	jjSetFadeColors(
		pal.color[207].red,
		pal.color[207].green,
		pal.color[207].blue
	);
	pal.apply();
}

bool onDrawLives(jjPLAYER@ player, jjCANVAS@ screen) {

screen.drawSprite(590, 45, ANIM::PICKUPS, 24, jjGameTicks>>2, -1, SPRITE::NORMAL);
screen.drawSprite(570, 45, ANIM::PICKUPS, 25, jjGameTicks>>2, -1, SPRITE::NORMAL);
screen.drawSprite(580, 30, ANIM::PICKUPS, 81, jjGameTicks>>2, -1, SPRITE::NORMAL);
screen.drawString(570, 15, "SUGAR RUSH", STRING::SMALL, STRING::PALSHIFT, 16);
screen.drawString(600, 35, formatInt(player.food%100, "1") + " / 100", STRING::MEDIUM, STRING::PALSHIFT, 32);
			//screen.drawTile(440, 5, 748);
			//screen.drawSprite(460, 15, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 2);
 
	if (player.gems[GEM::PURPLE] < gemgoal) {
		if (player.localPlayerID == 0) {
			screen.drawString(290, 45, formatInt(player.gems[GEM::PURPLE], "1") + " / " + formatInt(gemgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 232);
			//screen.drawTile(320, 5, 748);
			//screen.drawSprite(320, 5, ANIM::PICKUPS, 35, 1, SPRITE::NORMAL);
			//screen.drawSprite(320, 5, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 0);
		
			screen.drawString(170, 15, formatInt(player.gems[GEM::RED], "1") + " / 5", STRING::MEDIUM, STRING::PALSHIFT, 32);
			//screen.drawTile(200, 5, 748);
			screen.drawSprite(150, 15, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 0);
			
			
			screen.drawString(290, 15, formatInt(player.gems[GEM::GREEN], "1") + " / 2", STRING::MEDIUM, STRING::PALSHIFT, 32);
			//screen.drawTile(320, 25, 748);
			screen.drawSprite(270, 15, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 1);
			
			screen.drawString(410, 15, formatInt(player.gems[GEM::BLUE], "1") + " / 10", STRING::MEDIUM, STRING::PALSHIFT, 32);
			//screen.drawTile(440, 5, 748);
			screen.drawSprite(390, 15, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 2);
			
			//screen.drawSprite(120, 130, ANIM::PICKUPS, 35, SPRITE::RESIZED,16); 
		
		}
		}
if (player.gems[GEM::PURPLE] >= gemgoal) {
screen.drawString(290, 45, formatInt(p.gems[GEM::PURPLE], "1") + " / " + formatInt(gemgoal, "1"), STRING::MEDIUM, STRING::PALSHIFT, 16);}
//screen.drawTile(320, 5, 748);		
	screen.drawSprite(270, 45, ANIM::PICKUPS, 35, jjGameTicks>>2, -1, SPRITE::GEM, 3);	
	return false;
}

bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) {
	 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;
}

void onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if (obj.eventID == OBJECT::SPARK) {
 if (play !is null) {
			if (force == 0) //normal collision, not using any buttstomps or whatever
				play.hurt();
				else if (force != 0)
				{obj.delete();}}
				}
					else if (obj.eventID == OBJECT::APPLE)
	{  //boss.eventID == OBJECT::WITCH;
	obj.state = STATE::EXPLODE;
		obj.scriptedCollisions = false;
		play.morphTo(CHAR::FROG, false);}
					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);
	}
				}