Downloads containing hh17enemies.asc

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Holiday Hare '17Featured Download ShadowGPW Single player 8.8 Download file
TSF with JJ2+ Only: Holiday Hare '18Featured Download SmokeNC Single player 8.9 Download file

File preview

#pragma require "HH17Enemies.asc"
#pragma require "HH17_Crow.wav"
#pragma require "HH17_Balloon.wav"

namespace HH17 {
	void setEnemy(OBJECT::Object eventID) {
		switch (eventID) {
			case OBJECT::BAT:
				jjObjectPresets[OBJECT::BAT].behavior = BlueBat();
				jjAnimSets[ANIM::BAT].load();
			break;
			case OBJECT::BILSY:
				jjAnimSets[ANIM::BILSBOSS].load();
			break;
			case OBJECT::CRAB:
				jjObjectPresets[OBJECT::CRAB].behavior = YetiCrab();
				jjAnimSets[ANIM::UTERUS].load();
			break;
			case OBJECT::DEMON:
				jjObjectPresets[OBJECT::DEMON].behavior = IceDemon();
				jjAnimSets[ANIM::DEMON].load();
			break;
			case OBJECT::DOGGYDOGG:
				jjObjectPresets[OBJECT::DOGGYDOGG].behavior = BlueDog();
			break;
			case OBJECT::DRAGON:
				jjObjectPresets[OBJECT::DRAGON].behavior = IceDragon();
			break;
			case OBJECT::FENCER:
				jjObjectPresets[OBJECT::FENCER].behavior = WhiteFencer();
			break;
			case OBJECT::LABRAT:
				jjObjectPresets[OBJECT::LABRAT].behavior = CaveRat();
			break;
			case OBJECT::MONKEY:
				jjObjectPresets[OBJECT::MONKEY].behavior = SnowMonkey();
			break;
			case OBJECT::STANDMONKEY:
				jjObjectPresets[OBJECT::MONKEY].behavior = SnowMonkey();
			break;
			case OBJECT::QUEEN:
				jjAnimSets[ANIM::QUEEN].load();
			break;
			case OBJECT::RAVEN:
				jjObjectPresets[OBJECT::RAVEN].behavior = WhiteRaven();
				jjAnimSets[ANIM::RAVEN].load();
				jjSampleLoad(SOUND::P2_TONG, "HH17_crow.wav");
			break;
			case OBJECT::SKELETON:
				jjObjectPresets[OBJECT::SKELETON].behavior = BoneChucker();
			break;
			case OBJECT::FLOATSUCKER:
				jjObjectPresets[OBJECT::FLOATSUCKER].behavior = WhiteSucker();
				jjSampleLoad(SOUND::P2_FART, "HH17_balloon.wav");
			break;
			case OBJECT::SUCKER:
				jjObjectPresets[OBJECT::FLOATSUCKER].behavior = WhiteSucker();
			break;
			case OBJECT::TUFTURT:
				jjObjectPresets[OBJECT::TUFTURT].behavior = YetiTurtle();
			break;
			default: break;
				
		}
		setEnemyPalettes(eventID);
	}
	void replaceAllEnemies() {
		HH17::setEnemy(OBJECT::BAT);
		HH17::setEnemy(OBJECT::BILSY);
		HH17::setEnemy(OBJECT::BUBBA);
		HH17::setEnemy(OBJECT::CRAB);
		HH17::setEnemy(OBJECT::DEMON);
		HH17::setEnemy(OBJECT::DOGGYDOGG);
		HH17::setEnemy(OBJECT::DRAGON);
		HH17::setEnemy(OBJECT::FENCER);
		HH17::setEnemy(OBJECT::FLOATSUCKER);
		HH17::setEnemy(OBJECT::LABRAT);
		HH17::setEnemy(OBJECT::MONKEY);
		HH17::setEnemy(OBJECT::STANDMONKEY);
		HH17::setEnemy(OBJECT::QUEEN);
		HH17::setEnemy(OBJECT::RAVEN);
		HH17::setEnemy(OBJECT::ROTATINGROCK);
		HH17::setEnemy(OBJECT::SKELETON);
		HH17::setEnemy(OBJECT::SUCKER);
		HH17::setEnemy(OBJECT::TUFBOSS);
		HH17::setEnemy(OBJECT::TUFTURT);
	}
	void handleEnemyProjectiles() {
		for (int i = 0; i < jjObjectCount; i++) {
			jjOBJ@ obj = jjObjects[i];
			if (obj.behavior == BEHAVIOR::TOASTERBULLET && obj.creatorType != CREATOR::PLAYER && jjGameTicks % 1 == 0) {
				IceBullet temp;
				jjOBJ@ icebullet = jjObjects[jjAddObject(OBJECT::ICEBULLETPU, int(obj.xPos), int(obj.yPos), obj.objectID, CREATOR::OBJECT, jjVOIDFUNCOBJ(temp.onBehave))];
				jjSample(icebullet.xPos, icebullet.yPos, SOUND::AMMO_ICEPU3);
				icebullet.xPos = obj.xOrg + (8 * obj.direction);
				icebullet.counterEnd = 30;
				icebullet.state = STATE::FLY;
				icebullet.playerHandling = HANDLING::ENEMYBULLET;
				obj.delete();
			}
			
			if (obj.behavior == BEHAVIOR::MONKEYBULLET) {
				Snowball temp;
				jjOBJ@ snowball = jjObjects[jjAddObject(OBJECT::BOUNCERBULLET, int(obj.xPos), int(obj.yPos), obj.objectID, CREATOR::OBJECT, jjVOIDFUNCOBJ(temp.onBehave))];
				snowball.playerHandling = HANDLING::ENEMYBULLET;
				jjSample(snowball.xOrg, snowball.yOrg, SOUND::COMMON_FOEW2, 0, 0);
				snowball.xAcc = snowball.yAcc = 0;
				snowball.xSpeed = 8 * obj.direction;
				snowball.yPos = snowball.yOrg;
				int playerID = snowball.findNearestPlayer(80000);
				if (jjPlayers[playerID].yPos > int(snowball.yPos)) snowball.ySpeed = (jjPlayers[playerID].yPos > int(snowball.yPos) + 64)? 2:0;
				else if (jjPlayers[playerID].yPos < int(snowball.yPos)) snowball.ySpeed = (jjPlayers[playerID].yPos < int(snowball.yPos) - 64)? -4:-2;
				snowball.direction = obj.direction;
				snowball.counterEnd = 140;
				snowball.animSpeed = 1;
				snowball.light = 8;
				snowball.state = STATE::FLY;
				snowball.killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
				obj.delete();
			}
		}
	}
	void processEnemyColors() {
		jjPalette.fill(255, 255, 255, 2, 1, 1);
		jjPalette.fill(217, 241, 255, 3, 1, 1);
		jjPalette.fill(161, 208, 255, 4, 1, 1);
		jjPalette.fill(109, 179, 255, 5, 1, 1);
		jjPalette.fill(52, 146, 255, 6, 1, 1);
		jjPalette.fill(0, 118, 255, 7, 1, 1);
		jjPalette.fill(0, 94, 231, 8, 1, 1);
		jjPalette.fill(0, 71, 189, 9, 1, 1);
		jjPalette.fill(0, 47, 146, 10, 1, 1);
		jjPalette.fill(0, 28, 104, 11, 1, 1);
		jjPalette.fill(0, 10, 61, 12, 1, 1);
		jjPalette.fill(0, 0, 24, 13, 1, 1);
		jjPalette.apply();
	}
}

void setEnemyPalettes(OBJECT::Object eventID) {
	jjANIMATION@ animRock = jjAnimations[jjAnimSets[ANIM::ROCK] + 0];
	jjANIMATION@ animTurt = jjAnimations[jjAnimSets[ANIM::TUFTUR] + 0];
	
	if (jjGameMode == GAME::COOP || jjGameMode == GAME::SP) {
		HH17::processEnemyColors();
		switch (eventID) {
			case OBJECT::BAT:
				for (uint i = 0; i < 4; i++) {
					jjANIMATION@ animBat = jjAnimations[jjAnimSets[ANIM::BAT] + i];
					for (uint j = 0; j < animBat.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animBat + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 88 && sprite[x,y] <= 94) sprite[x,y] -= 57;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::BILSY:
				for (uint i = 0; i < 8; i++) {
					jjANIMATION@ animBilsy = jjAnimations[jjAnimSets[ANIM::BILSBOSS] + i];
					for (uint j = 0; j < animBilsy.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animBilsy + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
								if (sprite[x,y] >= 59 && sprite[x,y] <= 63) sprite[x,y] += 14;
								if (sprite[x,y] >= 64 && sprite[x,y] <= 71) sprite[x,y] += 8;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::BUBBA:
				for (uint i = 0; i < 9; i++) {
					jjANIMATION@ animBubba = jjAnimations[jjAnimSets[ANIM::BUBBA] + i];
					for (uint j = 0; j < animBubba.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animBubba + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 16;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::CRAB:
				for (uint i = 0; i < 8; i++) {
					jjANIMATION@ animCrab = jjAnimations[jjAnimSets[ANIM::UTERUS] + i];
					for (uint j = 0; j < animCrab.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animCrab + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 16 && sprite[x,y] <= 23) sprite[x,y] += 16;
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] += 48;
								if (sprite[x,y] == 48 || sprite[x,y] == 49) sprite[x,y] = 72;
								if (sprite[x,y] >= 50 && sprite[x,y] <= 55) sprite[x,y] += 23;
								if (sprite[x,y] >= 80 && sprite[x,y] <= 87) sprite[x,y] -= 75;
								if (sprite[x,y] >= 88 && sprite[x,y] <= 95) sprite[x,y] -= 56;
							}
						}
							sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::DEMON:
				for (uint i = 0; i < 4; i++) {
					jjANIMATION@ animDemon = jjAnimations[jjAnimSets[ANIM::DEMON] + i];
					for (uint j = 0; j < animDemon.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animDemon + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
								if (sprite[x,y] >= 40 && sprite[x,y] <= 47) sprite[x,y] += 32;
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 16;
								if (sprite[x,y] >= 64 && sprite[x,y] <= 71) sprite[x,y] += 8;
								if (sprite[x,y] >= 80 && sprite[x,y] <= 87) sprite[x,y] -= 75;
							}
						}
							sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::DOGGYDOGG:
				for (uint i = 0; i < 2; i++) {
					jjANIMATION@ animDog = jjAnimations[jjAnimSets[ANIM::DOG] + i];
					for (uint j = 0; j < animDog.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animDog + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 16 && sprite[x,y] <= 23) sprite[x,y] += 8;
								if (sprite[x,y] >= 40 && sprite[x,y] <= 43) sprite[x,y] -= 36;
								if (sprite[x,y] >= 44 && sprite[x,y] <= 46) sprite[x,y] -= 35;
								if (sprite[x,y] == 47) sprite[x,y] = 13;
		 
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::DRAGON:
				for (uint i = 0; i < 3; i++) {
					jjANIMATION@ animDragon = jjAnimations[jjAnimSets[ANIM::DRAGON] + i];
					for (uint j = 0; j < animDragon.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animDragon + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 59 && sprite[x,y] <= 63) sprite[x,y] -= 26;
								if (sprite[x,y] >= 80 && sprite[x,y] <= 87) sprite[x,y] -= 8;
							}
						}
						sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::FENCER:
				for (uint i = 0; i < 2; i++) {
					jjANIMATION@ animFencer = jjAnimations[jjAnimSets[ANIM::FENCER] + i];
					for (uint j = 0; j < animFencer.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animFencer + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 21;
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 16;
								if (sprite[x,y] == 80) sprite[x,y] = 72;
								if (sprite[x,y] >= 81 && sprite[x,y] <= 87) sprite[x,y] -= 9;
							}
						}
						sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::LABRAT:
				for (uint i = 0; i < 3; i++) {
					jjANIMATION@ animRat = jjAnimations[jjAnimSets[ANIM::LABRAT] + i];
					for (uint j = 0; j < animRat.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animRat + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 43;
							}
						}
						sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::MONKEY:
				for (uint i = 0; i < 7; i++) {
					jjANIMATION@ animMonkey = jjAnimations[jjAnimSets[ANIM::MONKEY] + i];
					for (uint j = 0; j < animMonkey.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animMonkey + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 41 && sprite[x,y] <= 47) sprite[x,y] -= 8;
								if (sprite[x,y] == 40 || (sprite[x,y] >= 56 && sprite[x,y] <= 63)) sprite[x,y] = 0;
								if (i > 1) {
									if (sprite[x,y] >= 65 && sprite[x,y] <= 70) sprite[x,y] += 4;
								} else {
									if (sprite[x,y] >= 64 && sprite[x,y] <= 71) sprite[x,y] += 8;
								}
							}
						}
						sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::RAVEN:
				for (uint i = 0; i < 3; i++) {
					jjANIMATION@ animRaven = jjAnimations[jjAnimSets[ANIM::RAVEN] + i];
					for (uint j = 0; j < animRaven.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animRaven + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] == 40) sprite[x,y] = 64;
								if (sprite[x,y] >= 59 && sprite[x,y] <= 62) sprite[x,y] += 8;
								if (sprite[x,y] == 71 || sprite[x,y] == 76) sprite[x,y] = 35;
								if (sprite[x,y] == 77) sprite[x,y] = 34;
								if (sprite[x,y] == 78) sprite[x,y] = 33;
								if (sprite[x,y] == 79) sprite[x,y] = 15;
							}
						}
						sprite.save(frame);
					}
				}
			break;

			case OBJECT::QUEEN:
				for (uint i = 0; i < 8; i++) {
					jjANIMATION@ animQ = jjAnimations[jjAnimSets[ANIM::QUEEN] + i];
					for (uint j = 0; j < animQ.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animQ + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::ROTATINGROCK:
				for (uint j = 0; j < animRock.frameCount; j++) {
					jjANIMFRAME@ frame = jjAnimFrames[animRock + j];
					jjPIXELMAP sprite(frame);
					for (uint x = 0; x < sprite.width; ++x) {
						for (uint y = 0; y < sprite.height; ++y) {
							if (sprite[x,y] >= 64 && sprite[x,y] <= 71) sprite[x,y] = 17 - (sprite[x,y]&7)*2;
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::SKELETON:
				for (uint i = 0; i < 3; i++) {
					jjANIMATION@ animBones = jjAnimations[jjAnimSets[ANIM::SKELETON] + i];
					for (uint j = 0; j < animBones.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animBones + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] == 72) sprite[x,y] = 2;
								if (sprite[x,y] >= 73 && sprite[x,y] <= 79) sprite[x,y] -= 69;
							}
						}
						sprite.save(frame);
					}
				}
			break;
		
			case OBJECT::SUCKER:
				for (uint i = 0; i < 7; i++) {
					jjANIMATION@ animSucker = jjAnimations[jjAnimSets[ANIM::SUCKER] + i];
					for (uint j = 0; j < animSucker.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animSucker + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 16;
								if (sprite[x,y] == 83) sprite[x,y] = 36;
							}
						}
						sprite.save(frame);
					}
				}
			break;

			case OBJECT::FLOATSUCKER:
				for (uint i = 0; i < 7; i++) {
					jjANIMATION@ animSucker = jjAnimations[jjAnimSets[ANIM::SUCKER] + i];
					for (uint j = 0; j < animSucker.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animSucker + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] -= 22;
								if (sprite[x,y] >= 48 && sprite[x,y] <= 55) sprite[x,y] -= 16;
								if (sprite[x,y] == 83) sprite[x,y] = 36;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			case OBJECT::TUFTURT:
				for (uint j = 0; j < animTurt.frameCount; j++) {
					jjANIMFRAME@ frame = jjAnimFrames[animTurt + j];
					jjPIXELMAP sprite(frame);
					for (uint x = 0; x < sprite.width; ++x) {
						for (uint y = 0; y < sprite.height; ++y) {
							if (sprite[x,y] == 40) sprite[x,y] = 64;
							if (sprite[x,y] >= 56 && sprite[x,y] <= 63) sprite[x,y] += 8;
							if (sprite[x,y] == 83 || sprite[x,y] == 84) sprite[x,y] = 72;
							if (sprite[x,y] >= 85 && sprite[x,y] <= 86) sprite[x,y] -= 11;
							if (sprite[x,y] >= 88 && sprite[x,y] <= 94) sprite[x,y] -= 58;
						}
					}
					sprite.save(frame);
				}
			break;
		
			case OBJECT::TUFBOSS:
				for (int i = 0; i < 6; i++) {
					jjANIMATION@ animTufBoss = jjAnimations[jjAnimSets[ANIM::TUFBOSS] + i];
					for (uint j = 0; j < animTufBoss.frameCount; j++) {
						jjANIMFRAME@ frame = jjAnimFrames[animTufBoss + j];
						jjPIXELMAP sprite(frame);
						for (uint x = 0; x < sprite.width; ++x) {
							for (uint y = 0; y < sprite.height; ++y) {
								if (sprite[x,y] == 40) sprite[x,y] = 64;
								if (sprite[x,y] >= 56 && sprite[x,y] <= 63) sprite[x,y] += 8;
								if (sprite[x,y] == 82 || sprite[x,y] == 83) sprite[x,y] = 72;
								if (sprite[x,y] >= 84 && sprite[x,y] <= 86) sprite[x,y] -= 11;
								if (sprite[x,y] >= 73 && sprite[x,y] <= 79) sprite[x,y] -= 40;
							}
						}
						sprite.save(frame);
					}
				}
			break;
			
			default: break;
		}
	}
}

bool facingPlayer(jjOBJ@ obj, int playerID) {
	if (((obj.xPos < (jjPlayers[playerID].xPos - 32) && obj.direction == 1) || (obj.xPos > (jjPlayers[playerID].xPos + 32) && obj.direction == -1)) && obj.yPos <= int(jjPlayers[playerID].yPos + 208) && obj.yPos >= int(jjPlayers[playerID].yPos - 208)) return true;
	return false;
}

bool moving(jjOBJ@ obj) {
	if (obj.xSpeed >= 1 || obj.xSpeed <= -1) return true;
	return false;
}

class BlueBat : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BAT);
		obj.determineCurFrame();
		
		int playerID = obj.findNearestPlayer(20000);
		
		if (playerID > -1 && obj.freeze == 0) {
			if (obj.ySpeed != 0) {
				if (jjPlayers[playerID].xPos > int(obj.xPos + 20) && obj.xPos < (obj.xOrg + 96)) {
					obj.xPos += jjDifficulty > 1? 2:1;
					obj.direction = 1;
				}
				else if (jjPlayers[playerID].xPos < int(obj.xPos - 20) && obj.xPos > (obj.xOrg - 96)) {
					obj.xPos -= jjDifficulty > 1? 2:1;
					obj.direction = -1;
				}
				if (jjPlayers[playerID].yPos > obj.yPos && obj.yPos < (obj.yOrg + 96)) obj.yPos += 1;
			}
		}
	}
}

class YetiCrab : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::CRAB);
		
		if (obj.xSpeed > 0 && obj.direction == 1) obj.xPos += 1;
		else if (obj.xSpeed < 0 && obj.direction == -1) obj.xPos -= 1;
	}
}

class IceDemon : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::DEMON);
		obj.determineCurFrame();
		
		int playerID = obj.findNearestPlayer(120000);
		int fireRate = jjDifficulty >= 3? 6:(15 * (3 / (jjDifficulty + 1)));
		
		if (playerID > -1 && obj.freeze == 0) {
			if (facingPlayer(obj, playerID) && jjGameTicks % fireRate == 0 && moving(obj)) {
				IceBullet temp;
				jjOBJ@ icebullet = jjObjects[jjAddObject(OBJECT::ICEBULLETPU, int(obj.xPos + (8 * obj.direction)), int(obj.yPos + 4), obj.objectID, CREATOR::OBJECT, jjVOIDFUNCOBJ(temp.onBehave))];
				icebullet.playerHandling = HANDLING::ENEMYBULLET;
				icebullet.animSpeed = 1;
				icebullet.direction = obj.direction;
				icebullet.xSpeed = 6 * icebullet.direction;
				
				if (jjPlayers[playerID].yPos > int(obj.yPos + 32)) icebullet.ySpeed = 2;
				else if (jjPlayers[playerID].yPos < int(obj.yPos - 32)) icebullet.ySpeed = -2;
				else icebullet.ySpeed = 0;
				
				icebullet.state = STATE::FLY;
				icebullet.lightType = LIGHT::POINT;
				icebullet.counterEnd = 90;
				if (icebullet.counter == 1) jjSample(icebullet.xPos, icebullet.yPos, SOUND::AMMO_ICEPU2, 48, 0);
			}
		}
		if (obj.state == STATE::KILL) {
			obj.particlePixelExplosion(1);
			jjSample(obj.xPos, obj.yPos, SOUND::BILSBOSS_FIRESTART, 0, 0);
		}
	}
}

class BlueDog : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::DOGGYDOGG);
		
		int playerID = obj.findNearestPlayer(50000);
		if (playerID > -1 && obj.freeze == 0) {
			if (facingPlayer(obj, playerID) && moving(obj)) {
				obj.xPos += (2 * obj.direction);
				obj.state = STATE::ACTION;
			}
			else if (obj.xPos > int(jjPlayers[playerID].xPos + 64) || obj.xPos < int(jjPlayers[playerID].xPos - 64)) obj.direction *= -1;
		}
	}
}

class IceDragon : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::DRAGON, obj.var[1] == 0? true:false);
		if (obj.var[1] == 1) jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos + 2, obj.curFrame, obj.direction, SPRITE::NORMAL, 3, 3, 3);
		obj.freeze = 0;
		for (int i = 1; i < jjObjectCount; i++) {
			if (jjObjects[i].behavior == BEHAVIOR::PLATFORM) {
				float dx = jjObjects[i].xOrg - obj.xOrg, dy = jjObjects[i].yOrg - obj.yOrg;
				if (dx * dx + dy * dy < 128 * 128) {
					obj.xPos = jjObjects[i].xPos;
					obj.yPos = jjObjects[i].yPos - 10;
					obj.var[1] = 1;
				}
			}
		}
	}
}

class WhiteFencer : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::FENCER);
		int playerID = obj.findNearestPlayer(150000);
		if (playerID > -1 && obj.freeze == 0) {
			if (obj.xSpeed > 0) {
				if ((jjPlayers[playerID].xPos - obj.xPos) >= 96 && (jjPlayers[playerID].xPos - obj.xPos) <= 128) obj.xPos += 2;
				else if ((jjPlayers[playerID].xPos - obj.xPos) >= 128) obj.xPos += 3;
			}
			else if (obj.xSpeed < 0) {
				if ((obj.xPos - jjPlayers[playerID].xPos) >= 96 && (obj.xPos - jjPlayers[playerID].xPos) <= 128) obj.xPos -= 2;
				else if ((obj.xPos - jjPlayers[playerID].xPos) >= 128) obj.xPos -= 3;
			}
			
			if (obj.ySpeed < 0) {
				obj.yPos -= 1;
			}
			
			if (obj.freeze == 0) {
				if (obj.xPos > int(jjPlayers[playerID].xPos + 32)) obj.direction = -1;
				else if (obj.xPos < int(jjPlayers[playerID].xPos - 32)) obj.direction = 1;
			}
		}
	}
}

class CaveRat : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::LABRAT);
		if (obj.ySpeed != 0 && !jjMaskedPixel(int(obj.xPos + (64*obj.direction)), int(obj.yPos), 4)) {
			obj.xPos += 2 * obj.direction;
		}
		if (jjMaskedPixel(int(obj.xPos + (8*obj.direction)), int(obj.yPos), 4)) {
			obj.xPos += 2 * obj.direction;
		}
	}
}

class SnowMonkey : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::MONKEY);
		
		int playerID = obj.findNearestPlayer(30000);
		if (playerID > -1 && obj.freeze == 0 && !moving(obj)) {
			if (obj.xPos > int(jjPlayers[playerID].xPos + 32)) obj.direction = -1;
			else if (obj.xPos < int(jjPlayers[playerID].xPos - 32)) obj.direction = 1;
		}
	}
}

class WhiteRaven : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::RAVEN);
		
		int playerID = obj.findNearestPlayer(50000);
		if (playerID > -1 && obj.freeze == 0) {
			if (obj.ySpeed > 0.1 && (obj.xSpeed > 0.5 || obj.xSpeed < -0.5)) {
				obj.ySpeed = 4;
			}
			if (jjPlayers[playerID].xPos > int(obj.xPos)) obj.xPos += 2;
			else if (jjPlayers[playerID].xPos < int(obj.xPos)) obj.xPos -= 2;
		}
		
		if (obj.state != STATE::KILL && obj.isActive && jjGameTicks % 85 == 0 && obj.freeze == 0)
			jjSample(obj.xPos, obj.yPos, SOUND::P2_TONG, 32, 35000 + jjRandom()%12000);
	}
}

class BoneChucker : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::SKELETON);
		
		int playerID = obj.findNearestPlayer(150000);
		int fireRate = jjDifficulty >= 3? 12:(35 * (3 / (jjDifficulty + 1)));
		
		if (playerID > -1 && obj.freeze == 0) {
			if (facingPlayer(obj, playerID) && jjGameTicks % fireRate == 0) {
				jjOBJ@ bone = jjObjects[jjAddObject(OBJECT::SHARD, int(obj.xPos - (8 * obj.direction)), int(obj.yPos + 2), obj.objectID, CREATOR::OBJECT)];
				bone.behavior = BEHAVIOR::BOUNCERBULLET;
				bone.determineCurAnim(ANIM::SKELETON, 0);
				bone.playerHandling = HANDLING::ENEMYBULLET;
				bone.animSpeed = 1;
				bone.direction = obj.direction;
				bone.xSpeed = 6 * bone.direction;
				bone.ySpeed = -3;
				bone.state = STATE::FLY;
				bone.lightType = LIGHT::POINT;
				bone.counterEnd = 105;
				if (bone.counter == 0) randomBoneSample(bone);
				bone.killAnim = jjObjectPresets[OBJECT::BOUNCERBULLET].killAnim;
			}
		}
	}
}

void randomBoneSample(jjOBJ@ obj) {
	switch(jjRandom()%4) {
		case 0: jjSample(obj.xPos, obj.yPos, SOUND::SKELETON_BONE1, 0, 0); break;
		case 1: jjSample(obj.xPos, obj.yPos, SOUND::SKELETON_BONE2, 0, 0); break;
		case 2: jjSample(obj.xPos, obj.yPos, SOUND::SKELETON_BONE3, 0, 0); break;
		case 3: jjSample(obj.xPos, obj.yPos, SOUND::SKELETON_BONE5, 0, 0); break;
	}
}

class WhiteSucker : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::FLOATSUCKER, obj.state == STATE::KILL? true:false);
		if (obj.state != STATE::KILL) jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, (1 + (obj.age/20)) * obj.direction, (1 + (obj.age/20)), obj.freeze > 0? SPRITE::FROZEN : SPRITE::NORMAL); 
		int playerID = obj.findNearestPlayer(28000);
		if (playerID > -1 && obj.state == STATE::FLOAT) {
			if (obj.age < 100 && obj.freeze == 0) {
				obj.age += 5;
			}
		} else {
			if (obj.age > 0) obj.age -= 5;
		}
		
		if (obj.age == 5 && obj.var[1] == 1) {
			obj.var[0] = 1;
		}
		
		if (obj.age == 10) {
			obj.var[1] = 0;
		}
		
		if (obj.age == 0) {
			obj.var[0] = 0;
			obj.var[1] = 1;
		}
		
		float dx = jjPlayers[playerID].xPos - obj.xPos, dy = jjPlayers[playerID].yPos - obj.yPos;
		if (obj.freeze == 0 && dx * dx + dy * dy < obj.age * obj.age) {
			jjPlayers[playerID].hurt(1, false);
			if (jjPlayers[playerID].xPos > int(obj.xPos + 8)) jjPlayers[playerID].xSpeed = 4;
			else if (jjPlayers[playerID].xPos < int(obj.xPos - 8)) jjPlayers[playerID].xSpeed = -4;
			
			if (jjPlayers[playerID].xPos < int(obj.xPos + 8) && jjPlayers[playerID].xPos > int(obj.xPos - 8)) {
				jjPlayers[playerID].ySpeed = jjPlayers[playerID].yPos > obj.yPos? 3:-3;
				jjPlayers[playerID].xSpeed = 4 * obj.direction;
			} else jjPlayers[playerID].ySpeed = jjPlayers[playerID].yPos > obj.yPos? 1:-1;
		}
		
		if (obj.age == 5 && obj.var[1] == 1 && obj.freeze == 0) jjSample(obj.xPos, obj.yPos, SOUND::P2_FART, 48, 0);
		
		for (int i = 0; i < jjObjectCount; i++) {
			jjOBJ@ bull = jjObjects[i];
			if (bull.playerHandling == HANDLING::PLAYERBULLET && obj.state == STATE::FLOAT) {
				float bdx = bull.xPos - obj.xPos, bdy = bull.yPos - obj.yPos;
				if (bdx * bdx + bdy * bdy < 200 * 200) {
					if (obj.age < 100 && obj.freeze == 0) obj.age += 5;
				}
				if (bdx * bdx + bdy * bdy < obj.age * obj.age) {
					if (bull.var[3] == 3) {
						jjOBJ@ freeze = jjObjects[jjAddObject(OBJECT::ICEBULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER)];
						freeze.counterEnd = 1;
						freeze.state = STATE::FLY;
						freeze.xSpeed = 1;
						freeze.playerHandling = HANDLING::PLAYERBULLET;
						bull.delete();
					} else {
						bull.ricochet();
					}
				}
			}
		}
		
		if (obj.state == STATE::FREEZE) {
			obj.special--;
			if (obj.special == 0) {
				obj.unfreeze(1);
				obj.state = obj.oldState;
			}
		}
	}
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
		if (bull !is null) {
			if (bull.playerHandling == HANDLING::PLAYERBULLET) {
				obj.energy -= bull.animSpeed;
				obj.justHit = 5;
				if (bull.var[3] == 3) obj.special = 350;
			}
		}
		return true;
	}
}

class YetiTurtle : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::WALKINGENEMY);
		int playerID = obj.findNearestPlayer(130000);
		if (playerID > -1 && obj.freeze == 0) {
			
			if (obj.age > 0) obj.age--;
			jjPLAYER@ play;
			float dx = jjPlayers[playerID].xPos - obj.xPos, dy = jjLocalPlayers[playerID].yPos - obj.yPos;
			if (obj.freeze == 0 && facingPlayer(obj, playerID) && obj.age == 0 && dx * dx + dy * dy < 50 * 50) {
				obj.age = 35;
				jjPlayers[playerID].xSpeed = 16 * obj.direction;
				jjPlayers[playerID].ySpeed = -6;
				jjPlayers[playerID].hurt(1, false);
				jjSample(jjPlayers[playerID].xPos, jjPlayers[playerID].yPos, SOUND::FATCHK_HIT1, 42, 0);
			}
		
			for (int i = 0; i < jjObjectCount; i++) {
				if (jjObjects[i].eventID == OBJECT::ROTATINGROCK && obj.doesCollide(jjObjects[i], true) && facingPlayer(obj, playerID)) {
					if ((obj.xSpeed > 0 && jjPlayers[playerID].xPos > obj.xPos) || (obj.xSpeed < 0 && jjPlayers[playerID].xPos < obj.xPos)) {
						jjObjects[i].xSpeed = 8 * (obj.xSpeed > 0? 1:-1);
						jjObjects[i].ySpeed = -2;
						jjObjects[i].state = STATE::FLY;
					}
				}
			}
		}
	}
}

class IceBullet : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, true);
		obj.direction = obj.xSpeed < 1? -1:1;
		int playerID = obj.findNearestPlayer(30000);
		if (obj.state == STATE::FLY && obj.doesCollide(jjPlayers[playerID], true)) {
			jjPlayers[playerID].freeze(true);
			jjPlayers[playerID].xSpeed -= (obj.xSpeed / (obj.direction == -1? 8:-8)) * obj.direction;
		}
	}
}

class Snowball : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
		if (obj.state != STATE::EXPLODE) {
			obj.direction = obj.xSpeed > 0? 1:-1;
			obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
			jjDrawRotatedSprite(int((obj.xPos + (8*obj.direction)) - jjCos(obj.var[0])), int((obj.yPos - (16*obj.direction)) - jjSin(obj.var[0])), ANIM::FONT, 0, 14, obj.var[0], 1.5 * obj.direction, 1.5, SPRITE::SINGLEHUE, 2);
			obj.ySpeed += 0.15;
		}
	}
}