Downloads containing xlmthunder.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Thunder Cliffs Superjazz Capture the flag N/A Download file

File preview

const bool MLLESetupSuccessful = MLLE::Setup(); ///@MLLE-Generated
#include "MLLE-Include-1.6.asc" ///@MLLE-Generated
#pragma require "xlmthunder-MLLE-Data-2.j2l" ///@MLLE-Generated
#pragma require "xlmthunder-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "Carrot1.j2t" ///@MLLE-Generated
#pragma require "ICJungD.j2t" ///@MLLE-Generated
#pragma require "ICJungS.j2t" ///@MLLE-Generated
#pragma require "Aztec2.j2t" ///@MLLE-Generated
#pragma require "xlmthunder.j2l" ///@MLLE-Generated
#pragma require "lightning2.wav"

class BackgroundLightning {
	bool isVisible;
	int xPixelOnLayer;
	
	BackgroundLightning(int xPixelOnLayer) {
		this.xPixelOnLayer = xPixelOnLayer;
		this.isVisible = false;
	}
}

void CantBeBuried(jjOBJ@ obj) {
	obj.behave(BEHAVIOR::PICKUP);
	
	if (jjMaskedPixel(int(obj.xPos), int(obj.yPos) + 8)) {
		obj.state = STATE::FLOAT;
	}
}

const float BLUE_BASE_X = 30 << TILE_SHIFT;
const float BLUE_BASE_Y = 33 << TILE_SHIFT;
const float RED_BASE_X = 130 << TILE_SHIFT;
const float RED_BASE_Y = 33 << TILE_SHIFT;

const int BACKGROUND_LIGHTNING_INTERVAL = 490;
const int BACKGROUND_LIGHTNING_OFFSET_Y = -300;
const int BACKGROUND_THUNDER_SAMPLE_DELAY = 100;
const int RED_SIDE_X_ORIGIN = 80 << 5;
const int TILE_SHIFT = 5;

const uint BASE_LIGHTNING_SAMPLE_COOLDOWN = 70;
const uint BLUE_BASE_Y_TILE = 33;
const uint RED_BASE_Y_TILE = 33;

const array<BackgroundLightning@> BACKGROUND_LIGHTNINGS = {
	BackgroundLightning(29 << TILE_SHIFT), // Layer 6 Lightning begin
	BackgroundLightning(24 << TILE_SHIFT),
	BackgroundLightning(9 << TILE_SHIFT),
	BackgroundLightning(4 << TILE_SHIFT), // Layer 6 lightnings end
	BackgroundLightning(0 << TILE_SHIFT), // Layer 7 Lightning begin
	BackgroundLightning(17 << TILE_SHIFT),
	BackgroundLightning(33 << TILE_SHIFT) // Layer 7 lightnings end
};

const array<uint16> LIGHTNING_FRAMES_ONE = { 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467 };
const array<uint16> LIGHTNING_FRAMES_TWO = { 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477 };
const array<uint16> LIGHTNING_FRAMES_THREE = { 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487 };

bool isLightningVisibleBlue = false;
bool isLightningVisibleRed = false;
bool isThunderSoundDelayed = false;

int previousTeamScoreBlue = 0;
int previousTeamScoreRed = 0;

uint baseLightningSampleCooldown = 0;
uint lightningFrameCounterBlue = 0;
uint lightningFrameCounterGeneral = 0;
uint lightningFrameCounterRed = 0;
uint thunderSampleDelayCounter = 0;

void disableAllBackgroundLightnings() {
	for (uint i = 0; i < BACKGROUND_LIGHTNINGS.length(); ++i) {
		BACKGROUND_LIGHTNINGS[i].isVisible = false;
	}
}

void drawLightningAtXPixel(jjCANVAS@ canvas, int xPixel) {
	for (uint i = 0; i < 30; ++i) { // 30 tiles should be enough...
		if (i % 3 == 2) {
			canvas.drawTile(xPixel, int(i << TILE_SHIFT) + BACKGROUND_LIGHTNING_OFFSET_Y, LIGHTNING_FRAMES_THREE[lightningFrameCounterGeneral]);
		} else if (i % 3 == 1) {
			canvas.drawTile(xPixel, int(i << TILE_SHIFT) + BACKGROUND_LIGHTNING_OFFSET_Y, LIGHTNING_FRAMES_TWO[lightningFrameCounterGeneral]);
		} else {
			canvas.drawTile(xPixel, int(i << TILE_SHIFT) + BACKGROUND_LIGHTNING_OFFSET_Y, LIGHTNING_FRAMES_ONE[lightningFrameCounterGeneral]);
		}
	}
}

bool isAnyBackgroundLightningVisible() {
	for (uint i = 0; i < BACKGROUND_LIGHTNINGS.length(); ++i) {
		if (BACKGROUND_LIGHTNINGS[i].isVisible) {
			return true;
		}
	}
	return false;
}

void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (isLightningVisibleBlue) {
		for (uint i = 0; i < BLUE_BASE_Y_TILE; ++i) {
			if (i % 3 == 2) {
				canvas.drawTile(BLUE_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_THREE[lightningFrameCounterBlue]);
			} else if (i % 3 == 1) {
				canvas.drawTile(BLUE_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_TWO[lightningFrameCounterBlue]);
			} else {
				canvas.drawTile(BLUE_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_ONE[lightningFrameCounterBlue]);
			}
		}
	}
	
	if (isLightningVisibleRed) {
		for (uint i = 0; i < RED_BASE_Y_TILE; ++i) {
			if (i % 3 == 2) {
				canvas.drawTile(RED_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_THREE[lightningFrameCounterRed]);
			} else if (i % 3 == 1) {
				canvas.drawTile(RED_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_TWO[lightningFrameCounterRed]);
			} else {
				canvas.drawTile(RED_BASE_X, i << TILE_SHIFT, LIGHTNING_FRAMES_ONE[lightningFrameCounterRed]);
			}
		}
	}
}

// NOTE: The layer needs to have at least non-0 tile placed or else these hooks won't be called at all.
// Setting jjLayers[6].hasTiles = true; artifically does not work either, so just place a transparent tile somewhere on the layer in MLLE...
void onDrawLayer6(jjPLAYER@ play, jjCANVAS@ canvas) {
	for (uint i = 0; i < 4; ++i) {
		BackgroundLightning@ lightning = BACKGROUND_LIGHTNINGS[i];
		
		if (lightning.isVisible) {
			drawLightningAtXPixel(canvas, lightning.xPixelOnLayer);
		}
	}
}

void onDrawLayer7(jjPLAYER@ play, jjCANVAS@ canvas) {
	for (uint i = 4; i < BACKGROUND_LIGHTNINGS.length(); ++i) {
		BackgroundLightning@ lightning = BACKGROUND_LIGHTNINGS[i];
		if (lightning.isVisible) {
			drawLightningAtXPixel(canvas, lightning.xPixelOnLayer);
		}
	}
}

void onLevelBegin() {
	jjAnimSets[ANIM::BILSBOSS].load();
	jjSampleLoad(SOUND::BILSBOSS_SCARY3, "lightning2.wav");
	
	array<uint8> bridgeRedColorMapping(256, 0);
	
	bridgeRedColorMapping[15] = 48;
	bridgeRedColorMapping[32] = 49;
	bridgeRedColorMapping[33] = 50;
	bridgeRedColorMapping[34] = 26;
	bridgeRedColorMapping[35] = 27;
	bridgeRedColorMapping[36] = 28;
	bridgeRedColorMapping[37] = 29;
	bridgeRedColorMapping[38] = 30;
	bridgeRedColorMapping[39] = 31;
	
	jjANIMSET@ bridgeAnimSet = jjAnimSets[ANIM::BRIDGE];
	jjANIMFRAME@ diamondBridgeFrame = jjAnimFrames[jjAnimations[bridgeAnimSet.firstAnim + 5].firstFrame];
	jjANIMFRAME@ sciFiBridgeFrame = jjAnimFrames[jjAnimations[bridgeAnimSet.firstAnim + 6].firstFrame];
	
	jjPIXELMAP diamondBridgeSprite(diamondBridgeFrame);
	diamondBridgeSprite.recolor(bridgeRedColorMapping);
	diamondBridgeSprite.save(sciFiBridgeFrame); // Replace Sci-Fi bridge sprites with the re-colored Diamond sprites
	
	jjAlert("NOTE: Powered up Electro-blaster (Gun9) always does |2 |||||||damage in this level!");
}

void onLevelLoad() {
	jjUseLayer8Speeds = true;
	
	jjObjectPresets[OBJECT::CARROT].behavior = CantBeBuried;
	jjObjectPresets[OBJECT::FULLENERGY].behavior = CantBeBuried;
	
	// For buffing powered up Electro bullets to do 2 dmg as with /strongpowerups on. No idea why it works, but thx PJ! xP
	jjObjectPresets[OBJECT::ELECTROBULLETPU].eventID = OBJECT::ELECTROBULLET;
}

void onMain() {
	array<jjLAYER@> layers = jjLayerOrderGet();
	
	layers[5].xOffset += 6.20f;

	processBackgroundLightningEffects();
	processBaseLightningEffects();
}

void playDistantThunderSample() {
	jjSamplePriority(SOUND::BILSBOSS_SCARY3);
}

// JATKA TÄSTÄ...GJ! Sait salamat renderöityä sopivasti taustalayereiden väliin ja sadettakin hieman luonnosteltua taustalle...
// Katso haluatko vielä muokata joitakin tausta-elementtejä hieman, kuten esim. vaihtaa etummaiset puut yms johonkin muuhun jne...
// Muuten alkaakin tausta näyttämään melko hyvältä, jotta voi aloittaa itse layoutia...
void playLightningSampleAt(float centerX, float centerY) {
	const float fiveTiles = 5 << TILE_SHIFT;
	const float endX = fiveTiles * 3 + centerX;
	const float startY = centerY + fiveTiles;
	for (float x = centerX - fiveTiles; x < endX; x += fiveTiles) {
		for (float y = startY; y > 0; y -= fiveTiles) {
			// Keep these for now for debugging purposes
			//jjAlert("x: " + x + ", y: " + y);
			//jjDrawTile(x, y, 1);
			jjSample(x, y, SOUND::BILSBOSS_THUNDER);
		}
	}
}

void processBackgroundLightningEffects() {

	if (isThunderSoundDelayed) {
		if (thunderSampleDelayCounter > 0) {
			--thunderSampleDelayCounter;
		} else {
			playDistantThunderSample();
			isThunderSoundDelayed = false;
		}
	}

	if 	(jjGameTicks % 7 == 0 && isAnyBackgroundLightningVisible()) {
		if (lightningFrameCounterGeneral < LIGHTNING_FRAMES_ONE.length() - 1) {
			++lightningFrameCounterGeneral;
		} else {
			disableAllBackgroundLightnings();
		}
	}
	
	if (jjGameTicks % BACKGROUND_LIGHTNING_INTERVAL == 0) {
		int randomIndex = jjRandom() % BACKGROUND_LIGHTNINGS.length();
		BACKGROUND_LIGHTNINGS[randomIndex].isVisible = true;
		lightningFrameCounterGeneral = 0;
		thunderSampleDelayCounter = BACKGROUND_THUNDER_SAMPLE_DELAY;
		isThunderSoundDelayed = true;
	}
}

void processBaseLightningEffects() {

	// These will also trigger for a client who joins during an ongoing game where the respective team's score is higher than 0,
	// but that should not be a problem as it happens only once and works as a nice welcome effect I guess
	if (jjTeamScore[TEAM::BLUE] > previousTeamScoreBlue) {
		playLightningSampleAt(BLUE_BASE_X, BLUE_BASE_Y);
		lightningFrameCounterBlue = 0;
		isLightningVisibleBlue = true;
		previousTeamScoreBlue = jjTeamScore[TEAM::BLUE];
	} else if (jjTeamScore[TEAM::BLUE] < previousTeamScoreBlue) { // As set by /bluescore x etc
		previousTeamScoreBlue = jjTeamScore[TEAM::BLUE];
	}
	
	if (jjTeamScore[TEAM::RED] > previousTeamScoreRed) {
		playLightningSampleAt(RED_BASE_X, RED_BASE_Y);
		lightningFrameCounterRed = 0;
		isLightningVisibleRed = true;
		previousTeamScoreRed = jjTeamScore[TEAM::RED];
	} else if (jjTeamScore[TEAM::RED] < previousTeamScoreRed) { // As set by /redscore x etc
		previousTeamScoreRed = jjTeamScore[TEAM::RED];
	}
	
	if (jjGameTicks % 7 == 0 && isLightningVisibleBlue) {
		if (lightningFrameCounterBlue < LIGHTNING_FRAMES_ONE.length() - 1) {
			++lightningFrameCounterBlue;
		} else {
			isLightningVisibleBlue = false;
		}
	}
	
	if 	(jjGameTicks % 7 == 0 && isLightningVisibleRed) {
		if (lightningFrameCounterRed < LIGHTNING_FRAMES_ONE.length() - 1) {
			++lightningFrameCounterRed;
		} else {
			isLightningVisibleRed = false;
		}
	}
}

void onLevelReload() {
	MLLE::ReapplyPalette();
}