Downloads containing BL18_level03.j2as

Downloads
Name Author Game Mode Rating
JJ2+ Only: Foo Single Player 2/14:...Featured Download Violet CLM Single player 10 Download file

File preview

#include "MLLE-Include-1.4.asc"
const bool MLLESetupSuccessful = MLLE::Setup();
#pragma require "sirius1.j2t"
#pragma require "psych2.j2t"
#pragma require "egypt.j2t"
#pragma require "gloweeb-fix.j2t"
#pragma require "wtfacrid.j2t"
#pragma require "candionv.j2t"
#pragma require "candin01.j2t"
#pragma require "BL18_level03.j2l"
#include "BL18.asc"

const uint TimeTarget = 675;
uint BubbleFrame;
bool Outside = false;
bool BeenOutsideBefore = false;
void onLevelLoad() {
	TrueColor::EnableCaching();
	@BL18::myCoinWarpFunction = ToggleFinalTrigger;
	@BL18::myLevelReload = RefreshStatsAfterBoss;
	BL18::Setup();
	
	//setup resized blocks for menu textured background
	jjPIXELMAP blocks(635);
	array<jjPIXELMAP@> newTiles = {jjPIXELMAP(),jjPIXELMAP(),jjPIXELMAP(),jjPIXELMAP()};
	for (uint x = 0; x < 64; ++x)
		for (uint y = 0; y < 64; ++y)
			newTiles[(x >> 5) | ((y >> 5) << 1)][x & 31, y & 31] = blocks[x >> 1, y >> 1];
	for (uint i = 0; i < 4; ++i)
		newTiles[i].save(647 + (i & 1) + (i & 2) * 5);
		
	for (int i = 0; i < (jjIsTSF ? 13 : 12); ++i)
		BL18::Recolor(jjAnimations[jjAnimSets[ANIM::FROG] + i], array<uint8>={80}, BL18::RecolorReplace(224)); //green to chocolate
		
	for (int i = 0; i < 6; ++i) {
		const jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::UTERUS] + i];
		BL18::Recolor(anim, array<uint8>={24, 48}, BL18::RecolorReplace(40));
		BL18::Recolor(anim, array<uint8>={16, 80}, BL18::RecolorReplace(24));
	}
	
	jjObjectPresets[OBJECT::CHOCBAR].playerHandling = HANDLING::PARTICLE; //eyecandy only
	
	BubbleFrame = jjAnimations[jjAnimSets[TrueColor::FindCustomAnim()].load(BL18::AnimSets::LavaLamp, "BL18.j2a")];
	Bubbles.resize(100);
	
	jjObjectPresets[OBJECT::MORPH].playerHandling = HANDLING::PARTICLE;
	jjObjectPresets[OBJECT::MORPH].curFrame = BubbleFrame + 2;;
	jjObjectPresets[OBJECT::MORPH].behavior = GiantBubble;
	
	jjWaterLayer = 0;
	
	for (int i = 0; i < 4; ++i) { //carrying over to SPIKEBOLL3D
		const jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::SPIKEBOLL + (i >> 1)] + (i & 1)];
		BL18::Recolor(anim, array<uint8>={72}, BL18::RecolorReplace(224));
		BL18::Recolor(anim, array<uint8>={24}, BL18::RecolorReplace(48));
	}
	jjObjectPresets[OBJECT::SPIKEBOLL].energy = 0; //unshootable
	jjObjectPresets[OBJECT::SPIKEBOLL].behavior = SpikeBollWrapper;
	jjObjectPresets[OBJECT::SPIKEBOLL3D].behavior = SpikeBoll3DWrapper;
	
	Uterus(jjObjectPresets[OBJECT::UTERUS]);
	UterusSpikeBall(jjObjectPresets[OBJECT::UTERUSSPIKEBALL]);
	jjObjectPresets[OBJECT::CRAB].behavior = BEHAVIOR::INACTIVE; //cheap fix
}

class Uterus : BL18::Enemy {
	Uterus(jjOBJ@ preset) {
		super(preset);
		if (jjDifficulty < 2)
			preset.energy = (preset.energy * 3 / 5);
	}
	void onBehave(jjOBJ@ obj) override {
		if (obj.state == STATE::DEACTIVATE) { //fixes JJ2 bug
			obj.xOrg = 77*32 + 15;
			obj.yOrg = 2*32 + 15;
			obj.deactivate();
		} else if (obj.state != STATE::DONE)
			obj.behave(BEHAVIOR::UTERUS, true);
		obj.bulletHandling = HANDLING::DETECTBULLET;
	}
	void onDraw(jjOBJ@ obj) override {
		drawHearts(obj);
	}
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) override {
		auto state = obj.state;
		if (state == STATE::FREEZE) state = obj.oldState;
		if (bullet !is null && (state == STATE::FLY || (state == STATE::EXTRA && !obj.isFreezable))) {
			bullet.state = STATE::EXPLODE;
		} else if (bullet is null)
			player.hurt();
		else {
			Enemy::onObjectHit(obj, bullet, player, force);
			if (obj.energy <= 0)
				@BL18::CurrentPopup = ConversationOfIneffableWisdom();
		}
		return true;
	}
}
class UterusSpikeBall : BL18::Enemy {
	UterusSpikeBall(jjOBJ@ preset) {
		super(preset);
		preset.direction = 1;
		preset.curFrame = BubbleFrame;
	}
	void onBehave(jjOBJ@ obj) override {
		if (obj.state != STATE::DONE)
			obj.behave(BEHAVIOR::UTERUSSPIKEBALL, false);
		else
			obj.eventID = 0; //don't be detected to still exist
	}
	void onDraw(jjOBJ@ obj) override {
		drawMainSprite(obj, -1, obj.var[1]);
	}
}

class ConversationOfIneffableWisdom : BL18::Conversation {
	ConversationOfIneffableWisdom() {
		super(Conversations[Conversations.length-1], 0, BubbleFrame);
		BL18::Player.bossActivated = false;
	}
	uint8 DelayCounter = 0;
	bool Do() override {
		if (DelayCounter < 140)
			++DelayCounter;
		else if (!Conversation::Do()) {
			@BL18::CurrentPopup = null;
			onFunction1(null, 0);
		}
		return true;
	}
	void Draw(jjCANVAS@ canvas) const override {
		if (DelayCounter >= 140)
			Conversation::Draw(canvas);
	}
	void DrawCustomFriendTalkSprite(jjCANVAS@ canvas) const override {
		canvas.drawRotatedSprite(jjResolutionWidth-100, 300, ANIM::UTERUS, 3, jjGameTicks>>3, 768 + int(jjSin(jjGameTicks<<1)*40), 2,2);
	}
	bool DrawHUD() const override { return DelayCounter < 140; }
}

void onFunction11(jjPLAYER@, bool outside) {
	if (Outside != outside) {
		jjPalette = MLLE::Palette;
		jjLayers[7].hasTiles = !outside;
		if (Outside = outside) {
			jjPalette.gradient(jjPALCOLOR(148, 0, 0), jjPALCOLOR(199, 148, 0));
			jjTexturedBGTexture = TEXTURE::MUCKAMOKNIGHT;
		} else
			jjTexturedBGTexture = TEXTURE::LAYER8;
		jjPalette.apply();
		TrueColor::ProcessPalette();
		if (Outside && !BeenOutsideBefore) {
			BeenOutsideBefore = true;
			auto bubbleBitmap = TrueColor::Bitmap(jjPIXELMAP(jjAnimFrames[BubbleFrame]));
			for (uint x = 0; x < bubbleBitmap.width; ++x)
				for (uint y = 0; y < bubbleBitmap.height; ++y) { //increase contrast
					int red = bubbleBitmap.pixels[x][y].red;
					red -= (255 - red);
					if (red < 0) red = 0;
					bubbleBitmap.pixels[x][y].red = red;
				}
			const int scale = 9;
			TrueColor::EnableCaching(false); //only will be used in this one palette
			Resize::Resize(bubbleBitmap, scale, Resize::Method::BilinearInterpolation).saveToAnimFrames(BubbleFrame + 2, TrueColor::Coordinates(0,0, 32*scale,32*scale, 32*scale/-2, 32*scale/-2, 0,0,0,0, true));
			TrueColor::EnableCaching(true);
		}
	}
}
void onFunction13() {
	jjLevelName = "Chocolate Lamp 2";
	jjLevelName = "Chocolate Lamp 2";
}

void ToggleFinalTrigger() {
	if (jjTriggers[31]) {
		jjTriggers[6] = false;
		jjTriggers[8] = false;
		jjTriggers[31] = false;
		jjSamplePriority(BL18::HPTrigger);
	}
}

int LastFood = 0, LastLives = 0;

void RefreshStatsAfterBoss() {
	if (LastFood != 0 || LastLives != 0)  { //should only be true if you died while fighting the boss, in which case, remove references to killing Uterus's shield enemies
		BL18::Player.food = LastFood;
		BL18::Player.lives = LastLives;
		LastFood = LastLives = 0;
	}
	jjSetWaterLevel(((BL18::Player.xOrg >= 232 * 32 && BL18::Player.yOrg >= 32*32) ? 29 : 255) * 32, true);
	Outside = BL18::Player.xOrg < 161 * 32; //other way around, to force onFunction11 to work
	onFunction11(null, !Outside);
}

void onFunction12(jjPLAYER@ play) {
	if (!jjTriggers[31]) {
		jjTriggers[31] = true;
		jjTriggers[30] = jjDifficulty < 2;
		jjMusicLoad("boss.j2b");
		play.activateBoss();
		onFunction11(play, true);
		LastFood = play.food;
		LastLives = play.lives;
	}
}

void onPlayerInput(jjPLAYER@ play) {
	if (play.bossActivated) {
		play.cameraFreeze(77*32, 6*32, true, true);
	} else
		play.cameraUnfreeze();
}

class Bubble {
	BL18::Point Location;
	uint CurFrame;
	uint AgeX, AgeY;
	float Scale;
	void Do() {
		if (Location.y < -50) {
			Randomize(true);
		} else {
			Location.x += jjSin(AgeX >> 4) * 1.333;
			Location.y -= abs(jjCos(AgeY >> 4)) * 2;
			const auto rand = jjRandom();
			AgeX += rand & 15;
			AgeY += (rand >> 4) & 31;
		}
	}
	void Randomize(bool snapToBottom) {
		auto rand = jjRandom();
		CurFrame = BubbleFrame + ((rand % 6) / 5);
		Location.x = jjRandom() % 800;
		Location.y = snapToBottom ? 650 : (jjRandom() % 600);
		AgeX = AgeY = jjRandom();
		Scale = 1.25 + (jjRandom() & 63) / 128.f;
	}
	Bubble() {
		Randomize(false);
	}
	void Draw(jjCANVAS@ canvas) const {
		canvas.drawRotatedSpriteFromCurFrame(
			int(Location.x), int(Location.y),
			CurFrame,
			AgeX >> 1,
			Scale + jjSin(AgeY >> 3) / 4,
			Scale + jjCos(AgeY >> 3) / 4,
			SPRITE::TRANSLUCENT
		);
	}
};
array<Bubble> Bubbles(0);

void onMain() {
	if (Outside)
		for (int i = Bubbles.length >> (jjLowDetail?2:0); --i >= 0;)
			Bubbles[i].Do();
}
void onDrawLayer8(jjPLAYER@, jjCANVAS@ canvas) {
	if (Outside)
		for (int i = Bubbles.length >> (jjLowDetail?2:0); --i >= 0;)
			Bubbles[i].Draw(canvas);
}

void GiantBubble(jjOBJ@ obj) {
	if (obj.state == STATE::DEACTIVATE)
		obj.deactivate();
	else if (Outside && !jjLowDetail) {
		++obj.age;
		const float x = obj.xPos + jjSin(obj.age) * 10, y = obj.yPos + jjCos(obj.age) * 10;
		jjDrawSpriteFromCurFrame(x,y, obj.curFrame, 1, SPRITE::NEONGLOW, 0, 1);
		jjDrawSpriteFromCurFrame(x,y, obj.curFrame+1, 1, SPRITE::NEONGLOW, 1, 1);
		jjDrawSpriteFromCurFrame(x,y, obj.curFrame+2, 1, SPRITE::NEONGLOW, 2, 1);
	}
}

void SpikeBollWrapper(jjOBJ@ obj) {
	if (obj.yOrg > jjWaterLevel) {
		obj.playerHandling = HANDLING::SPECIAL;
		obj.behave(BEHAVIOR::PLATFORM, true);
	} else if (obj.state == STATE::DEACTIVATE)
		obj.deactivate();
	else
		obj.playerHandling = HANDLING::PARTICLE;
}
void SpikeBoll3DWrapper(jjOBJ@ obj) {
	if (obj.yOrg > jjWaterLevel) //visible
		obj.behave(BEHAVIOR::SPIKEBOLL3D, true);
	else if (obj.state == STATE::DEACTIVATE)
		obj.deactivate();
}

array<array<string>> Conversations = {
	{
		"S0You probolly know this@already but lava will@burn your butt."
	},
	{
		"S2Hey IK now I already@asked aout this earlier,@but..........",
		"S4your really trying to@ask FORAEMON to be@your valatine?",
		"J0Of course! I love a man@with a beard made of@finely-woven pipe cleaners.",
		"J5And there's something kinky@about when he says that@I'll never be a foo.",
		"S4@uhhuhhhhh",
		"S5But we pilleged his castles,@wrecked his hellagram@maxine, and killed him.",
		"S7To death!",
		"J1Sure, he might be a bit@mad about that, but@he's just being tsundere.",
		"J4There's no stopping@true love, Spotty!",
		"S3But youare BOTH MEN,@and homurasexuality is@forbidden llove",
		"J7...",
		"S6Have you not read that,@he who crated tham from@the beginning mad them...",
		"S4mole and femole, and said,@\"Therfore a man sholl leave@his father and his mother...",
		"S8and hold fist to his wife,@and the too shall becoma@one flesh?\" - JESUS",
		"J3...",
		"J2I think we should@stop this conversation here."
	},
	{
		"S3soooooo hey@whats with all the coims?",
		"S6i know alot abouit@realty, so i know@you dont need rent.",
		"J8Oh, I'm collecting@these to pay for@the Valentine's Day card!",
		"J7Sorry, I thought@that was obvious.",
		"S7weLlll not saying@that it wasnt : P",
		"S8but we forgot to state@the premise of this whole@thing in the first level,",
		"S9so Ithought why not@do it now?"
	},
	{
		"S2Hey jazz",
		"S9would you like  to buy@some amway products?"
	},
	{
		"S9\"4 where TWO orr THREE@gather im my name, there@am I wit hthem\" -Jesus",
		"S0so you have to be CARFULL@ith all these tubes, Jazz!",
		"S6sometams a set of tubes will@have THREE EXATS, so u must@ go IN each to go OUT each!"
	},{
		"J4@Ha! I won!",
		"S0@@Jazz...",
		"J0Holy shit it's a talking crab!",
		"S0Of course I can talk...@I am the #Crab of@Ineffable Wisdom.",
		"J2Hello@Crab of Ineffable Wisdom!",
		"S0Hello Jazz.",
		"S0I would like to impart@some ineffable wisdom@to you right now.",
		"J7Well, sure, why not?",
		"S0The next stage of your@journey is very long.",
		"S0Very, very, very long.",
		"S0So you should DEFINITELY@SAVE YOUR GAME next@time you get a chance.",
		"S0And if you've been playing@this in one sitting, maybe@take a break first.",
		"S0That's all,@you've been warned.",
		"J5Thank you@Crab of Ineffable Wisdom!"
	}
};