Downloads containing ab19btl09.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Anniversary Bash 19 Levels Jazz2Online Multiple N/A Download file

File preview

#pragma require "BubbleGun.j2a"
class Point {
	int x, y;
	Point() {}
	Point(int X, int Y) {
		x = X;
		y = Y;
	}
}
funcdef jjPALCOLOR ColorFunction(jjPALCOLOR);
void darkenLayer(jjLAYER@ layer, array<uint8>& freePaletteIndices, ColorFunction@ func) {
	array<int> tileIDs, uniqueTileIDs;
	for (int i = 0; i < layer.height; i++) {
		for (int j = 0; j < layer.width; j++) {
			int tileID = layer.tileGet(j, i);
			if (tileID != 0)
				tileIDs.insertLast(tileID);
		}
	}
	int prev = 0;
	tileIDs.sortAsc();
	for (uint i = 0; i < tileIDs.length(); i++) {
		if (tileIDs[i] != prev)
			uniqueTileIDs.insertLast(prev = tileIDs[i]);
	}
	uint firstNewTile = jjTileCount;
	jjTilesFromTileset(jjTilesetFileName, 1, uniqueTileIDs.length());
	array<uint8> mapping(256);
	for (uint i = 0; i < uniqueTileIDs.length(); i++) {
		jjPIXELMAP tile(uniqueTileIDs[i]);
		for (int j = 0; j < 32; j++) {
			for (int k = 0; k < 32; k++) {
				uint8 pixel = tile[k, j];
				if (pixel != 0) {
					if (mapping[pixel] == 0) {
						jjPALCOLOR color = func(jjPalette.color[pixel]);
						uint8 bestMatch = jjPalette.findNearestColor(color);
						if (!freePaletteIndices.isEmpty()) {
							jjPALCOLOR other = jjPalette.color[bestMatch];
							int red = other.red - color.red;
							int green = other.green - color.green;
							int blue = other.blue - color.blue;
							int distance = red * red + green * green + blue * blue;
							if (distance > 16) {
								bestMatch = freePaletteIndices[freePaletteIndices.length() - 1];
								jjPalette.color[bestMatch] = color;
								freePaletteIndices.removeLast();
							}
						}
						mapping[pixel] = bestMatch;
					}
					tile[k, j] = mapping[pixel];
				}
			}
		}
		tile.save(firstNewTile + i);
	}
	layer.generateSettableTileArea();
	for (int i = 0; i < layer.height; i++) {
		for (int j = 0; j < layer.widthReal; j++) {
			int tileID = layer.tileGet(j, i);
			if (tileID != 0)
				layer.tileSet(j, i, firstNewTile + uniqueTileIDs.find(tileID));
		}
	}
}
/*void turnTilesOrange(jjLAYER@ layer) {
	array<int> tileIDs, uniqueTileIDs;
	for (int i = 0; i < layer.height; i++) {
		for (int j = 0; j < layer.width; j++) {
			int tileID = layer.tileGet(j, i);
			if (tileID != 0)
				tileIDs.insertLast(tileID);
		}
	}
	int prev = 0;
	tileIDs.sortAsc();
	for (uint i = 0; i < tileIDs.length(); i++) {
		if (tileIDs[i] != prev)
			uniqueTileIDs.insertLast(prev = tileIDs[i]);
	}
	uint firstNewTile = jjTileCount;
	jjTilesFromTileset(jjTilesetFileName, 1, uniqueTileIDs.length());
	array<uint8> mapping(256);
	for (uint i = 0; i < uniqueTileIDs.length(); i++) {
		jjPIXELMAP tile(uniqueTileIDs[i]);
		for (int j = 0; j < 32; j++) {
			for (int k = 0; k < 32; k++) {
				uint8 pixel = tile[k, j];
				if (pixel != 0) {
					if (mapping[pixel] == 0) {
						jjPALCOLOR color = jjPalette.color[pixel];
						color.red = color.red * 2 / 3;
						color.green = color.green * 2 / 3;
						color.blue = color.blue * 2 / 3;
						mapping[pixel] = jjPalette.findNearestColor(color);
					}
					tile[k, j] = mapping[pixel];
				}
			}
		}
		tile.save(firstNewTile + i);
	}
	layer.generateSettableTileArea();
	for (int i = 0; i < layer.height; i++) {
		for (int j = 0; j < layer.widthReal; j++) {
			int tileID = layer.tileGet(j, i);
			if (tileID != 0)
				layer.tileSet(j, i, firstNewTile + uniqueTileIDs.find(tileID));
		}
	}
}*/
bool generateCustomSpringSprites(jjANIMSET@ anim, const array<uint> &in colors) {
	int length = colors.length();
	bool success = (@customSpringSprite = anim).allocate(array<uint>(length * 3, 5)) !is null;
	if (success) {
		uint srcSet = jjAnimSets[ANIM::SPRING];
		for (int i = 0; i < length; i++) {
			uint color = colors[i];
			uint destAnimOffset = anim + i * 3;
			for (int j = 0; j < 3; j++) {
				uint srcAnim = jjAnimations[srcSet + j];
				uint destAnim = jjAnimations[destAnimOffset + j];
				for (int k = 0; k < 5; k++) {
					jjPIXELMAP image(jjAnimFrames[destAnim + k] = jjAnimFrames[srcAnim + k]);
					int width = image.width;
					int height = image.height;
					for (int l = 0; l < height; l++) {
						for (int m = 0; m < width; m++) {
							int pixel = image[m, l];
							if (pixel >= 32 && pixel < 40)
								image[m, l] = color + (pixel & 7);
						}
					}
					if (!image.save(jjAnimFrames[destAnim + k]))
						return false;
				}
			}
		}
	}
	return success;
}
void initializeCustomSpring(jjOBJ@ obj) {
	int anim = obj.curAnim;
	obj.behave(obj.behavior = BEHAVIOR::SPRING, false);
	if (obj.curAnim != anim) {
		obj.curAnim = anim + 2;
		obj.determineCurFrame();
	}
	obj.draw();
}
void turnIntoCustomSpring(jjOBJ@ obj, uint color, float power, bool horizontal) {
	if (horizontal) {
		obj.xSpeed = power;
		obj.ySpeed = 0.f;
	} else {
		obj.xSpeed = 0.f;
		obj.ySpeed = -power;
		if (obj.state == STATE::START && obj.creatorType == CREATOR::LEVEL) {
			int x = int(obj.xPos) >> 5;
			int y = int(obj.yPos) >> 5;
			if (jjParameterGet(x, y, 0, 1) != 0) {
				jjParameterSet(x, y, 0, 1, 0);
				obj.yPos -= 4.f;
				obj.ySpeed = power;
			}
		}
	}
	obj.behavior = initializeCustomSpring;
	obj.curAnim = customSpringSprite + color * 3 + (horizontal ? 1 : 0);
	obj.energy = obj.frameID = obj.freeze = obj.justHit = obj.light = obj.points = 0;
	obj.causesRicochet = obj.isBlastable = obj.isTarget = obj.scriptedCollisions = obj.triggersTNT = false;
	obj.deactivates = obj.isFreezable = true;
	obj.bulletHandling = HANDLING::IGNOREBULLET;
	obj.playerHandling = HANDLING::SPECIAL;
	obj.lightType = LIGHT::NORMAL;
	obj.determineCurFrame();
}
void bubbleGun(jjOBJ@ bubble) {
    if (bubble.state == STATE::START) {
		bubble.state = STATE::FLY;
		if (jjLocalPlayers[0].isLocal) jjSample(bubble.xPos, bubble.yPos, SOUND::COMMON_PLOP2, 0, 0);
	}
	
	if (jjMaskedPixel(int(bubble.xPos) + int(bubble.xSpeed), int(bubble.yPos)) || jjMaskedPixel(int(bubble.xPos) - int(bubble.xSpeed), int(bubble.yPos)) || jjMaskedPixel(int(bubble.xPos), int(bubble.yPos) + int(bubble.ySpeed)) || jjMaskedPixel(int(bubble.xPos), int(bubble.yPos) - int(bubble.ySpeed))) {
		jjSample(bubble.xPos, bubble.yPos, SOUND::P2_SPLOUT, 0, 0);
	}
	
	bubble.behave(BEHAVIOR::WATERSHIELDBULLET);
	bubble.killAnim = jjObjectPresets[OBJECT::WATERSHIELDBULLET].killAnim;
}
void bubbleGunPU(jjOBJ@ bubble) {
	if (bubble.state == STATE::START) {
		bubble.state = STATE::FLY;
		if (jjLocalPlayers[0].isLocal) jjSample(bubble.xPos, bubble.yPos, SOUND::COMMON_PLOP2, 0, 0);
	}

	if (jjMaskedPixel(int(bubble.xPos) + int(bubble.xSpeed), int(bubble.yPos)) || jjMaskedPixel(int(bubble.xPos) - int(bubble.xSpeed), int(bubble.yPos)) || jjMaskedPixel(int(bubble.xPos), int(bubble.yPos) + int(bubble.ySpeed)) || jjMaskedPixel(int(bubble.xPos), int(bubble.yPos) - int(bubble.ySpeed))) {
		jjSample(bubble.xPos, bubble.yPos, SOUND::P2_SPLOUT, 0, 0);
	}
	
	bubble.behave(BEHAVIOR::WATERSHIELDBULLET);
	
	if (bubble.state == STATE::FLY && bubble.counter > 0) {
		switch (bubble.direction) {
			case 1: bubble.xSpeed = bubble.xSpeed - 0.1; bubble.ySpeed = bubble.ySpeed - 0.08; break;
			case -1: bubble.xSpeed = bubble.xSpeed + 0.1; bubble.ySpeed = bubble.ySpeed - 0.08; break;
		}
	}
	
	bubble.killAnim = jjObjectPresets[OBJECT::WATERSHIELDBULLET].killAnim;
	bubble.var[6] = 8;
}
jjANIMSET@ customSpringSprite;
jjLAYER@ layer7Backup;
int layer7Row = 0;
array<Point> oneWays;
array<bool> specialMove(jjLocalPlayerCount);
//array<uint16> tilesToTurnOrange = {102, 101, 114, 115, 116};
//array<uint16> tilesToReplace = {556, 563, 564, 565, 566};
void onLevelLoad() {
	jjDelayGeneratedCrateOrigins = true;
	jjMASKMAP poleMask(133);
	poleMask.save(146);
	poleMask.save(153);
	poleMask.save(156);
	for (int i = 0; i < 14; i++) {
		for (int j = 0; j < 32; j++) {
			poleMask[j, i] = false;
		}
	}
	poleMask.save(163);
	jjMASKMAP vineMask(87);
	for (int i = 0; i < 32; i++) {
		vineMask[i, 5] = true;
	}
	vineMask.save(63);
	vineMask.save(64);
	vineMask.save(87);
	vineMask.save(89);
	vineMask.save(533);
	vineMask.save(534);
	vineMask.save(535);
	jjPIXELMAP(163 | TILE::VFLIPPED).save(153);
	for (int i = 146; i <= 156; i += 10) {
		jjPIXELMAP poleTile(i);
		for (int j = 0; j < 32; j++) {
			poleTile[23, j] = poleTile[22, j];
		}
		poleTile.save(i);
	}
	jjPalette.color[176] = jjPALCOLOR(69, 88, 143);
	jjPIXELMAP fog0, fog50, fog100;
	for (int i = 0; i < 32; i++) {
		for (int j = 0; j < 32; j++) {
			fog0[j, i] = i << 2;
			fog50[j, i] = i + 32 << 2;
			fog100[j, i] = 176;
		}
	}
	fog0.save(660);
	jjTileType[660] = 0;
	fog50.save(661);
	jjTileType[661] = 0;
	fog100.save(679);
	jjTileType[679] = 0;
	jjLAYER fogLayer(jjLayers[6]);
	fogLayer.generateSettableTileArea();
	fogLayer.spriteMode = SPRITE::ALPHAMAP;
	fogLayer.spriteParam = 176;
	int top = -1, bottom = -1;
	for (int i = 0; i < fogLayer.height; i++) {
		for (int j = 0; j < fogLayer.widthReal; j++) {
			if (fogLayer.tileGet(j, i) != 0) {
				if (top < 0)
					top = i;
				bottom = i;
				fogLayer.tileSet(j, i, 0);
			}
		}
	}
	for (int i = 0; i < fogLayer.widthReal; i++) {
		fogLayer.tileSet(i, top - 2, 660);
		fogLayer.tileSet(i, top - 1, 661);
		fogLayer.tileSet(i, bottom + 1, 661 | TILE::VFLIPPED);
		fogLayer.tileSet(i, bottom + 2, 660 | TILE::VFLIPPED);
	}
	array<uint8> freePaletteIndices = {113, 118, 120, 160};
	for (int i = 177; i < 208; i++) {
		freePaletteIndices.insertLast(i);
	}
	if (jjLayers[8].hasTileMap)
		darkenLayer(jjLayers[8], freePaletteIndices, function(color) {
			color.setHSL(color.getHue(), color.getSat() / 2, color.getLight());
			return color;
		});
	if (jjLayers[1].hasTileMap)
		darkenLayer(jjLayers[1], freePaletteIndices, function(color) {
			color.setHSL(color.getHue(), color.getSat() * 4 / 5, color.getLight() * 2 / 5);
			return color;
		});
	jjLayerOrderSet(array<jjLAYER@> = {jjLayers[2], jjLayers[3], jjLayers[4], jjLayers[1], jjLayers[5], jjLayers[6], fogLayer, jjLayers[7], jjLayers[8]});
	for (int i = 0; i < jjLayers[4].height; i++) {
		for (int j = 0; j < jjLayers[4].width; j++) {
			if (jjEventGet(j, i) == AREA::ONEWAY)
				oneWays.insertLast(Point(j, i));
		}
	}
	int tileOffset = jjTileCount;
	jjTilesFromTileset(jjTilesetFileName, 1, 128);
	for (int i = 0; i < 128; i++) {
		jjPIXELMAP tile;
		for (int j = 0; j < 32; j++) {
			for (int k = 0; k < 32; k++) {
				tile[k, j] = 58;
			}
		}
		for (int j = jjRandom() & 3; j >= 0; j--) {
			tile[jjRandom() & 31, jjRandom() & 31] = (jjRandom() & 15 == 0 ? 48 + (jjRandom() & 127) : 144 + (jjRandom() & 15));
		}
		tile.save(tileOffset + i);
	}
	jjLayers[7].generateSettableTileArea();
	for (int i = 0; i < jjLayers[7].height; i++) {
		for (int j = 0; j < jjLayers[7].widthReal; j++) {
			if (jjLayers[7].tileGet(j, i) != 0)
				jjLayers[7].tileSet(j, i, tileOffset + (jjRandom() & 127));
		}
	}
	layer7Row = jjLayers[7].height / 2;
	@layer7Backup = jjLAYER(jjLayers[7]);
	layer7Backup.generateSettableTileArea();
	/*array<uint8> mapping(256);
	for (uint i = 0; i < tilesToTurnOrange.length(); i++) {
		jjPIXELMAP tile(tilesToTurnOrange[i]);
		for (int j = 0; j < 32; j++) {
			for (int k = 0; k < 32; k++) {
				uint8 pixel = tile[k, j];
				if (pixel != 0) {
					if (mapping[pixel] == 0) {
						jjPALCOLOR color = jjPalette.color[pixel];
						int hue = color.getHue();
						int sat = color.getSat();
						int light = color.getLight();
						if (i > 2 && k <= 16) color.setHSL(hue + 100, sat, light + 10);
						else if (i < 2) color.setHSL(hue + 100, sat, light + 10);
						mapping[pixel] = jjPalette.findNearestColor(color);
					}
					tile[k, j] = mapping[pixel];
				}
			}
		}
		tile.save(tilesToReplace[i]);
		jjMASKMAP(tilesToTurnOrange[i]).save(tilesToReplace[i], true);
	}*/
	generateCustomSpringSprites(jjAnimSets[ANIM::CUSTOM[3]], array<uint> = {40});
	turnIntoCustomSpring(jjObjectPresets[OBJECT::FROZENSPRING], 0, 21.f, false);
	jjAnimSets[ANIM::CUSTOM[0]].load(0, "BubbleGun.j2a");
	jjAnimSets[ANIM::CUSTOM[1]].load(1, "BubbleGun.j2a");
	jjAnimSets[ANIM::CUSTOM[2]].load(2, "BubbleGun.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 29] = jjAnimations[jjAnimSets[ANIM::AMMO] + 8];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 28] = jjAnimations[jjAnimSets[ANIM::CUSTOM[0]] + 0];
	jjAnimations[jjAnimSets[ANIM::PICKUPS] + 62] = jjAnimations[jjAnimSets[ANIM::CUSTOM[1]] + 0];
	jjAnimations[jjAnimSets[ANIM::PICKUPS] + 55] = jjAnimations[jjAnimSets[ANIM::CUSTOM[2]] + 0];
	jjObjectPresets[OBJECT::ICEBULLET].behavior = bubbleGun;
	jjObjectPresets[OBJECT::ICEBULLET].counterEnd = 105;
	jjObjectPresets[OBJECT::ICEBULLET].freeze = 0;
	jjObjectPresets[OBJECT::ICEBULLET].special = jjObjectPresets[OBJECT::ICEBULLET].determineCurAnim(ANIM::AMMO, 8);
	jjObjectPresets[OBJECT::ICEBULLET].xSpeed = 1.25;
	jjObjectPresets[OBJECT::ICEBULLET].determineCurFrame();
	jjObjectPresets[OBJECT::ICEBULLETPU].behavior = bubbleGunPU;
	jjObjectPresets[OBJECT::ICEBULLETPU].counterEnd = 105;
	jjObjectPresets[OBJECT::ICEBULLETPU].freeze = 0;
	jjObjectPresets[OBJECT::ICEBULLETPU].special = jjObjectPresets[OBJECT::ICEBULLETPU].determineCurAnim(ANIM::CUSTOM[0], 0);
	jjObjectPresets[OBJECT::ICEBULLETPU].xSpeed = 1.5;
	jjObjectPresets[OBJECT::ICEBULLETPU].determineCurFrame();
	jjObjectPresets[OBJECT::ICEAMMO3].determineCurFrame();
	jjObjectPresets[OBJECT::ICEAMMO15].determineCurFrame();
	jjObjectPresets[OBJECT::ICEPOWERUP].determineCurFrame();
	jjWeapons[WEAPON::ICE].spread = SPREAD::NORMAL;
	jjWeapons[WEAPON::ICE].defaultSample = false;
}
void onLevelBegin() {
	for (int i = 0; i < jjObjectCount; i++) {
		jjOBJ@ obj = jjObjects[i];
		if (obj.eventID == OBJECT::GENERATOR) {
			int x = int(obj.xOrg) >> 5;
			int y = (int(obj.yOrg) >> 5) - 1;
			if (x >= 0 && y >= 0 && x < jjLayers[4].width && y < jjLayers[4].height && jjEventGet(x, y) == AREA::PATH)
				obj.xPos += 14.f;
		}
	}
}
void onPlayer(jjPLAYER@ player) {
	if (jjEventGet(int(player.xPos) >> 5, int(player.yPos) >> 5) == AREA::SUCKERTUBE)
		player.alreadyDoubleJumped = false;
	bool previousSpecialMove = specialMove[player.localPlayerID];
	bool currentSpecialMove = player.specialMove != 0 && jjCharacters[player.charCurr].groundJump != GROUND::JAZZ;
	if (currentSpecialMove ^^ previousSpecialMove) {
		for (uint i = 0; i < oneWays.length(); i++) {
			const Point@ tile = oneWays[i];
			jjEventSet(tile.x, tile.y, currentSpecialMove ? 0 : AREA::ONEWAY);
		}
		specialMove[player.localPlayerID] = currentSpecialMove;
	}
}
void onDrawLayer8(jjPLAYER@ player, jjCANVAS@) {
	int y = 30 - int(player.cameraY * jjLayers[6].ySpeed / 32.f);
	if (layer7Row != y) {
		while (layer7Row > y) {
			layer7Row--;
			for (int i = 0; i < jjLayers[7].widthReal; i++) {
				int realRow = (layer7Row + jjLayers[7].height) % jjLayers[7].height;
				jjLayers[7].tileSet(i, realRow, 0);
			}
		}
		while (layer7Row < y) {
			for (int i = 0; i < jjLayers[7].widthReal; i++) {
				int realRow = (layer7Row + jjLayers[7].height) % jjLayers[7].height;
				jjLayers[7].tileSet(i, realRow, layer7Backup.tileGet(i, realRow));
			}
			layer7Row++;
		}
	}
}