Downloads containing HH18_level06.j2as

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

File preview

#pragma require "HH18E1.j2a"
#pragma require "SExmas.j2a"
#pragma require "hh17enemies.asc"
#include "HH18Smoke.asc"
#include "hh17enemies.asc"
#include "HH18savegems.asc"

/*** Copypasted and adapted by Slaz, scripted visuals by Violet CLM, xmas sprites by Sir Ementaler and Smoke  ***/
/*** Feel free to use/edit this script like I did :P ***/

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;
	}
}

const uint16 LollipopTileID = 390;
array<uint16> tilesToTurnIntoSprites = {
	585,625,
	604,605,606,607,608,
	LollipopTileID
};
class Sprite {
	Sprite(){}
	float x, y;
	uint age;
	uint color;
	Sprite(float xx, float yy, uint a, uint c = 0) {
		x = xx; y = yy; age = a; color = c;
	}
}
uint firstSingleTileFrameID, firstMultiTileFrameID, firstCandyCaneFrameID;
const uint levelWidth = jjLayerWidth[4];
const uint levelHeight = jjLayerHeight[4];

array<Sprite> Lollipops, Spazzes, Jacks, CandyCanes;
array<array<Sprite>> Lights(2);

void onLevelLoad() {
	gem::restorePlayerGems();
	jjUseLayer8Speeds = true;
	jjTexturedBGTexture = TEXTURE::XARGON;
	
	SMOKE::PENGUINATOR(OBJECT::LIZARD, 1+jjDifficulty);
	SMOKE::SANTAGHOST(OBJECT::FATCHICK, 2+jjDifficulty);
	SMOKE::SNOWMAN(OBJECT::STANDMONKEY, 0, 5, 6, 20, 100, 256, 1+jjDifficulty);
	SMOKE::FROZENALIEN(OBJECT::LABRAT, 2+jjDifficulty);
	SMOKE::FROZENSHADE(OBJECT::HELMUT, 1+jjDifficulty);
	
	HH17::setEnemy(OBJECT::DOGGYDOGG);
	HH17::setEnemy(OBJECT::TUFTURT);
	HH17::setEnemy(OBJECT::BAT);
	HH17::setEnemy(OBJECT::FLOATSUCKER);
	
	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");
	jjAnimSets[ANIM::SPIKEPLAT].load(4, "SExmas.j2a");
	jjObjectPresets[OBJECT::BOMBCRATE].behavior = GiftBox();
	jjObjectPresets[OBJECT::BOMBCRATE].determineCurAnim(ANIM::CUSTOM[0], 0);
	jjObjectPresets[OBJECT::SPIKEPLATFORM].killAnim = jjObjectPresets[OBJECT::SPIKEPLATFORM].determineCurAnim(ANIM::SPIKEPLAT, 0) + 1;
	
	array<jjLAYER@> layerOrder = {jjLayers[1], jjLayers[2], jjLayers[3], jjLayers[4], jjLayers[5], jjLayers[6]};
	
	for (uint i = 0; i < 5*2; ++i) {
		jjLAYER rocksInChocolate(4, 1);
		rocksInChocolate.tileWidth = true;
		rocksInChocolate.ySpeed = 0.24 - i * 0.003;
		rocksInChocolate.xSpeed = 0.7 - i * 0.04;
		rocksInChocolate.xOffset = jjRandom();
		rocksInChocolate.yOffset = -666 + int(i*20);
		rocksInChocolate.generateSettableTileArea();
		for (uint x = 0; x < 4; ++x)
			rocksInChocolate.tileSet(x, 0, 680 + 8 - (i & ~1) + (x & 1));
		layerOrder.insertLast(@rocksInChocolate);
		
	}
	
	{
		jjLAYER bigTrees(4, 8), smallTrees(4, 5);
		bigTrees.tileWidth = smallTrees.tileWidth = true;
		bigTrees.limitVisibleRegion = smallTrees.limitVisibleRegion = true;
		bigTrees.yOffset = -180; smallTrees.yOffset = -300;
		bigTrees.generateSettableTileArea();
		smallTrees.generateSettableTileArea();
		for (uint x = 0; x < 4; ++x) {
			for (int y = 0; y < bigTrees.height; ++y) {
				if (y < 3) { if (!(y == 0 && x > 1))
					bigTrees.tileSet(x, y, 578 + (x & 1) + (y - x/2) * 10);
				} else
					bigTrees.tileSet(x, y, 598 + (x & 1));
			}
			for (int y = 0; y < smallTrees.height; ++y) {
				if (y < 2)
					smallTrees.tileSet(x, y, 576 + (x & 1) + (y * 10));
				else
					smallTrees.tileSet(x, y, 586);
			}
		}
		for (uint i = 0; i < 8; ++i) {
			jjLAYER trees(i < 5 ? bigTrees : smallTrees);
			trees.ySpeed = 0.13 - i * 0.02;
			trees.xSpeed = 0.3 - i * 0.024;
			trees.xOffset = jjRandom();
			trees.yOffset += (i < 5) ? int(i*60) : (210 + int(i*30));
			layerOrder.insertLast(@trees);
		}
	}
	
	layerOrder.insertLast(jjLayers[7]);
	jjLAYER secondBackgroundMountains(jjLayers[7]);
	secondBackgroundMountains.yOffset = 64;
	secondBackgroundMountains.ySpeed *= 0.85;;
	secondBackgroundMountains.xSpeed *= 0.7;
	layerOrder.insertLast(@secondBackgroundMountains);
	
	layerOrder.insertLast(jjLayers[8]);
	jjLayerOrderSet(layerOrder);
	
	firstSingleTileFrameID = jjAnimations[jjAnimSets[ANIM::CUSTOM[0]].allocate(array<uint> = {tilesToTurnIntoSprites.length, 2, 4})];
	firstMultiTileFrameID = firstSingleTileFrameID + tilesToTurnIntoSprites.length;
	firstCandyCaneFrameID = firstMultiTileFrameID + 2;
	jjANIMFRAME@ frame;
	for (uint i = 0; i < tilesToTurnIntoSprites.length; ++i) {
		@frame = jjAnimFrames[firstSingleTileFrameID + i];
		jjPIXELMAP(tilesToTurnIntoSprites[i]).save(frame);
		frame.hotSpotX = frame.hotSpotY = -16;
	}
	
	jjObjectPresets[OBJECT::CHOCBAR].curFrame = jjAnimations[jjObjectPresets[OBJECT::CHOCBAR].curAnim].firstFrame = firstSingleTileFrameID;
	jjObjectPresets[OBJECT::ICECREAM].curFrame = jjAnimations[jjObjectPresets[OBJECT::ICECREAM].curAnim].firstFrame = firstSingleTileFrameID + 1;
	
	@frame = jjAnimFrames[firstMultiTileFrameID];
	jjPIXELMAP(32, 0, 128,128).save(frame);
	frame.hotSpotX = frame.hotSpotY = 0;
	@frame = jjAnimFrames[firstMultiTileFrameID + 1];
	jjPIXELMAP(160, 0, 64,96).save(frame);
	frame.hotSpotX = 0; frame.hotSpotY = -64;
	
	for (uint i = 0; i < 4; ++i) {
		@frame = jjAnimFrames[firstCandyCaneFrameID + i];
		jjPIXELMAP(7*32, i * 20, 12, 96 - i*20).save(frame);
		frame.hotSpotX = -6; frame.hotSpotY = 0;
	}
	
	for (uint x = 0; x < levelWidth; ++x) {
		for (uint y = 0; y < levelHeight; ++y) {
			const uint16 tileID1 = jjTileGet(4, x, y), tileID2 = jjTileGet(5, x, y);
			if (tileID1 == LollipopTileID || tileID2 == LollipopTileID)
				Lollipops.insertLast(Sprite(x * 32 + 16, y * 32 + 16, jjRandom()));
			else if (tileID1 == 301)
				Spazzes.insertLast(Sprite((x - 1) * 32, y * 32, 0));
			else if (tileID1 >= 340 && tileID1 <= 343)
				jjTileSet(4, x,y, 56);
			else if (tileID1 >= 395 && tileID1 <= 398)
				jjTileSet(4, x,y, 5);
			else if (tileID1 == 334 || tileID1 == 335) {
				jjTileSet(4, x,y, tileID1 - 30);
				if (tileID1 == 334)
					Jacks.insertLast(Sprite(x * 32, y * 32, jjRandom()));
			}
			if (jjEventGet(x, y) == 255)
				CandyCanes.insertLast(Sprite(x * 32 + 16, y * 32 + 16, jjRandom(), 3 - jjParameterGet(x, y, 0, 2)));
				
		}
	}
	
	const uint16 firstTreeTileID = 592;
	array<jjPIXELMAP@> foregroundTreeTileImages(679 - firstTreeTileID + 1, null);
	for (uint i = 0; i < 2; ++i) {
		const jjLAYER@ layer = jjLayers[1 + i];
		for (int x = layer.width - 1; x >= 0; --x)
			for (int y = layer.height - 1; y >= 0; --y) {
				const uint16 tileID = layer.tileGet(x, y);
				if (tileID >= firstTreeTileID) {
					const uint16 adjustedTileID = tileID - firstTreeTileID;
					if (foregroundTreeTileImages[adjustedTileID] is null)
						@foregroundTreeTileImages[adjustedTileID] = jjPIXELMAP(tileID);
					const jjPIXELMAP@ tileImage = foregroundTreeTileImages[adjustedTileID];
					uint8 xx, yy;
					while (tileImage[xx = jjRandom() & 31, yy = jjRandom() & 31] == 0);
					Lights[i].insertLast(Sprite(x * 32 + xx, y * 32 + yy, jjRandom(), jjRandom() % 5));
				}
			}
	}
}

void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ screen) {
	for (uint i = 0; i < Lollipops.length; ++i) {
		const Sprite@ sprite = Lollipops[i];
		screen.drawRotatedSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstSingleTileFrameID + 7, sprite.age - (jjGameTicks << 4));
	}
	for (uint i = 0; i < Spazzes.length; ++i) {
		const Sprite@ sprite = Spazzes[i];
		screen.drawSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstMultiTileFrameID, 1, SPRITE::SHADOW);
	}
	for (uint i = 0; i < CandyCanes.length; ++i) {
		const Sprite@ sprite = CandyCanes[i];
		screen.drawSwingingVineSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstCandyCaneFrameID + sprite.color, 96 - sprite.color*20, int(jjSin(sprite.age + jjGameTicks * 6) * 0x4000));
	}
}
void onDrawLayer5(jjPLAYER@, jjCANVAS@ screen) {
	for (uint i = 0; i < Jacks.length; ++i) {
		const Sprite@ sprite = Jacks[i];
		screen.drawRotatedSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstMultiTileFrameID + 1, int(jjSin(jjGameTicks << 2) * 28));
	}
}
void drawLights(uint id, jjCANVAS@ screen) {
	const array<Sprite>@ lights = @Lights[id];
	for (uint i = 0; i < lights.length; ++i) {
		const Sprite@ sprite = lights[i];
		screen.drawSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstSingleTileFrameID + 2 + sprite.color, 1, SPRITE::BRIGHTNESS, 128 + int(jjSin(sprite.age + (jjGameTicks << 3)) * 40));
	}
}
void onDrawLayer1(jjPLAYER@, jjCANVAS@ screen) { drawLights(0, screen); }
void onDrawLayer2(jjPLAYER@, jjCANVAS@ screen) { drawLights(1, screen); }

void onPlayer(jjPLAYER@ play) {
	jjPARTICLE@ part = jjAddParticle(PARTICLE::ICETRAIL);
	if (part !is null) {
		part.icetrail.colorDelta = -1;
		part.xPos = play.cameraX + (jjRandom() % jjSubscreenWidth);
		part.yPos = play.cameraY;
	}
	gem::trackPlayerGems(play);
	gem::upgradeHealth(play);
}

bool onDrawLives(jjPLAYER@ play, jjCANVAS@ canvas)  { return true; }

void onLevelReload() {
	HH17::processEnemyColors();
	gem::restorePlayerGems();
}

void onMain() {
	gem::deleteCollectedGems();
}

void onFunction0(jjPLAYER@ play) {
	gem::saveGemData();
	jjNxt(false, false);
}