Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Foo Single Player 2/14:... | Violet CLM | Single player | 10 |
#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!"
}
};
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.