Downloads containing HH24_level05.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Holiday Hare 24Featured Download PurpleJazz Single player 10 Download file

File preview

const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, null, null, null, null, null, null, NapsWeapons::AntiGravityBouncer()}); ///@MLLE-Generated
#include "MLLE-Include-1.7w.asc" ///@MLLE-Generated
#pragma require "HH24_level05-MLLE-Data-2.j2l" ///@MLLE-Generated
#pragma require "HH24_level05-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "CandionVPeaks.j2t" ///@MLLE-Generated
#pragma require "rainbowrunner.j2t" ///@MLLE-Generated
#pragma require "Rainbowrunner.j2t" ///@MLLE-Generated
#pragma require "HH24_level05.j2l" ///@MLLE-Generated
#include "AntiGravBouncers.asc" ///@MLLE-Generated
#pragma require "AntiGravBouncers.asc" ///@MLLE-Generated
#pragma require "snd_mouse.wav"
#pragma require "SEweapon.asc"
#pragma require "SExmas.j2a"
#pragma require "crayonbridge.j2a"
#pragma require "xmasTufTurt.j2a"
#pragma require "HH24.j2a"
#include "SEweapon.asc"
#include "HH17Enemies_HH24.asc"
#include "HH18Smoke_HH24.asc"
#pragma require "TornadoGun.j2a"
#include "HH24.asc"
#include "Resize v11.asc"

// Ice, Bouncers, Seekers, Toasters, Pepper Spray

const float PI = 3.1415927f;

class Imitation : jjBEHAVIORINTERFACE {
	private uint8 eventID;
	private jjBEHAVIOR behavior;
	Imitation(uint8 realEventID, uint8 fakeEventID) {
		jjOBJ@ obj = jjObjectPresets[realEventID];
		eventID = obj.eventID;
		behavior = obj.behavior;
		obj.eventID = fakeEventID;
		obj.behavior = this;
	}
	void onBehave(jjOBJ@ obj) override {
		if (obj.state == STATE::DEACTIVATE)
			obj.eventID = eventID;
		obj.behave(behavior);
	}
}

class GiftBox : jjBEHAVIORINTERFACE {
	void destroy(jjOBJ@ obj) {
		jjSample(obj.xPos, obj.yPos, SOUND::COMMON_WOOD1);
		{
			int id = jjAddObject(OBJECT::EXPLOSION, obj.xPos, obj.yPos);
			if (id != 0) {
				jjOBJ@ other = jjObjects[id];
				other.determineCurAnim(ANIM::PICKUPS, 4);
			}
		}
		for (int i = jjRandom() & 7 | 8; i-- != 0;) {
			int id = jjAddObject(OBJECT::SHARD, obj.xPos, obj.yPos);
			if (id != 0) {
				jjOBJ@ other = jjObjects[id];
				other.determineCurAnim(ANIM::PICKUPS, 93 + (jjRandom() & 1));
			}
		}
		obj.yPos -= 8.f;
		for (int i = obj.var[1]; i-- != 0;) {
			int id = jjAddObject(obj.var[0], obj.xPos, obj.yPos);
			if (id != 0) {
				jjOBJ@ other = jjObjects[id];
				if (other.playerHandling == HANDLING::PICKUP) {
					int angle = (jjRandom() & 255) + 128;
					other.xSpeed = jjCos(angle) * 5.f;
					other.ySpeed = jjSin(angle) * -3.f;
				} else if (other.playerHandling == HANDLING::SPECIAL) {
					other.deactivates = false;
				}
			}
		}
		obj.clearPlatform();
		obj.delete();
	}
	void onBehave(jjOBJ@ obj) override {
		switch (obj.state) {
			case STATE::START:
				{
					uint16 x = int(obj.xOrg) >>> 5;
					uint16 y = int(obj.yOrg) >>> 5;
					obj.var[0] = jjParameterGet(x, y, 0, 8);
					obj.var[1] = jjParameterGet(x, y, 8, 4);
					obj.curAnim += jjParameterGet(x, y, 12, 2);
					obj.determineCurFrame();
					obj.bulletHandling = HANDLING::DESTROYBULLET;
					obj.scriptedCollisions = true;
				}
				break;
			case STATE::FALL:
				obj.var[2] = 1;
				break;
			case STATE::FREEZE:
			case STATE::SLEEP:
				if (obj.var[2] != 0) {
					destroy(obj);
					return;
				}
		}
		obj.behave(BEHAVIOR::MONITOR);
	}
	bool onObjectHit(jjOBJ@, jjOBJ@, jjPLAYER@, int) {
		return true;
	}
	bool onIsSolid(jjOBJ@) {
		return true;
	}
}

void onLevelLoad() {
	jjSampleLoad(SOUND::PINBALL_BELL, "snd_mouse.wav");
	
	HH17::setEnemy(OBJECT::BAT);
	HH17::setEnemy(OBJECT::DEMON);
	//HH17::setEnemy(OBJECT::FLOATSUCKER);
	//HH17::setEnemy(OBJECT::SUCKER);
	SMOKE::FROZENSHADE(OBJECT::SPARK, 3);
	
	Imitation(OBJECT::TACO, OBJECT::MILK);
	
	uint src = jjAnimSets[ANIM::CUSTOM[255]].load(0, "SExmas.j2a");
	uint dest = jjAnimSets[ANIM::PICKUPS];
	for (int i = 0; i < 95; i++) {
		const jjANIMATION@ anim = jjAnimations[src + i];
		if (anim.frameCount != 0)
			jjAnimations[dest + i] = anim;
	}
	
	jjAnimSets[ANIM::BRIDGE].load(1, "SExmas.j2a");
	jjAnimSets[ANIM::CUSTOM[0]].load(2, "SExmas.j2a");
	jjObjectPresets[OBJECT::ONEUPCRATE].behavior = GiftBox();
	jjObjectPresets[OBJECT::ONEUPCRATE].determineCurAnim(ANIM::CUSTOM[0], 0);
	jjAnimSets[ANIM::SPIKEBOLL].load(3, "SExmas.j2a");
	jjAnimSets[ANIM::SPIKEBOLL3D].load(3, "SExmas.j2a");
	jjAnimSets[ANIM::SPIKEPLAT].load(4, "SExmas.j2a");
	
	src = jjAnimSets[ANIM::CUSTOM[254]].load(0, "HH24.j2a");

	jjAnimations[dest + 18] = jjAnimations[src + 6]; // Chips -> Chocolate Chip Cookie
	jjAnimations[dest + 23] = jjAnimations[src + 8]; // Cucumber -> White Chocolate
	jjAnimations[dest + 48] = jjAnimations[src + 11]; // Lemon -> Swiss Roll
	jjAnimations[dest + 49] = jjAnimations[src + 13]; // Lettuce -> Lollipop
	jjAnimations[dest + 76] = jjAnimations[src + 12]; // Pie -> Apple Pie
	
	// Christmas Tuf Turt
	
	jjAnimSets[ANIM::TUFTUR].load(1, "HH24.j2a");
	jjObjectPresets[OBJECT::TUFTURT].determineCurAnim(ANIM::TUFTUR, 0);
	
	jjObjectPresets[OBJECT::BUBBA].behavior = WindBubba();
	jjObjectPresets[OBJECT::BUBBA].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::BUBBA].bulletHandling = HANDLING::DETECTBULLET;
	jjObjectPresets[OBJECT::BUBBA].scriptedCollisions = true;
	jjObjectPresets[OBJECT::BUBBA].isBlastable = false;
	jjObjectPresets[OBJECT::BUBBA].energy = 100;
	jjObjectPresets[OBJECT::BUBBA].points = 10000;
	
	HH17::setEnemy(OBJECT::BUBBA);
	
	jjAnimSets[ANIM::CUSTOM[69]].load(0, "TornadoGun.j2a");
	
	HH24::levelLoad();
	
	//jjObjectPresets[OBJECT::GUN9AMMO3].lightType = LIGHT::BRIGHT;
	//jjObjectPresets[OBJECT::GUN9AMMO3].light = 12;
	
	jjObjectPresets[OBJECT::BAT].behavior = BlueBat();
}

enum BubbaStates {Intro, Hover, Shoot, Dive, Whirlwind, Dead};
uint currState = Intro;

class WindBubba : jjBEHAVIORINTERFACE {
	int currAnim, sample, armor, armorCounter;
	float bossHP = 120 + (40*jjDifficulty);
	bool lowHP;
	
	int highHPAttackSpeed = 140;
	int lowHPAttackSpeed = 105;
	
	int highHPAttackSpeed_Hard = 85;
	int lowHPAttackSpeed_Hard = 55;
	
	void onBehave(jjOBJ@ obj) {
		obj.determineCurAnim(ANIM::BUBBA, currAnim);
		obj.determineCurFrame();
		
		if (jjGameTicks % 4 == 0) {
			obj.frameID++;
		}
		
		obj.counter++;
		
		if (obj.freeze > 0) {
			obj.unfreeze(1);
		}
		
		if (obj.justHit != 0) armorCounter = 0;
		else armorCounter++;
	  
		if (armorCounter > 0) {
			if (armorCounter < 35) {
				if (armorCounter % 7 == 0) {
					armor--;
				}
			}
		}
		if (armorCounter >= 70) {
			if (armorCounter % 4 == 0) {
				armor--;
			}
		}
	  
	  if (armor > 20) armor = 20;
	  if (armor < 0) armor = 0;
	  
	  obj.energy = int(bossHP / (1.2+(0.4*jjDifficulty)));
		
		if (currState < Dead) {
			obj.xPos += jjSin(jjGameTicks*10)*1.25;
			obj.yPos += jjCos(jjGameTicks*10)*0.75;
			
			for (int i = 0; i <= jjLocalPlayerCount; i++) {
				jjLocalPlayers[i].boss = obj.objectID;
			}
		}
		
		obj.xPos = obj.xPos + obj.xSpeed;
		obj.yPos = obj.yPos + obj.ySpeed;
		
		lowHP = obj.energy <= 50;
		
		int playerID = obj.findNearestPlayer(1000000);
		jjPLAYER@ play = jjPlayers[playerID];
		
		if (play.xPos > int(obj.xPos+32)) obj.direction = 1;
		else if (play.xPos < int(obj.xPos-32)) obj.direction = -1;
		
		int flightAngle = int(atan2(obj.xPos - int(play.xPos + (128*obj.direction)), obj.yPos - int(play.yPos - 60)) * (512 / PI));
		int attackAngle = int(atan2(obj.xPos - play.xPos - (play.xSpeed * 4), obj.yPos - play.yPos - (play.ySpeed * 16)) * (512 / PI));
		
		if (obj.energy <= 0 && currState < Dead) {
			currState = Dead;
			obj.counter = 0;
			obj.frameID = 0;
		}
		
		switch (currState) {
			case Intro:
				currAnim = 3;
				if (obj.counter == 1) {
					bossHP = 120 + (40*jjDifficulty);
					jjMusicLoad("snowf.it");
					jjLocalPlayers[0].showText("@@@@@@@Who dares invade my lair?@@Prepare to be blown away, foolish rabbit!");
					for (int i = 0; i <= jjLocalPlayerCount; i++) {
						jjLocalPlayers[i].activateBoss(true);
					}
				}
				if (obj.counter == 140) {
					currState = Hover;
					obj.counter = 0;
				}
			break;
			case Hover:
				currAnim = 3;
				moveIntoXPosition(obj, play, 4, flightAngle);
				moveIntoYPosition(obj, play, 3, flightAngle);
				
				if (jjDifficulty < 2) {
					if (obj.counter % (lowHP? lowHPAttackSpeed:highHPAttackSpeed) == 0 && obj.counter > 0) {
						randomAttack(obj, jjRandom()%6);
						obj.frameID = 0;
						obj.counter = 0;
					}
				} else {
					if (obj.counter % (lowHP? lowHPAttackSpeed_Hard:highHPAttackSpeed_Hard) == 0 && obj.counter > 0) {
						randomAttack(obj, jjRandom()%6);
						obj.frameID = 0;
						obj.counter = 0;
					}				
				}
			break;
			
			case Shoot:
				moveIntoXPosition(obj, play, 3, flightAngle);
				moveIntoYPosition(obj, play, 2, flightAngle);
				
				currAnim = 0;
				
				if (obj.counter % 55 == 0) {
					jjSample(play.xPos, play.yPos, SOUND::BUBBA_SNEEZE2);
					jjSample(play.xPos, play.yPos, SOUND::INTRO_BLOW, 48, 25000);
					jjSample(play.xPos, play.yPos, SOUND::COMMON_BIRDFLY, 48, 25000);
					
					int bulletID = jjAddObject(OBJECT::BLASTERBULLET, obj.xPos + (20 * obj.direction), obj.yPos, obj.objectID, CREATOR::OBJECT);
					jjOBJ @ o = jjObjects[bulletID];
					o.behavior = Tornado;
					o.determineCurAnim(ANIM::CUSTOM[69], 0);
					o.direction = o.xSpeed < 0? 1:-1;
					o.xSpeed = -4 * jjSin(attackAngle);
					o.ySpeed = -7 * jjCos(attackAngle);
					o.xAcc = 0;
					o.yAcc = -0.1;
					o.counterEnd = 180;
					o.killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;

				}
				
				if (obj.counter == 180) {
					currState = Hover;
					obj.frameID = 0;
					obj.counter = 0;
				}
			break;
			
			case Dive:
				
				if (obj.counter < 55) {
					currAnim = 5;
					if (obj.counter == 1) {
						jjSample(play.xPos, play.yPos, SOUND::COMMON_REVUP);
					}
					obj.xSpeed = 2.5 * jjSin(attackAngle);
					obj.ySpeed = 2.5 * jjCos(attackAngle);
				}
				
				if (obj.counter == 62) {
					currAnim = 2;
					jjSample(play.xPos, play.yPos, SOUND::INTRO_SHOTGRN);
					obj.xSpeed = -6 * jjSin(attackAngle);
					obj.ySpeed = -6 * jjCos(attackAngle);
				}
				
				if (obj.counter > 42 && obj.counter < 84) {
					obj.xSpeed += -0.2 * jjSin(attackAngle);
					obj.ySpeed += -0.2 * jjCos(attackAngle);
				}
				
				if (obj.counter == 111) {
					currState = Hover;
					obj.frameID = 0;
					obj.counter = 0;
				}
			break;
			
			case Whirlwind:
				if (obj.counter < 14) {
					currAnim = 7;
				}
				
				if (obj.counter >= 14 && obj.counter < 140) {
					currAnim = 6;
					sample = jjSampleLooped(play.xPos, play.yPos, SOUND::BUBBA_TORNADOATTACK2, sample, 0, 5000);
					
					obj.xSpeed = 4 * obj.direction;
					obj.ySpeed = 6 * jjCos(jjGameTicks*12);
				}
				
				if (obj.counter >= 140) {
					currAnim = 8;
				}
				
				if (obj.counter % 21 == 0) {
					jjSample(play.xPos, play.yPos, SOUND::INTRO_BLOW, 48, 25000);
					jjSample(play.xPos, play.yPos, SOUND::COMMON_BIRDFLY, 48, 25000);
					
					int bulletID = jjAddObject(OBJECT::BLASTERBULLET, obj.xPos + (20 * obj.direction), obj.yPos, obj.objectID, CREATOR::OBJECT);
					jjOBJ @ o = jjObjects[bulletID];
					o.behavior = Tornado;
					o.creatorType = CREATOR::OBJECT;
					o.determineCurAnim(ANIM::CUSTOM[69], 0);
					o.direction = o.xSpeed < 0? 1:-1;
					o.xSpeed = -6 * jjSin(attackAngle);
					o.ySpeed = -6 * jjCos(attackAngle);
					o.xAcc = 0;
					o.yAcc = -0.1;
					o.counterEnd = 180;
					o.killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
					o.playerHandling == HANDLING::SPECIAL;
				}
				
				if (obj.counter == 175) {
					currState = Hover;
					obj.frameID = 0;
					obj.counter = 0;
					obj.xSpeed = obj.ySpeed = 0;
				}
			break;
			case Dead:
				for (int i = 0; i <= jjLocalPlayerCount; i++) {
					jjLocalPlayers[i].bossActivated = false;
				}
				obj.xSpeed = 0;
				obj.ySpeed = -2;
				currAnim = 1;
				if (obj.counter == 1) {
					jjLocalPlayers[0].showText("@@@@@@@Welp, I'm off to the pearly gates...");
				}
				
				if (obj.counter == 175) {
					HH24::endLevel();
				}
			break;
		}
	}
	
	void randomAttack(jjOBJ@ obj, int rand) {
		switch (rand) {
			case 0: currState = Shoot; break;
			case 1: currState = Shoot; break;
			case 2: currState = lowHP? Whirlwind:Shoot; break;
			case 3: currState = Dive; break;
			case 4: currState = Dive; break;
			case 5: currState = Whirlwind; break;
		}
	}
	
	void moveIntoXPosition(jjOBJ@ obj, jjPLAYER@ play, float speed, int angle) {
		if (obj.xPos < int(play.xPos - 140) || obj.xPos > int(play.xPos + 140)) {
			obj.xSpeed = -speed * jjSin(angle);
		} else {
			obj.xSpeed = 0;
		}
	}
	void moveIntoYPosition(jjOBJ@ obj, jjPLAYER@ play, float speed, int angle) {
		if (obj.yPos < int(play.yPos - 88) || obj.yPos > int(play.yPos)) {
			obj.ySpeed = -speed * jjCos(angle);
		} else {
			obj.ySpeed = 0;
		}
	}
	
	void onDraw(jjOBJ@ obj) {
		if (currState < Dead) jjDrawSprite(obj.xPos, obj.yPos + 22, ANIM::AMMO, 2, 4, obj.direction, SPRITE::SINGLEHUE, 32);
		jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, obj.justHit > 0? SPRITE::SINGLECOLOR : SPRITE::NORMAL, jjLocalPlayers[0].blink == 0? 15:32);
	}
	
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
		if (bull !is null) {
			if (bull.playerHandling == HANDLING::PLAYERBULLET && currState < Dead && bull.creatorType == CREATOR::PLAYER) {
				obj.justHit = 5;
				float multiplier = ((bull.var[3] == 4 || bull.var[3] == 5 || bull.var[3] == 6)? 0.4f : 0.6f) * (play.blink == 0? 1:0.25);
				bossHP -= (damageCalc(obj, bull, armor, play) > (bull.animSpeed * multiplier))? damageCalc(obj, bull, armor, play) : (bull.animSpeed * multiplier);
				armor += bull.animSpeed;
			}
			if ((bull.var[6] & 16) == 0 && bull.creatorType == CREATOR::PLAYER) {
				bull.state = STATE::EXPLODE;
			}
		} else if (play !is null) {
			if (currState < Dead) play.hurt(1, false);
		}
		return true;
	}
}

float damageCalc(jjOBJ@ obj, jjOBJ@ bullet, int armor, jjPLAYER@ play) {
	if (armor <= bullet.animSpeed) {
		return bullet.animSpeed * (play.blink == 0? 1:0.25);
	} else {
		return (bullet.animSpeed - ((0.0125f * (bullet.animSpeed*3)) * armor)) * (play.blink == 0? 1:0.25);
	}
}

void Tornado(jjOBJ@ obj) {
	obj.behave(BEHAVIOR::BULLET, obj.state != STATE::EXPLODE? false:true);
	if (obj.state == STATE::FLY) {
		jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
		
		int playerID = obj.findNearestPlayer(20000);
		jjPLAYER@ play = jjPlayers[playerID];
			
		float pdx = play.xPos - obj.xPos, pdy = play.yPos - obj.yPos;
		if ((pdx * pdx + pdy * pdy < 48 * 48)) {
			play.ySpeed -= 1.5;
			play.xSpeed -= 3.5 * obj.direction;
			play.keyJump = false;
		}
	}
	if (obj.state == STATE::EXPLODE) {
		if (obj.var[0] == 0) {
			jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SWISH4, 36, 15000);
			obj.var[0] = 1;
		}
	}
}

void onLevelReload() {
	MLLE::SpawnOffgridsLocal();
	MLLE::ReapplyPalette();
	HH17::processEnemyColors();
	currState = Intro;
	jjMusicLoad("tan-lowh.it");
	HH24::levelReload();
}


void onMain() {
	HH24::main();
	for (int i = 0; i < 1024; i++) {
		jjPARTICLE@ particle = jjParticles[i];
		if (particle.type == PARTICLE::SNOW) {
			if (jjTileGet(1, int(particle.xPos/32), int(particle.yPos/32)) != 0) {
				particle.xSpeed = -4;
			}
		}
	}
}

void onFunction0(jjPLAYER@ player) {
	jjSample(player.xPos, player.yPos, SOUND::PINBALL_BELL);
	jjSample(player.xPos, player.yPos, SOUND::PINBALL_BELL);
	jjSample(player.xPos, player.yPos, SOUND::PINBALL_BELL);
	player.showText(0, 0);
}
bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
	return MLLE::WeaponHook.drawAmmo(player, canvas);
}

void onLevelBegin() {
	MLLE::SpawnOffgrids();
	
	for (int i = 0; i < 2; i++) {
		Resize::Resize(
			jjAnimations[jjAnimSets[ANIM::CUSTOM[23]] + i],
			1.25,
			Resize::Method::Scale2x
		);
	}
}
void onPlayer(jjPLAYER@ player) {
	HH24::player(player);
}

bool onDrawScore(jjPLAYER@ player, jjCANVAS@ canvas) {
	HH24::score(player, canvas, true);
	return false;
}