Downloads containing turtlevania.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Castle Turtlevania Speaktrap Single player 6.9 Download file

File preview

//this script is a MESS!

int maxhealth = 3;
int health = maxhealth;

const uint tweedleMaxClones = 4;
const uint tweedleCooldown = 128; //192
const uint bubbaLifesteal = 4;

//abilities
bool running_boots = false;
bool super_jump = false;
bool mega_jump = false;
int lastWep = 0;

//cheats ;)
//bool running_boots = true;
//bool super_jump = true;

//RU-RU-RU-RURKOWCE
bool doopy = true;
//I CO TERAS?



//a lot of variables
bool sjumping = false;
bool firstmusic = false;
bool chaos_on = false;
bool noHUD = false;
bool alreadyStoned = false;
bool spazm = false;

bool paintingbossFight = false;
bool bubbaFight = false;
bool tweedleFight = false;
bool paintingDefeated = false;
bool bubbaDefeated = false;
bool tweedleDefeated = false;
bool paintfrozen = false;


uint paintingFrameID = 0;
uint psubFrameID = 0;
int bubbaID = 0;
int tweedleID = 0;
int tweedleGhosts = 0;
int ammodrop;
int place = 1;
int paintingbossID;

array<bool> CollectedWeapons(9,false);

jjOBJ@ enemy;
//jjOBJ@ tweedleObj;


const uint dnCYCLELENGTH=700; // Day Length.
const uint dnEVERYXTICKS=4; //the amount ticks the pallette refreshes it's colours.
const uint dnINITIALTICKS=256; //determines the initial time of the day. 0 means dawn, 256 means noon, 512 means dusk, 768 means midnight and 1024 means dawn again. All values allowed.
const string dnNIGHTTILESET="Inferno1.j2t"; // the name of the tileset whose palette should be used in midnight.
const string dnDAYTILESET="InfernoN.j2t";
jjPAL PaletteNight;
jjPAL PaletteDay;

bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
	if (!noHUD){
      canvas.drawString(
			24,
	      		jjSubscreenHeight - 445,
	      		(health + "/" + maxhealth),
	      		STRING::MEDIUM,
	      		STRING::NORMAL
		);
		
	      	canvas.drawString(
			16,
	      		jjSubscreenHeight - 460,
	      		"Health",
	      		STRING::SMALL,
	      		STRING::NORMAL
		);}
    return true;
}

bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {
	
	return true;
	}
	
bool onDrawAmmo(jjPLAYER@ p, jjCANVAS@ canvas) {
	return noHUD;
}

bool onDrawScore(jjPLAYER@ p, jjCANVAS@ canvas) {
	return true;
}	

/***Constants***/
const float cMaxSpeed = 10; //The maximum speed the boomerang can have
const float cAcceleration = 0.2; //The acceleration of the boomerang
const float cReturnAccMult = 1; //When the boomerang is returning, this is a multiplier for the acceleration (so a value of 2 let's the boomerang return with 2x acceleration)
const float cVerSpdMult = 0.7; //When the boomerang is shot vertical and not returning, this is a multiplier for the acceleration (a higher value lets the boomerang go faster and higher upward)
const float cReturnSpeed = 0.4; //At what speed the boomerang returns back to the player (WARNING! This constant should always be higher than cAcceleration)
const float cReturnRadius = 32; //Radius in pixels at which the player takes the boomerang back

const float cBombSpeed = 7; //xSpeed of the bomb
const float cBombPlayerSpeed = 10; //xSpeed the bomb can gain by player speed (if a player is running full speed it will add 6 xSpeed)
const int cBombLifeTime = 60; //Time till the bomb explodes (run away! run away!!!1)
 
 
/***Variables***/
array<bool> returning(32, false);
array<bool> boomerangfired(32, false);
array<float> speed(32, cMaxSpeed);
 
/***Math functions***/
//Calculates the distance between two points
float distance(float x1, float y1, float x2, float y2) {
  return sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
}

void CreateBomb(int objectID) {
  int playerID = jjObjects[objectID].creator - 32768;
  int bombID = jjAddObject(OBJECT::APPLE, jjPlayers[playerID].xPos, jjPlayers[playerID].yPos - 24, jjPlayers[playerID].playerID, CREATOR::PLAYER);
  jjObjects[bombID].objType = 3;
  jjObjects[bombID].determineCurAnim(ANIM::BUBBA, 6, true);
  jjObjects[bombID].special = 11;
  jjObjects[bombID].xSpeed = cBombSpeed*jjPlayers[playerID].direction + cBombPlayerSpeed*jjPlayers[playerID].xSpeed/16;
  jjObjects[bombID].ySpeed = -1;
}
 
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::BUBBA, 8, true);
  jjObjects[explosionID].killAnim = ANIM::AMMO;
  jjObjects[explosionID].state = STATE::EXPLODE;
}

/***Other functions***/
void BoomerangGun(int boomerangID) {
  int playerID = jjObjects[boomerangID].creator - 32768;
 
  if ((abs(jjObjects[boomerangID].xSpeed) < cReturnSpeed && jjObjects[boomerangID].direction != 0) || (abs(jjObjects[boomerangID].ySpeed) < cReturnSpeed && jjObjects[boomerangID].direction == 0) && !returning[playerID])
    returning[playerID] = true;
 
  if (jjObjects[boomerangID].counter == 1) {
    if (playerID == p.playerID)
      p.noFire = true;
    jjObjects[boomerangID].determineCurAnim(ANIM::TUFBOSS, 3);
    jjObjects[boomerangID].counterEnd = 254;
  }
 
  if (returning[playerID]) {
    if (distance(jjPlayers[playerID].xPos, jjPlayers[playerID].yPos, jjObjects[boomerangID].xPos, jjObjects[boomerangID].yPos) < cReturnRadius)
      jjKillObject(boomerangID);
   
    if (speed[playerID] < cMaxSpeed)
      speed[playerID] = speed[playerID] + cAcceleration*cReturnAccMult;
 
    jjObjects[boomerangID].ySpeed = speed[playerID]*(jjPlayers[playerID].yPos - jjObjects[boomerangID].yPos)/distance(jjPlayers[playerID].xPos, jjPlayers[playerID].yPos, jjObjects[boomerangID].xPos, jjObjects[boomerangID].yPos);
    jjObjects[boomerangID].xSpeed = speed[playerID]*(jjPlayers[playerID].xPos - jjObjects[boomerangID].xPos)/distance(jjPlayers[playerID].xPos, jjPlayers[playerID].yPos, jjObjects[boomerangID].xPos, jjObjects[boomerangID].yPos);
  } else {
    if (speed[playerID] > 0)
      speed[playerID] = speed[playerID] - cAcceleration;
    if (jjObjects[boomerangID].direction == 0)
      jjObjects[boomerangID].ySpeed = -speed[playerID]*cVerSpdMult;
    else
      jjObjects[boomerangID].xSpeed = speed[playerID]*jjObjects[boomerangID].direction;
  }
 
  if (jjObjects[boomerangID].counter > 200)
    jjObjects[boomerangID].counter = 30;
}

void ChaoticRealm(){
	for(int i=1;i<4096;i++) jjTileType[i] = 5;
	PaletteNight.load(dnNIGHTTILESET);
	PaletteDay.load(dnDAYTILESET);
	jjLayerHasTiles[7] = false;
	jjTexturedBGTexture = TEXTURE::XARGON;
	jjTexturedBGStyle = TEXTURE::TILEMENU;
	jjLocalPlayers[0].showText("@@@@@@@@CHAOTIC REALM", STRING::MEDIUM);
	chaos_on = true;
}

void onLevelLoad()
{
	jjWaterLighting = WATERLIGHT::GLOBAL;
	jjSetWaterLevel(32*104, true);
	
	//jjSetWaterGradient(167, 19, 239, 7, 0, 19);
	jjSetWaterGradient(45, 0, 62, 7, 0, 9);
	jjObjectPresets[OBJECT::PEAR].determineCurAnim(ANIM::PICKUPS,33);
	jjObjectPresets[OBJECT::LIME].determineCurAnim(ANIM::PICKUPS,40);
	//jjObjectPresets[OBJECT::PRETZEL].determineCurAnim(ANIM::PICKUPS,40);
	jjObjectPresets[OBJECT::SPIKEBOLL].energy = 80;
	jjObjectPresets[OBJECT::SPIKEBOLL].bulletHandling = HANDLING::HURTBYBULLET;
	jjObjectPresets[OBJECT::SPIKEBOLL].behavior = paintbossB;
	jjObjectPresets[OBJECT::BEE].energy = 80;
	jjObjectPresets[OBJECT::PRETZEL].lightType = LIGHT::LASER;
	jjObjectPresets[OBJECT::PRETZEL].light = 40;
	jjObjectPresets[OBJECT::PEAR].lightType = LIGHT::LASER;
	jjObjectPresets[OBJECT::PEAR].light = 40;
	jjObjectPresets[OBJECT::LIME].lightType = LIGHT::LASER;
	jjObjectPresets[OBJECT::LIME].light = 40;
	jjObjectPresets[OBJECT::BEE].bulletHandling = HANDLING::HURTBYBULLET;
	
	
	jjPIXELMAP painting(64, 13*32, 64, 64);
		paintingFrameID = jjAnimations[jjAnimSets[ANIM::SPIKEBOLL].firstAnim].firstFrame;
		jjANIMFRAME@ frame = jjAnimFrames[paintingFrameID];
		painting.save(frame);
		frame.hotSpotX = -32;
		frame.hotSpotY = -32;
		
	//jjPIXELMAP psub(22*32, 9*32, 23*32, 10*32);
		psubFrameID = jjAnimations[jjAnimSets[ANIM::SPIKEBOLL].firstAnim].firstFrame;
		jjANIMFRAME@ frameChain = jjAnimFrames[psubFrameID+1];
		//psub.save(frameChain);
		//frame2.hotSpotX = -32;
		//frame2.hotSpotY = -32;
}
void onLevelBegin(){
	p.yPos = 32*99+16;
}

void paintbossB(jjOBJ@ paint) {
	paint.behave(BEHAVIOR::PLATFORM, false);
	jjDrawSpriteFromCurFrame(paint.xPos, paint.yPos, (ANIM::SPIKEBOLL), paint.direction);
}

void onFunction0(jjPLAYER@ p) {
//Painting Boss
if (!paintingbossFight && !paintingDefeated){
  paintingbossFight = true;
  jjMusicLoad("Pip Malt - Redemption.it");
  p.boss = paintingbossID;
  jjObjects[paintingbossID].light = 25;
  jjObjects[paintingbossID].lightType = LIGHT::NORMAL;
  //p.boss = jjAddObject(OBJECT::SPIKEBOLL, 101*32, 96*32);
  p.bossActivated = true;
  p.cameraFreeze(182*32, 98*32, true, false);
  jjTriggers[0] = true;}
}

void onFunction1(jjPLAYER@ p) {
//Bubba Boss
if (!bubbaFight && !bubbaDefeated){
  jjMusicLoad("Pip Malt - Amiable Arachnids.it");
  bubbaID = jjAddObject(OBJECT::BUBBA, 201*32, 38*32);
  p.boss = bubbaID;
  p.bossActivated = true;
  p.cameraFreeze(200*32, 36*32, true, false);
  jjTriggers[28] = true;
  bubbaFight = true;}
}

void onFunction2(jjPLAYER@ p) {
	if (place != 2){
	jjMusicLoad("whisper.s3m");
	//jjAlert("||CLOCKTOWER");
	jjLocalPlayers[0].showText("@@@@@@@@CLOCKTOWER", STRING::MEDIUM);
	place = 2;
	}
}

void onFunction3(jjPLAYER@ p) {
	if (place != 3){
	jjMusicLoad("life_of_stagelife.mod");
	jjLocalPlayers[0].showText("@@@@@@@@DEVIL'S GALLERY", STRING::MEDIUM);
	//jjAlert("||DEVIL'S GALLERY");
	place = 3;
	}
}

void onFunction4(jjPLAYER@ p) {
	if (place != 1){
	jjMusicLoad("fear2.mod");
	place = 1;
}
}

void onFunction5(jjPLAYER@ p) {
	if (place != 4){
	jjMusicLoad("knew.s3m");
	jjLocalPlayers[0].showText("@@@@@@@@CASTLE WALL", STRING::MEDIUM);
	//jjAlert("||CASTLE WALL");
	place = 4;
	}
}

void onFunction6(jjPLAYER@ p) {
	//Tweedle boss!!!//
	if (!tweedleFight && !tweedleDefeated){
	jjMusicLoad("Pip Malt - The Serpent's Wings.it");
	tweedleID = jjAddObject(OBJECT::BEE, 399*32, 11*32);
	jjObjects[tweedleID].determineCurAnim(ANIM::TWEEDLE, 1);
	p.boss = jjObjects[tweedleID].objectID;
	p.bossActivated = true;
	p.cameraFreeze(398*32, 11*32, true, false);
	jjTriggers[23] = true;
	tweedleFight = true;
	}
}
void onFunction7(jjPLAYER@ p) {
	p.xPos = p.xPos + 9376;
	p.yPos = p.yPos - 160;
	jjMusicLoad("goodbye_world.mod");
	ChaoticRealm();
}

void onFunction8(jjPLAYER@ p) {
	jjMusicLoad("turtlevania-music.mod");
	//ChaoticRealm();
}

void onPlayerInput(jjPLAYER@ play) {
//if (play.keySelect){

//}

if (!running_boots && health > 0) play.keyRun = false;
//if (sjumping && p.keyJump) sjumping = false;
//if (super_jump && p.keyDown && p.keyJump && p.ySpeed < 0) sjumping = true;

if (super_jump && p.keySelect && p.keyUp && p.charCurr != CHAR::BIRD) {
      		p.morphTo(CHAR::BIRD);
      		lastWep = p.currWeapon;
      		
      	 }
      	 
      	 if (super_jump && p.keySelect && p.keyDown && p.charCurr == CHAR::BIRD) {
      		p.revertMorph();
      		p.currWeapon = lastWep - 2;
      		
      	 }


      	//GRAVITY BOOTS
       if (mega_jump && p.ySpeed != 0 && p.keyUp && !p.antiGrav && p.charCurr != CHAR::BIRD) {
      		p.antiGrav = true;
      		p.buttstomp = 2;
			}
      	if (p.antiGrav){
			if (p.buttstomp > 118 || p.charCurr == CHAR::BIRD){
				p.antiGrav = false; }
      	
			if (p.keyDown && !p.keyUp){
				p.antiGrav = false;
				p.buttstomp = 2;
			}
      	}


if (health <= 0){
	play.keyRight = false;
	play.keyLeft = false;
	play.keyFire = false;
	play.keyRun = true;
	play.keyJump = false;
  }
if (p.lives != 3) health = 0;
}

void onPlayer() {
	
	if (doopy){
		if (p.xPos <= 768) doopy = false; //RURURURURURRURURUU
		if (p.xPos > 768) health = 0;
	}
	
	
	/*if (p.charOrig==CHAR::SPAZ && !spazm){
		jjAlert("|||||SPAZ MODE ACTIVATED");
		running_boots = true;
		spazm = true;
	}*/
	//if (spazm && p.ySpeed > 0) p.alreadyDoubleJumped = false;
	jjCHARACTER@ char = jjCharacters[p.charCurr];
	char.airJump =  AIR::HELICOPTER;
	char.groundJump = GROUND::JAZZ;
	
	
  if (!firstmusic && p.xPos > 32*92){
    jjMusicLoad("fear2.mod");
    firstmusic = true;
    }
    
  if (!firstmusic && p.xPos > 768 && p.xPos < 1024 && p.health == 5) p.health = 3;  
  //p.alreadyDoubleJumped = false;
  if (health <= 0 && p.xPos > 24*32){
	  p.bossActivated = false;
	  tweedleFight = false;
	  paintingbossFight = false;
	  bubbaFight = false;
	  noHUD = true;
	  p.cameraUnfreeze();
	  p.yPos = 40*32;
	  jjMusicStop();
  }
  if (health <= 0) p.xPos = (21*32)-30;
  if (p.health == 5 && p.xPos > 768){
	  maxhealth = maxhealth + 1;
	  p.health = 3;
	  health = maxhealth;
	  jjAlert("            |            |            Maximum health increased!");
	  //jjDrawString(p.cameraX + 40,  p.cameraY + (jjResolutionHeight * 0.75), "Maximum health increased", STRING::MEDIUM, STRING::NORMAL, 0, 1);
  }
  else if (p.health == 4){
	  if (health != maxhealth) health = health + 1;
	  p.health = 3;
  }
  else if (p.health == 2){
	  health = health - 1;
	  p.health = 3;
	  jjTriggers[19] = true;
	  if (bubbaFight){
		  jjObjects[bubbaID].energy = jjObjects[bubbaID].energy  + bubbaLifesteal;
		  jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
					if (particle !is null) {
						particle.xPos = jjObjects[bubbaID].xPos;
						particle.yPos = jjObjects[bubbaID].yPos;
						particle.string.text = "|+HEALTH";
						particle.ySpeed = -0.25;		
					}
	  }
  }

  
  
  if (!CollectedWeapons[2] && p.ammo[WEAPON::BOUNCER] > 0) CollectedWeapons[2]=true;
  if (!CollectedWeapons[3] && p.ammo[WEAPON::ICE] > 0) CollectedWeapons[3]=true;
  if (!CollectedWeapons[6] && p.ammo[WEAPON::TOASTER] > 0) CollectedWeapons[6]=true;
  if (!CollectedWeapons[5] && p.ammo[WEAPON::RF] > 0) CollectedWeapons[5]=true;
  
  
  /*if (sjumping){
    p.ySpeed = -20;
    if (jjMaskedHLine(p.xPos, 24, p.yPos - 32)) sjumping = false;
    }*/
  if (p.food >= 1 && !running_boots && p.xPos > 80*32 && p.xPos < 90*32 && p.yPos < 97*32) {
    running_boots = true;
    jjLocalPlayers[0].showText("@@@@@@@@YOU GOT SNEAKERS OF MERCURY!", STRING::MEDIUM);
    //jjAlert("            |            |        YOU GOT SNEAKERS OF MERCURY!");
    jjAlert("            |            |               Now you can sprint");
    jjSample(p.xPos, p.yPos, SOUND::COMMON_HARP1);
    p.food = 0;
    }
   if (p.food >= 1 && !super_jump && p.xPos > 430*32 && p.xPos < 445*32) {
    super_jump = true;
    jjLocalPlayers[0].showText("@@@@@@@@YOU GOT THE CARROT OF FLIGHT!", STRING::MEDIUM);
    //jjAlert("            |            |       YOU GOT THE CARROT OF FLIGHT!");
    jjAlert("            |        |     Press select weapon + up to fly");
    jjAlert("            |        |     and select weapon + down to revert");
    jjSample(p.xPos, p.yPos, SOUND::COMMON_HARP1);
    p.food = 0;
    }
    if (p.food >= 1 && !mega_jump && p.xPos > 80*32 && p.xPos < 90*32 && p.yPos > 97*32) {
    mega_jump = true;
    jjSetWaterLevel(32*127, false);
    jjLocalPlayers[0].showText("@@@@@@@@YOU GOT GRAVITY PRETZEL!", STRING::MEDIUM);
    //jjAlert("            |            |        YOU GOT GRAVITY PRETZEL!");
    jjAlert("            |            |               Press up while airborne");
    jjSample(p.xPos, p.yPos, SOUND::COMMON_HARP1);
    p.food = 0;
    }
  for (int i = 1; i < jjObjectCount; i++) {
    @enemy = jjObjects[i];
    //if (enemy.eventID == OBJECT::BUBBA) @bubbaObj = jjObjects[i];
    if (enemy.objType >= 16 && enemy.state == STATE::KILL && enemy.isActive && jjGameTicks%3 == 0) {
      switch (enemy.eventID) {
        //case OBJECT::BAT: ammodrop = OBJECT::BOUNCERAMMO3; break;
        case OBJECT::DRAGON: ammodrop = OBJECT::TOASTERAMMO3; break;
        case OBJECT::FISH: ammodrop = OBJECT::ICEAMMO3; break;
        case OBJECT::SPARK: ammodrop = OBJECT::GUN9AMMO3; break;
        case OBJECT::HELMUT: ammodrop = OBJECT::RFAMMO3; break;
        default: {
        switch (jjRandom()%8) {
          case 0: if (CollectedWeapons[2]) ammodrop = OBJECT::BOUNCERAMMO3; break;
          case 1: if (CollectedWeapons[3]) ammodrop = OBJECT::ICEAMMO3; break;
          case 2: if (p.ammo[WEAPON::SEEKER] > 0) ammodrop = OBJECT::SEEKERAMMO3; break;
          case 3: if (CollectedWeapons[5]) ammodrop = OBJECT::RFAMMO3; break;
          case 4: if (CollectedWeapons[6]) ammodrop = OBJECT::TOASTERAMMO3; break;
          case 5: if (p.ammo[WEAPON::TNT] > 0) ammodrop = OBJECT::TNTAMMO3; break;
          case 6: if (p.ammo[WEAPON::GUN8] > 0) ammodrop = OBJECT::GUN8AMMO3; break;
          case 7: if (p.ammo[WEAPON::GUN9] > 0) ammodrop = OBJECT::GUN9AMMO3; break;
          }
        }
      }
        jjAddObject(ammodrop, enemy.xPos, enemy.yPos, p.playerID, CREATOR::PLAYER);
    }
  }
  if (p.stoned == 0 && alreadyStoned) alreadyStoned = false;
  if (p.stoned>0 && !alreadyStoned){
		jjPARTICLE@ particle = jjAddParticle(PARTICLE::STRING);
					if (particle !is null) {
						particle.xPos = p.xPos;
						particle.yPos = p.yPos;
						particle.string.text = "||CURSE";
						particle.ySpeed = -0.25;		
					}
					alreadyStoned = true;
				}
}

/***Gameplay functions***/
void onMain() {
	
	if(chaos_on && jjGameTicks%dnEVERYXTICKS==0) {
    jjPalette=PaletteNight;
    jjPalette.copyFrom(2,252,2,PaletteDay,(jjSin(1024*jjGameTicks/dnCYCLELENGTH+dnINITIALTICKS)+1)/2);
    jjPalette.apply();
	}
	
	//jjObjects[paintingbossID].xPos = 183*32;
	//jjObjects[paintingbossID].yPos = 100+jjSin(jjGameTicks);
	
	
  for (int i = 0;  i < jjObjectCount; i++){
    if (paintingbossID == 0 && jjObjects[i].eventID == OBJECT::SPIKEBOLL)
         paintingbossID = i;
    /*if (tweedleID == 0 && jjObjects[i].eventID == OBJECT::BEE){
         tweedleID = i;
         @tweedleObj = jjObjects[i];
	 }*/
    if (jjObjects[i].isActive && jjObjects[i].creatorType == CREATOR::PLAYER) {
      //Maintain boomerang gun
      if (jjObjects[i].eventID == OBJECT::BLASTERBULLET) {
        BoomerangGun(i);
        if (jjGameTicks%20 == 0) jjSample(jjObjects[i].xPos, jjObjects[i].yPos, SOUND::TUFBOSS_CATCH);
        jjObjects[i].animSpeed = 3;
        boomerangfired[jjObjects[i].creator - 32768] = true;
        continue;
      }
      if (jjObjects[i].eventID == OBJECT::TNT && jjObjects[i].state != STATE::EXPLODE) {
        jjDeleteObject(i);
        CreateBomb(i);
        continue;
      }
      if (jjObjects[i].eventID == OBJECT::APPLE && jjObjects[i].special == 11) {
        jjObjects[i].age++;
        if (jjObjects[i].age > cBombLifeTime)
          DestroyBomb(i);
        continue;
      }
    }
   }
  for (int i = 0; i < 32; i++)
    if (!boomerangfired[i]) {
      speed[i] = cMaxSpeed;
      returning[i] = false;
      if (i == p.playerID)
        p.noFire = false;
    } else boomerangfired[i] = false;


if (paintingbossFight) { //.causesRicochet = true;
//Painting Boss
  if (jjObjects[paintingbossID].state == STATE::FREEZE && jjGameTicks%6==0){
	if (jjObjects[paintingbossID].justHit>0)
		jjObjects[paintingbossID].unfreeze(jjRandom()%2);
	paintfrozen = true;
	}
	else paintfrozen = false;
  if (jjObjects[paintingbossID].justHit>0 && jjGameTicks%4==0){
		int paintrav = jjAddObject(OBJECT::RAVEN, jjObjects[paintingbossID].xPos+jjRandom()%64-32, jjObjects[paintingbossID].yPos-jjRandom()%64);
		jjObjects[paintrav].lightType = LIGHT::FLICKER;
		jjObjects[paintrav].light = 60;
  }
  if (jjObjects[paintingbossID].state==STATE::KILL || jjObjects[paintingbossID].energy<0){
		jjObjects[paintingbossID].fireBullet(OBJECT::EXPLOSION);
		jjAddObject(OBJECT::FULLENERGY, jjObjects[paintingbossID].xPos, jjObjects[paintingbossID].yPos);
		paintingbossFight = false;
		paintingDefeated = true;
		p.bossActivated = false;
		p.cameraUnfreeze();
		jjTriggers[0] = false;
		jjMusicLoad("fear2.mod");
		for (int i = 0;  i < jjObjectCount; i++)
			if (jjObjects[i].eventID == OBJECT::RAVEN && jjObjects[i].xPos > 172*32 && jjObjects[i].xPos < 192*32 && jjObjects[i].yPos > 87*32 && jjObjects[i].yPos < 108*32)
				jjObjects[i].state=STATE::KILL;
		}
  }
  
if (bubbaFight){
	if (jjGameTicks%75==0)
		jjObjects[bubbaID].fireBullet(OBJECT::SMOKERING);
	if (jjObjects[bubbaID].energy<6){
		jjDeleteObject(bubbaID);
	  jjAddObject(OBJECT::FULLENERGY, jjObjects[bubbaID].xPos, jjObjects[bubbaID].yPos);
	  for (int j=0; j<4; j++)
		for (int i=0; i<4; i++)
			jjAddObject(OBJECT::TNTAMMO3, (199*32)+(32*i), (32*32)+(32*j));
	  jjAddObject(OBJECT::EXPLOSION, jjObjects[bubbaID].xPos, jjObjects[bubbaID].yPos);
	  bubbaFight = false;
	  bubbaDefeated = true;
	  p.bossActivated = false;
	  p.cameraUnfreeze();
	  jjTriggers[28] = false;
	  jjTriggers[17] = true;
	  for (int i=0; i <3 ;i++)
		jjTileSet(3,209,38+i,(jjTileGet(4,8,11+i)));
	}
}

if (tweedleFight) {
	tweedleGhosts = 0;
	for (int i = 0;  i < jjObjectCount; i++)
		if (jjObjects[i].eventID == OBJECT::PACMANGHOST){
			//jjObjects[i].determineCurAnim(ANIM::TWEEDLE, 1);
			tweedleGhosts++;/*
			if (jjObjects[i].state==STATE::KILL){
				jjDeleteObject(i);
				for (int j = 0;  j < jjObjectCount; j++)
					if (jjObjects[j].eventID == OBJECT::PACMANGHOST)
						jjDeleteObject(j);
						//jjObjects[j].state=STATE::KILL;
				break;
				}*/
			}
	if (tweedleGhosts<tweedleMaxClones && jjGameTicks % tweedleCooldown == 0){
		int tweedleClone = 
			jjAddObject(OBJECT::PACMANGHOST, jjObjects[tweedleID].xPos, jjObjects[tweedleID].yPos);
		jjObjects[tweedleClone].determineCurAnim(ANIM::TWEEDLE, 1);
		jjObjects[tweedleClone].energy = 1;
		jjSample(jjObjects[tweedleID].xPos, jjObjects[tweedleID].yPos, SOUND::DEVILDEVAN_JUMPUP);
		for (int i = 0; i<48;i++){
			jjPARTICLE@ particle = jjAddParticle(PARTICLE::SPARK);
			if (particle !is null) {
				particle.xPos = jjObjects[tweedleID].xPos;
				particle.yPos = jjObjects[tweedleID].yPos;
				particle.xSpeed = (jjRandom()%4);
				particle.ySpeed = (jjRandom()%4);
				}
			}
	}
	if (jjObjects[tweedleID].state==STATE::KILL){
		tweedleFight = false;
		tweedleDefeated = true;
		jjAddObject(OBJECT::FULLENERGY, jjObjects[tweedleID].xPos, jjObjects[tweedleID].yPos);
		p.bossActivated = false;
		p.cameraUnfreeze();
		jjTriggers[23] = false;
		jjMusicLoad("life_of_stagelife.mod");
		for (int i = 0;  i < jjObjectCount; i++)
			if (jjObjects[i].eventID == OBJECT::PACMANGHOST)
				jjObjects[i].state=STATE::KILL;
		}

  }

}
void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ screen) {
	
if (paintingbossFight){
	if (!paintfrozen){
	screen.drawRotatedSpriteFromCurFrame(
		jjObjects[paintingbossID].xPos, 
		jjObjects[paintingbossID].yPos, 
		paintingFrameID, 
		jjGameTicks << 1, 2, 1, 
		SPRITE::TINTED, 
		uint(abs(jjSin(jjGameTicks)) * 256)
		);
	screen.drawSpriteFromCurFrame(
		jjObjects[paintingbossID].xPos, 
		jjObjects[paintingbossID].yPos, 
		paintingFrameID, 
		0,
		SPRITE::NORMAL
		);
	screen.drawRotatedSpriteFromCurFrame(
		jjObjects[paintingbossID].xPos, 
		jjObjects[paintingbossID].yPos, 
		paintingFrameID, 
		jjGameTicks << 2, 2, 1, 
		SPRITE::BLEND_OVERLAY, 
		uint(abs(jjSin(jjGameTicks)) * 128)
		);
	}
	else screen.drawSpriteFromCurFrame(
		jjObjects[paintingbossID].xPos, 
		jjObjects[paintingbossID].yPos, 
		paintingFrameID, 
		0,
		SPRITE::FROZEN
		);
}
	
if (jjTriggers[24]) jjDrawString(p.cameraX + 238,  p.cameraY + (jjResolutionHeight * 0.75), "GAME OVER", STRING::MEDIUM, STRING::NORMAL, 1, 1);
if (jjResolutionHeight != 480 || jjResolutionWidth != 640) {
	jjDrawString(p.cameraX + 8,  p.cameraY + 16, "PLEASE SET", STRING::MEDIUM, STRING::NORMAL, 1, 1);
	jjDrawString(p.cameraX + 8,  p.cameraY + 16 + 24, "RESOLUTION", STRING::MEDIUM, STRING::NORMAL, 1, 1);
	jjDrawString(p.cameraX + 8,  p.cameraY + 16 + 48, "TO 640x480!", STRING::MEDIUM, STRING::NORMAL, 1, 1);
}
}