Downloads containing blcon.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Blast ConcussionFeatured Download Violet CLM Capture the flag 9.7 Download file

File preview

const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, null, null, null, null, null, SmokeWopens::PhoenixGun::Wopen(), ArcaneWeapons::FusionCannon::Weapon()}); ///@MLLE-Generated
#include "MLLE-Include-1.6w.asc" ///@MLLE-Generated
#pragma require "blcon-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "blcon.j2l" ///@MLLE-Generated
#include "ArcaneWeapon9.asc" ///@MLLE-Generated
#pragma require "ArcaneWeapon9.asc" ///@MLLE-Generated
#include "PhoenixGun.asc" ///@MLLE-Generated
#pragma require "PhoenixGun.asc" ///@MLLE-Generated
///@SaveAndRunArgs -server -capture ///@MLLE-Generated

#include "ArcaneWeapon4.asc"
#pragma require "ArcaneWeapon4.asc"
ArcaneWeapons::MortarLauncher::Weapon Mortar;

#pragma offer "spelunky_ignite.wav"
bool igniteLoaded = false;

#pragma offer "blastFirewall.png" //https://opengameart.org/content/animated-sprites-and-textures
bool FirewallLoaded;
array<jjLAYER@> FirewallAnimation(64, null);
jjPAL FirewallPalette;

bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
	return MLLE::WeaponHook.drawAmmo(player, canvas);
}
void onReceive(jjSTREAM&in packet, int fromClientID) {
	bool powerup; packet.pop(powerup);
	uint16 xPos; packet.pop(xPos);
	launchMortar(xPos, powerup, jjIsServer, -fromClientID);
}

void launchMortar(uint16 xPos, bool powerup, bool send, int toClientID) {
	jjOBJ@ obj = jjObjects[Mortar.FireBullet(xPos, 16, 256, powerup, 0, CREATOR::OBJECT, WEAPON::SEEKER)[0]];
	obj.creator = CREATOR::OBJECT;
	obj.var[7] = 0;
	obj.var[0] = int(obj.yPos) + jjMaskedTopVLine(int(obj.xPos), int(obj.yPos), 36*32);
	obj.behavior = MortarWrapper;
	obj.yAcc = abs(obj.yAcc);
	obj.animSpeed = powerup ? 2 : 1;
	obj.deactivates = false;
	
	if (send) {
		jjSTREAM packet;
		packet.push(powerup);
		packet.push(xPos);
		jjSendPacket(packet, toClientID);
	}
}


void onLevelLoad() {
	Mortar.LoadResources();
	if (jjAnimSets[ANIM::PINBALL] == 0)
		jjAnimSets[ANIM::PINBALL].load();
	jjObjectPresets[OBJECT::ONEUP].behavior = jjObjectPresets[OBJECT::GUN9AMMO3].behavior;
	jjObjectPresets[OBJECT::ONEUP].var[3] = WEAPON::GUN9 - 1;
	jjObjectPresets[OBJECT::ONEUP].eventID = OBJECT::GUN9AMMO3;
	jjPIXELMAP(0,0, 32,64, 5).trim().save(jjAnimFrames[jjObjectPresets[OBJECT::ONEUPBARREL].curFrame]);
	
	jjLAYER@ slime = MLLE::GetLayer("Slime");
	slime.yOffset = (jjLayerHeight[4] - slime.height) * -32;
	jjLAYER slime2(slime);
	slime2.warpHorizon.fadePositionY = 0;
	slime2.yOffset += slime2.height * 32;
	slime2.generateSettableTileArea();
	for (int x = slime2.widthReal; --x >= 0;)
		for (int y = slime2.height; --y >= 0;)
			slime2.tileSet(x,y, 392);
	auto layers = jjLayerOrderGet();
	layers.insertAt(5, slime2);
	
	const array<int> animIDs = {1,2,5,6};
	for (uint i = 0; i < animIDs.length; ++i) {
		jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::FLAG] + animIDs[i]];
		for (uint j = 0; j < anim.frameCount; ++j)
			jjAnimFrames[anim + j].hotSpotY += 5;
	}
	
	jjObjectPresets[OBJECT::CUCUMB].behavior = Toob;
	jjObjectPresets[OBJECT::CUCUMB].playerHandling = HANDLING::SPECIAL;
	jjObjectPresets[OBJECT::CUCUMB].bulletHandling = HANDLING::DESTROYBULLET;
	for (int i = 0; i < 2; ++i) {
		jjANIMFRAME@ toobFrame = jjAnimFrames[jjObjectPresets[OBJECT::CUCUMB].curFrame + i];
		jjPIXELMAP(32,2*32*i, 6*32,2*32, 5).save(toobFrame);
		toobFrame.hotSpotX = int(toobFrame.width) / -2;
		toobFrame.hotSpotY = -5;
	}
	
	array<uint8> keepSlime(256);
	for (uint i = 0; i < 256; ++i)
		keepSlime[i] = i;
	keepSlime[183] = 0;
	for (uint animID = 0; animID < 2; ++animID) {
		auto frames = jjAnimatedTiles[animID + 1].getFrames();
		for (uint frameID = 0; frameID < frames.length(); ++frameID) {
			const uint16 tileID = frames[frameID];
			jjPIXELMAP(tileID).recolor(keepSlime).save(tileID);
		}
	}
	
	igniteLoaded = jjSampleLoad(SOUND::P2_OPEN, "spelunky_ignite.wav");
	
	jjObjectPresets[OBJECT::LIGHTNINGSHIELD].behavior =
	jjObjectPresets[OBJECT::BOUNCERPOWERUP].behavior =
	jjObjectPresets[OBJECT::GUN8POWERUP].behavior =
		NoFallMonitor;
	
	if (FirewallPalette.load("blastFirewall.png")) {
		const jjPIXELMAP firewallSheet("blastFirewall.png");
		if (firewallSheet.height == 224*64) {
			FirewallLoaded = true;
			jjLAYER fireBase(1,7);
			fireBase.textureSurface = SURFACE::INNERLAYER;
			fireBase.textureStyle = TEXTURE::WAVE;
			fireBase.ySpeed = 1;
			fireBase.xInnerSpeed = 0.9;
			fireBase.tileWidth = true;
			fireBase.yOffset = -28 * 32 - 28;
			fireBase.hasTiles = false;
			fireBase.wave.amplitudeX = 0.125;
			fireBase.wave.wavelengthX = 255;
			fireBase.wave.waveSpeed = 3;
			for (uint frameID = 0; frameID < 64; ++frameID) {
				jjLAYER fire(fireBase);
				fire.spriteMode = SPRITE::BLEND_SCREEN;
				fire.spriteParam = 255;
				jjPIXELMAP copy(256,256);
				for (uint x = 0; x < 256; ++x) {
					uint yy = frameID * 224;
					for (uint y = 0; y < 224; ++y, ++yy)
						copy[x,y] = firewallSheet[x,yy];
				}
				copy.makeTexture(fire);
				@FirewallAnimation[frameID] = @fire;
				layers.insertAt(10, fire);
			}
			jjLAYER alienCylinder(jjLayers[6]);
			jjLayers[6].spriteMode = SPRITE::INVISIBLE;
			layers.insertAt(9, alienCylinder);
		}
	}
	
	if (jjLocalPlayerCount != 1)
		MLLE::GetLayer("cooba").hasTiles = false;
	
	jjLayerOrderSet(layers);
}
void onLevelBegin() {
	jjWeapons[WEAPON::RF].replacedByShield = true;
}

void MortarWrapper(jjOBJ@ obj) {
	if (obj.yPos >= 36*32) //don't fall into the caverns
		obj.state = STATE::EXPLODE;
	if (obj.state == STATE::EXPLODE) {
		if (obj.playerHandling != HANDLING::EXPLOSION) { //skip doBlast
			obj.playerHandling = HANDLING::EXPLOSION;
			obj.frameID = 0;
			obj.counter = 0;
			obj.curAnim = obj.killAnim;
			for (int i = 1; i < jjObjectCount; i++) {
				jjOBJ@ target = jjObjects[i];
				if (target.behavior == BEHAVIOR::DESTRUCTSCENERY && target.state != STATE::KILL && target.state != STATE::DONE && target.state != STATE::EXPLODE && abs(target.xPos - obj.xPos) < 80)
					target.state = STATE::KILL;
			}
		}
	} else
		obj.counter = 5; //don't explode early
	obj.behave(ArcaneWeapons::MortarLauncher::Behavior);
	if (obj.state != STATE::EXPLODE) {
		const int distance = obj.var[0] - int(obj.yPos);
		if (distance > 31)
			jjDrawRectangle(obj.xPos - distance/64, obj.yPos, distance / 32, distance, 15, SPRITE::TRANSLUCENT);
	}
}

array<uint> MortarCountdowns(jjLocalPlayerCount, 70 * 3);
void onPlayer(jjPLAYER@ player) {
	jjIsSnowing = jjLocalPlayerCount == 1 && player.yPos > 36*32;
	if (jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME) {
		if (MortarCountdowns[player.localPlayerID] > 0)
			MortarCountdowns[player.localPlayerID] -= 1;
		if (player.yPos < 36*32 && player.xPos > 9*32 && player.yPos < 144*32 + 16) {
			if (MortarCountdowns[player.localPlayerID] == 0) {
				launchMortar(uint16(player.xPos), player.flag != 0 || jjGameState == GAME::OVERTIME, true, 0);
				MortarCountdowns[player.localPlayerID] = jjGameState == GAME::OVERTIME ? 55 : 125;
			}
		}
	}
}

void onFunction0(jjPLAYER@ player, uint8 eventID) {
	if (player.fly == FLIGHT::AIRBOARD || jjLocalPlayerCount != 1)
		eventID = AREA::ONEWAY;
	for (uint x = 33; x <= 37; ++x)
		jjEventSet(x,24, eventID);
}
void onFunction1(jjPLAYER@ player, uint8 eventID) {
	if (player.fly == FLIGHT::AIRBOARD || jjLocalPlayerCount != 1)
		eventID = AREA::ONEWAY;
	for (uint x = 116; x <= 120; ++x)
		jjEventSet(x,24, eventID);
}

void Toob(jjOBJ@ obj) {
	if (obj.state == STATE::START) {
		if (obj.creatorType == CREATOR::LEVEL)
			jjAddObject(obj.eventID, obj.xPos, obj.yPos + 56);
		obj.state = STATE::IDLE;
	}
	const auto lastY = obj.yPos;
	if (obj.creatorType == CREATOR::LEVEL)
		for (uint i = 0; i < 2; ++i)
			jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame + i, layerZ: 3 + i);
	obj.yPos = obj.yOrg + jjSin(jjGameTicks << 2) * 4;
	obj.bePlatform(obj.xPos, lastY);
}

void onFunction2() {
	if (jjGameConnection != GAME::LOCAL)
		for (int x = jjLayerWidth[4]; --x >= 0;)
			for (int y = jjLayerHeight[4]; --y >= 0;)
				if (jjParameterGet(x,y, -12, 20) == OBJECT::GENERATOR | (1 << 11) | (OBJECT::TNTDESTRUCTSCENERY << 12))
					jjEventSet(x,y, AREA::ONEWAY);
}


uint8 Layer2OpacityTarget = 255;
void onFunction3(bool on) {
	if (jjLocalPlayerCount != 1)
		return;
	if (on && Layer2OpacityTarget == 255 && igniteLoaded)
		jjSamplePriority(SOUND::P2_OPEN);
	Layer2OpacityTarget = on ? 63 : 255;
	jjLayers[2].spriteMode = SPRITE::BLEND_NORMAL;
}
void onMain() {
	jjLAYER@ layer2 = jjLayers[2];
	if (layer2.spriteParam > Layer2OpacityTarget)
		layer2.spriteParam -= 8;
	else if (layer2.spriteParam < Layer2OpacityTarget) {
		layer2.spriteParam += 8;
		if (layer2.spriteParam == 255)
			layer2.spriteMode = SPRITE::NORMAL;
	}
}

void NoFallMonitor(jjOBJ@ obj) {
	obj.direction = SPRITE::FLIPV;
	obj.behavior = BEHAVIOR::MONITOR;
	obj.behave();
	obj.direction = (jjRandom() & 1) == 1 ? SPRITE::FLIPV : SPRITE::FLIPHV;
}

uint8 firewallFrameID;
void onDrawLayer7(jjPLAYER@, jjCANVAS@) {
	if (FirewallLoaded) {
		if (jjColorDepth == 16 && !jjLowDetail) {
			jjPalette = FirewallPalette;
			FirewallAnimation[firewallFrameID & 63].hasTiles = true;
		}
		FirewallAnimation[(firewallFrameID - 1) & 63].hasTiles = false;
		++firewallFrameID;
	}
}
void onDrawLayer6(jjPLAYER@, jjCANVAS@) {
	if (FirewallLoaded && jjColorDepth == 16 && !jjLowDetail)
		jjPalette = MLLE::Palette; //https://www.everypixel.com/image-9344540279828670815
}
void onLevelReload() {
	MLLE::ReapplyPalette();
}