Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Find It Out (Single Player) | Superjazz | Single player | 9.1 |
const bool MLLESetupSuccessful = MLLE::Setup(); ///@MLLE-Generated
#include "MLLE-Include-1.6.asc" ///@MLLE-Generated
#pragma require "Fio4_b-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "Inferno1.j2t" ///@MLLE-Generated
#pragma require "wbrg.j2t" ///@MLLE-Generated
#pragma require "Fio4_b.j2l" ///@MLLE-Generated
#pragma require "Boss2.j2b"
#include "Fio_common.asc"
#include "Fio_cutscene.asc"
#include "Fio_drawing.asc"
#include "Fio_entities.asc"
#include "Fio_globals.asc"
#include "Fio_utils.asc"
enum Cutscene { CUTSCENE_NONE, CUTSCENE_INTRO, CUTSCENE_BOSS, CUTSCENE_OUTRO };
class CoolingIce : jjBEHAVIORINTERFACE {
CoolingIce(jjOBJ@ obj) {
obj.behavior = this;
}
void onBehave(jjOBJ@ obj) override {
switch(obj.state) {
case STATE::START:
if (obj.ySpeed < 0) { // Upwards
if (!hasPlayerShotIceAmmoUpwardsInBossBattle) {
hasPlayerShotIceAmmoUpwardsInBossBattle = true;
fioDraw::doShowText(5);
}
obj.ySpeed = 1.5;
if (obj.eventID == OBJECT::ICEBULLETPU) {
if (playerHeatLevel > 1) {
playerHeatLevel -= 2;
} else {
playerHeatLevel = 0;
}
} else {
if (playerHeatLevel > 0) {
playerHeatLevel--;
} else {
playerHeatLevel = 0;
}
}
playerHeatLevelElapsed = 0;
}
break;
}
obj.behave(BEHAVIOR::BULLET);
}
}
const float BOSS_X = TILE * 45.5;
const float BOSS_Y = TILE * 61.25;
const float CUTSCENE_BOSS_X = TILE * 32;
const float CUTSCENE_BOSS_Y = TILE * 61;
const float DURATION_FADE_TOTAL = CUTSCENE_SECOND * 4;
const float DURATION_FADE_BLACKOUT = CUTSCENE_SECOND * 2;
const float INTRO_ROLL_X = TILE * 221;
const float INTRO_ROLL_Y = TILE * 40;
const float INTRO_X = TILE * 185;
const float INTRO_Y = TILE * 62;
const float PLATFORM_OFFSET = 26;
const float RABBIT_MIND_STONE_DURATION = CUTSCENE_SECOND * 8 - 3;
const float RABBIT_ROLL_DURATION = CUTSCENE_SECOND * 16;
const float RABBIT_STILL_DURATION_INTRO = CUTSCENE_SECOND * 10 - 22;
const uint MAX_HEAT_LEVEL = 5;
const uint8 HEAT_WARNING_MAX_INTENSITY_LEVEL_3 = 64;
const uint8 HEAT_WARNING_MAX_INTENSITY_LEVEL_4 = 96;
const uint8 HEAT_WARNING_MAX_INTENSITY_LEVEL_5 = 128;
const string NEXT_LEVEL_FILENAME = "Fio4_y.j2l";
uint playerHeatLevel = 1;
uint playerHeatLevelElapsed = 0;
uint playerHeatLevelIncreaseInterval = 350;
uint8 activeCutscene = uint8(CUTSCENE_NONE);
uint8 playerHeatLevelFade = 0;
bool hasBossFreezeTextBeenDisplayed = false;
bool hasHeatTextBeenDisplayed = false;
bool hasHeatTextBeenDisplayedNoIce = false;
bool hasIceSourceTextBeenShown = false;
bool hasPlayerShotIceAmmoUpwardsInBossBattle = false;
bool hasPlayerSteppedOnFirstPlatform = false;
bool isMindStoneVisible = false;
bool isPlayerHeatLevelFadingIn = false;
bool isPlayerRenderedInAir = false;
bool wasCutsceneWatchedTillTheEndBoss = false;
ANIM::Set playerAnimSet;
BossFromHell@ bubba;
CharacterWithMindStone@ character;
array<string> cutsceneTextsBoss = {
"||What? Is that really you again? You should have been dead long ago!",
"|Look! I have no intention to fight you again. I am just searching for a way to find someone from the underworld.",
"||Oh, then in any case this will be really simple. If you defeat me again, you'll be drawn deeper into the underworld, straight into a prison cell!",
"||Perhaps you'll find your miserable friend from the cell next to you! Hah hah!",
"||However, you don't even have to worry about that, because I will scorch your soul right here in my lair! No living soul can survive the heat for long!",
"|I guess you are right...It is getting quite hot here. Then this battle shall be quick!",
"||PREPARE TO DIE!"
};
array<string> cutsceneTextsIntro = {
"||||After getting in contact with the mystic energies in the darkness, you've once again entered a journey through space, wondering where you'll land this time.",
"||||During your travel, you notice that for a change, these energies do not hurt you. After everything you've gone through, you feel safe and sound for the first time in a long while.",
"||||Once the energies finally calm down, you notice a change in the surrounding temperature.",
"", // Empty for visuality
"|Woah! This place is the total opposite from the previous one, yet it's still quite dark! I wonder if I'm anywhere closer to Nicholas yet.",
"|Looks like I've lost contact with Nicholas again. Hopefully he is alright. If something bad has happened to him, I might never see the light of day again...",
"|I must push forward. My time to act may be limited."
};
array<string> cutsceneTextsOutro = {
"||YAAAAAARGGGGHHHHH!"
};
array<string> texts = {
"|Ugh...more dancing with death. If I ever survive, I'll have a good tale to tell.",
"|I wonder where this portal will take me to...",
"|Another source of ice in such a warm place! I wonder what can I use it this time for...",
"|Damn! I got nothing to cool off myself! This heat is killing me!",
"|It's getting too hot in here. Perhaps I could shoot ice upwards over myself to cool off? Else this heat kills me!", // 4th
"|Phew...that's better! I need to keep on cooling myself constantly!",
"|It is too hot here to actually freeze anything. I should just shoot it upwards to cool myself."
};
array<Checkpoint@> fio4bCheckpoints = {
Checkpoint(0, INTRO_X, INTRO_Y),
Checkpoint(1, TILE * 154, TILE * 22),
Checkpoint(2, TILE * 68, TILE * 14)
};
array<Platform@> bossPlatforms;
array<Platform@> platforms;
void controlBubba() {
if (bubba.obj.freeze > 1) {
bubba.obj.freeze = 1;
if (!hasBossFreezeTextBeenDisplayed) {
fioDraw::doShowText(6);
hasBossFreezeTextBeenDisplayed = true;
}
}
}
void controlPlayerHeatLevel(jjPLAYER@ play) {
if (playerHeatLevel >= MAX_HEAT_LEVEL) {
playerHeatLevelElapsed = 0;
} else if (playerHeatLevelElapsed < playerHeatLevelIncreaseInterval) {
playerHeatLevelElapsed++;
} else {
playerHeatLevel++;
playerHeatLevelElapsed = 0;
}
if (playerHeatLevel <= 3) {
play.jumpStrength = -10;
}
if (playerHeatLevel >= 3) {
if (play.xSpeed > 3) {
play.xSpeed = 3;
} else if (play.xSpeed < -3) {
play.xSpeed = -3;
}
if (!hasHeatTextBeenDisplayed && !hasPlayerShotIceAmmoUpwardsInBossBattle && play.ammo[3] > 0) {
fioDraw::doShowText(4);
hasHeatTextBeenDisplayed = true;
} else if (!hasHeatTextBeenDisplayedNoIce && play.ammo[3] == 0) {
fioDraw::doShowText(3);
hasHeatTextBeenDisplayedNoIce = true;
}
}
if (playerHeatLevel >= 4) {
play.jumpStrength = -6;
}
if (playerHeatLevel >= 5) {
play.hurt(1);
}
}
void drawIceSource(jjCANVAS@ canvas) {
canvas.drawRotatedSprite(TILE * 72.5, TILE * 14, ANIM::AMMO, 82, 8, jjGameTicks % 1024, 2, 2, SPRITE::BLEND_NORMAL, 192);
}
void drawMindStoneAtIntro(jjCANVAS@ canvas) {
canvas.drawTile(int(play.xPos) + character.mindStoneX, int(play.yPos) + character.mindStoneY, 965);
canvas.drawTile(int(play.xPos) + character.mindStoneX, int(play.yPos) + character.mindStoneY + TILE, 975);
}
void endCutsceneIntro() {
fioCut::endCutscene(INTRO_X, INTRO_Y);
isMindStoneVisible = false;
play.lighting = LIGHTING_TWILIGHT;
activeCutscene = CUTSCENE_NONE;
checkpoints[0].setReached();
fioUtils::releasePlayer();
}
void endCutsceneBoss() {
fioCut::endCutscene(CUTSCENE_BOSS_X, CUTSCENE_BOSS_Y);
activeCutscene = CUTSCENE_NONE;
fioCut::clearAnimationChains();
staticPlayerRenderState = STATE_STATIC_PLAYER_RENDER_OFF;
isPlayerHeatLevelFadingIn = false;
playerHeatLevelFade = 0;
fioUtils::releasePlayer();
play.cameraUnfreeze(false);
jjMusicLoad(BOSS_THEME_FILENAME, false, true);
fioDraw::textIndex = -1;
@bubba = BossFromHell(fio::getActiveObjectFromLevel(OBJECT::BUBBA), getBossHealthByDifficulty());
bubba.obj.state = STATE::DELAYEDSTART;
isCustomBossActivated = true;
CoolingIce(jjObjectPresets[OBJECT::ICEBULLET]);
CoolingIce(jjObjectPresets[OBJECT::ICEBULLETPU]);
initiatePlatformMovementBoss();
fio::preserveAmmoForBossBattle();
}
int getBossHealthByDifficulty() {
if (jjDifficulty >= 3) return 600;
if (jjDifficulty == 2) return 400;
if (jjDifficulty == 1) return 300;
return 200;
}
int getPointRewardByDifficulty() {
if (jjDifficulty >= 3) return 60000;
if (jjDifficulty == 2) return 10000;
if (jjDifficulty == 1) return 5000;
return 1000;
}
uint8 getHeatWarningIntensityLevel() {
if (playerHeatLevel == 3) {
return HEAT_WARNING_MAX_INTENSITY_LEVEL_3;
}
if (playerHeatLevel == 4) {
return HEAT_WARNING_MAX_INTENSITY_LEVEL_4;
}
return HEAT_WARNING_MAX_INTENSITY_LEVEL_5;
}
void initiatePlatformMovement() {
for (uint i = 0; i < platforms.length(); i++) {
platforms[i].obj.state = STATE::FADEIN;
}
}
void initiatePlatformMovementBoss() {
for (uint i = 0; i < bossPlatforms.length(); i++) {
bossPlatforms[i].obj.state = STATE::FADEIN;
}
}
void initializeIntro() {
fioCut::initializeCutscene(@processTickEvents, cutsceneTextsIntro);
fioCut::createEventFade(DURATION_FADE_TOTAL, DURATION_FADE_BLACKOUT, false, true);
fioCut::setTickEventsProcessed(true);
play.noFire = true;
play.cameraFreeze(INTRO_ROLL_X, INTRO_ROLL_Y, true, true);
activeCutscene = CUTSCENE_INTRO;
}
void initializeOutro() {
play.noFire = true;
play.invisibility = true;
play.invincibility = 7000; // Should suffice
isPlayerHiddenAndUnableToMove = true;
isPlayerRenderedInAir = true;
fioCut::initializeCutscene(@processTickEvents, cutsceneTextsOutro);
activeCutscene = CUTSCENE_OUTRO;
}
void initializeBossCutsceneAnimationChain() {
// Duration, xOrigin, yOrigin, xDestination, yDestination, angle, scaleX, scaleY, animSet, animationId,
// startingFrame, finalFrame, frameRate, repetitions (optional)
// REMINDER: DON'T FORGET TO REMOVE THE TRAILING COMMA, SINCE OTHERWISE AS WILL INSERT A NULL HANDLE AFTER THE LAST ACTUAL OBJECT ELEMENT
const array<fioCut::Animation@> animationsBoss = {
fioCut::Animation(CUTSCENE_SECOND * 44,
BOSS_X, BOSS_Y,
BOSS_X, BOSS_Y,
0, 1, 1, ANIM::BUBBA, 5, 0, 0, 1, 0, false, -1) // Framerate doesn't really matter here but w/e
};
fioCut::createAnimationChain(animationsBoss);
}
void initializeIntroAnimationChain() {
// Duration, xOrigin, yOrigin, xDestination, yDestination, angle, scaleX, scaleY, animSet, animationId,
// startingFrame, finalFrame, frameRate, repetitions (optional)
// REMINDER: DON'T FORGET TO REMOVE THE TRAILING COMMA, SINCE OTHERWISE AS WILL INSERT A NULL HANDLE AFTER THE LAST ACTUAL OBJECT ELEMENT
const array<fioCut::Animation@> animationsIntroRabbit = {
fioCut::Animation(RABBIT_ROLL_DURATION,
TILE * 222, TILE * 37,
TILE * 222, TILE * 37,
0, 1, 1, playerAnimSet, RABBIT::ROLLING, 0, 7, FRAME_RATE_INTRO_RABBIT),
fioCut::EmptyAnimation(CUTSCENE_SECOND),
fioCut::Animation(8,
TILE * 187, TILE * 61,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, RABBIT::ROLLING, 0, 7, FRAME_RATE_INTRO_RABBIT),
fioCut::Animation(4,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, RABBIT::ROLLING, 0, 7, FRAME_RATE_INTRO_RABBIT),
fioCut::Animation(RABBIT_STILL_DURATION_INTRO,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, character.idleAnimation, character.idleFrame, character.idleFrame, 1, 0, false, -1), // Framerate doesn't really matter here but w/e
fioCut::Animation(16,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, character.digAnimation, character.digFrameStart, character.digFrameEnd, 2, 1, false, -1),
fioCut::Animation(RABBIT_MIND_STONE_DURATION,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, character.withMindStoneAnimation, character.withMindStoneFrame, character.withMindStoneFrame, 1, 0, false, -1),
fioCut::Animation(16,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, character.digAnimation, character.digFrameEnd, character.digFrameStart, 2, 1, true, -1),
fioCut::Animation(CUTSCENE_SECOND * 5,
INTRO_X, INTRO_Y,
INTRO_X, INTRO_Y,
0, 1, 1, playerAnimSet, character.idleAnimation, character.idleFrame, character.idleFrame, 1, 0, false, -1)
};
fioCut::createAnimationChain(animationsIntroRabbit);
}
void initializePlatforms() {
platforms = array<Platform@>(0);
// The x argument should represent the location of the left edge of the platform
// and the y argument should represent the top part of the platform
array<array<Node@>> nodeSets = {
{
Node(TILE * 176, TILE * 60 + PLATFORM_OFFSET),
Node(TILE * 160, TILE * 60 + PLATFORM_OFFSET)
},
{
Node(TILE * 160, TILE * 43 + PLATFORM_OFFSET),
Node(TILE * 160, TILE * 59 + PLATFORM_OFFSET)
},
{
Node(TILE * 160, TILE * 42 + PLATFORM_OFFSET),
Node(TILE * 176, TILE * 42 + PLATFORM_OFFSET)
},
{
Node(TILE * 182, TILE * 39 + PLATFORM_OFFSET),
Node(TILE * 183, TILE * 38 + PLATFORM_OFFSET),
Node(TILE * 183, TILE * 37 + PLATFORM_OFFSET),
Node(TILE * 170, TILE * 34 + PLATFORM_OFFSET),
Node(TILE * 166, TILE * 24 + PLATFORM_OFFSET),
Node(TILE * 166, TILE * 30 + PLATFORM_OFFSET),
Node(TILE * 170, TILE * 34 + PLATFORM_OFFSET)
},
{
Node(TILE * 145, TILE * 24 + PLATFORM_OFFSET), // 5th
Node(TILE * 133, TILE * 36 + PLATFORM_OFFSET)
},
{
Node(TILE * 142, TILE * 39 + PLATFORM_OFFSET),
Node(TILE * 130, TILE * 27 + PLATFORM_OFFSET)
},
{
Node(TILE * 120, TILE * 49 + PLATFORM_OFFSET),
Node(TILE * 132, TILE * 37 + PLATFORM_OFFSET)
},
{
Node(TILE * 144, TILE * 39 + PLATFORM_OFFSET),
Node(TILE * 132, TILE * 51 + PLATFORM_OFFSET)
},
{
Node(TILE * 83, TILE * 53 + PLATFORM_OFFSET),
Node(TILE * 83, TILE * 42 + PLATFORM_OFFSET),
Node(TILE * 77, TILE * 42 + PLATFORM_OFFSET),
Node(TILE * 77, TILE * 53 + PLATFORM_OFFSET)
},
{
Node(TILE * 80, TILE * 40 + PLATFORM_OFFSET), // 10th
Node(TILE * 80, TILE * 32 + PLATFORM_OFFSET)
},
{
Node(TILE * 109, TILE * 59 + PLATFORM_OFFSET),
Node(TILE * 100, TILE * 65 + PLATFORM_OFFSET),
Node(TILE * 96, TILE * 65 + PLATFORM_OFFSET),
Node(TILE * 90, TILE * 56 + PLATFORM_OFFSET),
Node(TILE * 100, TILE * 65 + PLATFORM_OFFSET),
Node(TILE * 106, TILE * 65 + PLATFORM_OFFSET),
Node(TILE * 109, TILE * 60 + PLATFORM_OFFSET)
},
{
Node(TILE * 84, TILE * 32 + PLATFORM_OFFSET),
Node(TILE * 84, TILE * 18 + PLATFORM_OFFSET),
Node(TILE * 76, TILE * 18 + PLATFORM_OFFSET),
Node(TILE * 76, TILE * 32 + PLATFORM_OFFSET)
},
{
Node(TILE * 76, TILE * 18 + PLATFORM_OFFSET),
Node(TILE * 76, TILE * 32 + PLATFORM_OFFSET),
Node(TILE * 84, TILE * 32 + PLATFORM_OFFSET),
Node(TILE * 84, TILE * 18 + PLATFORM_OFFSET)
}
};
array<float> platformSpeeds = {
2.0,
2.0,
2.0,
2.0,
2.0, // 5th
2.0,
2.0,
2.0,
2.0,
3.0, // 10th
3.0,
3.0,
3.0
};
array<uint16> platformTileIds = {
50, 56, 60, 66
};
for (uint i = 0; i < nodeSets.length(); i++) {
platforms.insertLast(
Platform(
jjObjects[jjAddObject(OBJECT::PINKPLATFORM, nodeSets[i][0].x, nodeSets[i][0].y)],
nodeSets[i],
4, // renderOffsetY
platformSpeeds[i],
platformTileIds
)
);
}
}
void initializePlatformsAtBoss() {
bossPlatforms = array<Platform@>(0);
// The x argument should represent the location of the left edge of the platform
// and the y argument should represent the top part of the platform
array<array<Node@>> nodeSets = {
{
Node(TILE * 31, TILE * 61 + PLATFORM_OFFSET),
Node(TILE * 31, TILE * 54 + PLATFORM_OFFSET),
Node(TILE * 31, TILE * 68 + PLATFORM_OFFSET)
},
{
Node(TILE * 44, TILE * 61 + PLATFORM_OFFSET),
Node(TILE * 44, TILE * 68 + PLATFORM_OFFSET),
Node(TILE * 44, TILE * 54 + PLATFORM_OFFSET)
}
};
array<float> platformSpeeds = {
2.0,
2.0
};
array<uint16> platformTileIds = {
50, 53, 56, 60, 63, 66
};
for (uint i = 0; i < nodeSets.length(); i++) {
bossPlatforms.insertLast(
Platform(
jjObjects[jjAddObject(OBJECT::PINKPLATFORM, nodeSets[i][0].x, nodeSets[i][0].y)],
nodeSets[i],
4, // renderOffsetY
platformSpeeds[i],
platformTileIds,
5 // layerZ = 5, so that other renders are drawn front
)
);
}
}
bool isBubbaDead() {
return @bubba !is null && bubba.energy <= 0;
}
// Required for each level
bool onCheat(string &in cheat) {
return fio::handleCheat(cheat, NEXT_LEVEL_FILENAME);
}
// Required for each level
bool onDrawHealth(jjPLAYER@ play, jjCANVAS@ canvas) {
fioDraw::animateHud();
fioDraw::drawHud(play, canvas, activeCutscene != CUTSCENE_NONE);
if (activeCutscene != CUTSCENE_NONE) {
fioCut::drawCutscene(canvas, centeredText, activeCutscene == CUTSCENE_BOSS);
}
if (playerHeatLevel >= 3) {
canvas.drawRectangle(0, 0, jjSubscreenWidth, jjSubscreenHeight, 24, SPRITE::BLEND_NORMAL,
uint8(abs(jjSin(jjGameTicks % 512 * 2) * getHeatWarningIntensityLevel())));
}
return activeCutscene != CUTSCENE_NONE;
}
void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ canvas) {
if (activeCutscene != CUTSCENE_NONE) {
fioCut::renderAnimations(canvas);
if (isMindStoneVisible) {
drawMindStoneAtIntro(canvas);
}
}
fio::renderCommon(play, canvas);
drawIceSource(canvas);
if (isCustomBossActivated && !isBubbaDead()) {
for (uint i = 0; i < MAX_HEAT_LEVEL; i++) {
canvas.drawSprite(int(play.xPos) - 32 + i * 16, int(play.yPos) - 32, ANIM::AMMO, 13, 1, 0, SPRITE::SINGLECOLOR, 31);
}
for (uint i = 0; i < playerHeatLevel; i++) {
canvas.drawSprite(int(play.xPos) - 32 + i * 16, int(play.yPos) - 32, ANIM::AMMO, 13, 1, 0);
}
} else if (isPlayerHeatLevelFadingIn) {
for (uint i = 0; i < MAX_HEAT_LEVEL; i++) {
canvas.drawSprite(int(play.xPos) - 32 + i * 16, int(play.yPos) - 32, ANIM::AMMO, 13, 1, 0, SPRITE::BLEND_COLOR, playerHeatLevelFade);
}
for (uint i = 0; i < playerHeatLevel; i++) {
canvas.drawSprite(int(play.xPos) - 32 + i * 16, int(play.yPos) - 32, ANIM::AMMO, 13, 1, 0, SPRITE::BLEND_NORMAL, playerHeatLevelFade);
}
}
if (isPlayerRenderedInAir) {
fioDraw::drawFrameAtPlayerPos(play, canvas, fio::getAnimSetForPlayer(play), RABBIT::FALL, 0);
}
}
bool onDrawLives(jjPLAYER@ play, jjCANVAS@ canvas) {
return true;
}
bool onDrawScore(jjPLAYER@ play, jjCANVAS@ canvas) {
return activeCutscene != CUTSCENE_NONE;
}
void onFunction0() {
play.lighting = LIGHTING_TWILIGHT;
if (activeCutscene == CUTSCENE_NONE && !checkpoints[0].isReached()) {
checkpoints[0].setReached();
}
}
void onFunction1() {
fioDraw::doShowText(0);
}
void onFunction2() {
play.lighting = LIGHTING_TWILIGHT;
if (!checkpoints[1].isReached()) {
checkpoints[1].setReached();
}
}
void onFunction3() {
if (!checkpoints[2].isReached()) {
checkpoints[2].setReached();
}
}
void onFunction4() {
play.lighting = LIGHTING_TWILIGHT;
}
void onFunction5() {
fioDraw::doShowText(1);
}
void onFunction6() {
isPlayerUnableToMove = true;
play.warpToID(1);
}
void onFunction7() {
play.lighting = LIGHTING_STANDARD;
if (!wasCutsceneWatchedTillTheEndBoss) {
play.cameraFreeze(TILE * 39, TILE * 60, true, false);
fioCut::initializeCutscene(@processTickEvents, cutsceneTextsBoss);
activeCutscene = CUTSCENE_BOSS;
initializeBossCutsceneAnimationChain();
} else {
endCutsceneBoss();
}
}
void onFunction8() {
// hurt() instead of kill(), because kill() won't display the actual roast animation
play.hurt(7, true);
}
void onFunction9() {
if (play.ammo[3] < 99) {
play.ammo[3] = 99;
}
if (!hasIceSourceTextBeenShown) {
fioDraw::doShowText(2);
hasIceSourceTextBeenShown = true;
}
}
void onFunction10() {
play.warpToID(1);
}
void onLevelBegin() {
@character = fio::getCharacterWithMindStoneForPlayer(play, true);
initializeIntro();
initializePlatforms();
initializePlatformsAtBoss();
}
// Required for each level
void onLevelLoad() {
initializeGlobals(fio4bCheckpoints, 0);
fioDraw::initializeDrawing(texts, array<string>(0), false);
playerAnimSet = fio::getAnimSetForPlayer(jjLocalPlayers[0]);
if (jjDifficulty >= 2) {
playerHeatLevelIncreaseInterval = 210;
}
mindstoneCommunicationTileIds = array<uint16>(5);
mindstoneCommunicationTileIds[0] = 960;
mindstoneCommunicationTileIds[1] = 969;
mindstoneCommunicationTileIds[2] = 970;
mindstoneCommunicationTileIds[3] = 979;
mindstoneCommunicationTileIds[4] = 980;
}
// Required for each level
void onLevelReload() {
MLLE::ReapplyPalette();
reloadGlobals();
fioDraw::initializeDrawing(texts, array<string>(0), false);
initializePlatforms();
if (fio::handleLevelReload()) {
activeCutscene = CUTSCENE_NONE;
} else {
initializeIntro();
}
if (hasPlayerSteppedOnFirstPlatform) {
initiatePlatformMovement();
}
isCustomBossActivated = false;
isPlayerHeatLevelFadingIn = false;
playerHeatLevelFade = 0;
jjEnabledASFunctions[7] = true;
playerHeatLevel = 1;
playerHeatLevelElapsed = 0;
play.jumpStrength = -10;
jjObjectPresets[OBJECT::ICEBULLET].behavior = BEHAVIOR::BULLET;
jjObjectPresets[OBJECT::ICEBULLETPU].behavior = BEHAVIOR::BULLET;
initializePlatformsAtBoss(); // Reset boss platforms back to the original states
if (isBubbaDead()) {
fio::handleLevelCycle(NEXT_LEVEL_FILENAME, true); // Just in case you mess up the outro by jjk or something :-)
}
}
// Required for each level
void onMain() {
fio::controlPressedKeys();
fioDraw::controlHud();
}
// Required for each level
void onPlayer(jjPLAYER@ play) {
fio::handlePlayer(play);
if (activeCutscene != CUTSCENE_NONE) {
fioCut::run();
if (!fioCut::isTickEventsProcessed()) {
processTickEvents(play);
fioCut::setTickEventsProcessed(true);
}
}
if (!hasPlayerSteppedOnFirstPlatform && play.platform > 0) {
hasPlayerSteppedOnFirstPlatform = true;
initiatePlatformMovement();
}
if (isCustomBossActivated && isBubbaDead()) {
bubba.obj.particlePixelExplosion(1);
bubba.obj.state = STATE::KILL;
bubba.obj.delete();
fio::rewardPoints(getPointRewardByDifficulty());
isCustomBossActivated = false;
initializeOutro();
} else if (isCustomBossActivated && !isBubbaDead()) {
controlBubba();
controlPlayerHeatLevel(play);
} else if (isPlayerHeatLevelFadingIn && playerHeatLevelFade < 255) {
playerHeatLevelFade++;
}
if (isPlayerRenderedInAir) {
play.xPos = TILE * 39;
play.yPos = TILE * 60;
}
}
void onPlayerInput(jjPLAYER@ play) {
fio::controlArmoryInput(play);
fio::controlPlayerInput(play, activeCutscene != CUTSCENE_NONE);
if (activeCutscene != CUTSCENE_NONE) {
fioCut::controlPlayerInput(play);
if (fioCut::isCutsceneSkipInitiatedAfterDelay(play)) {
fioCut::setCutsceneSkipInitiated();
if (activeCutscene == CUTSCENE_INTRO) {
endCutsceneIntro();
} else if (activeCutscene == CUTSCENE_BOSS) {
endCutsceneBoss();
} else if (activeCutscene == CUTSCENE_OUTRO) {
fioUtils::releasePlayer();
isPlayerRenderedInAir = false;
fio::handleLevelCycle(NEXT_LEVEL_FILENAME, true, true);
// Don't set activeCutscene to CUTSCENE_NONE so that the cutscene engine can process the level cycle event properly
}
}
}
}
void onRoast(jjPLAYER@ victim, jjPLAYER@ killer) {
fio::saveTriggerStates();
asPlay.savePlayerProperties(play);
}
void processCutsceneBoss(jjPLAYER@ play) {
switch(uint(fioCut::getElapsedCutscene())) {
case 8:
fioCut::startTextSliding();
isPlayerHiddenAndUnableToMove = true;
staticPlayerRenderState = STATE_STATIC_PLAYER_RENDER_IDLE;
break;
case CUTSCENE_SECOND * 33:
isPlayerHeatLevelFadingIn = true;
break;
case CUTSCENE_SECOND * 44 - 20:
fio::increaseCutscenesWatchedIfFastForwardWasNotUsed(fioCut::wasFastForwardUsed);
wasCutsceneWatchedTillTheEndBoss = true;
endCutsceneBoss();
break;
}
}
void processCutsceneIntro(jjPLAYER@ play) {
switch(uint(fioCut::getElapsedCutscene())) {
case CUTSCENE_SECOND * 1:
fioCut::startTextSliding();
isPlayerHiddenAndUnableToMove = true;
break;
case CUTSCENE_SECOND * 4:
play.xPos = TILE * 221;
play.yPos = TILE * 55;
break;
case CUTSCENE_SECOND * 8:
initializeIntroAnimationChain();
break;
case CUTSCENE_SECOND * 24:
play.xPos = INTRO_X;
play.yPos = INTRO_Y;
jjSamplePriority(SOUND::COMMON_TELPORT2);
fioCut::createEventCameraScroll(25, TILE * 191, INTRO_Y,
INTRO_X, INTRO_Y);
break;
case CUTSCENE_SECOND * 35 + 11:
isMindStoneVisible = true;
fioCut::isMindstoneCommunicationRendered = true;
break;
case CUTSCENE_SECOND * 43 + 6:
isMindStoneVisible = false;
fioCut::isMindstoneCommunicationRendered = false;
break;
case CUTSCENE_SECOND * 47 - 3:
// Get player out of the ball mode in time
play.ballTime = 0;
break;
case CUTSCENE_SECOND * 48:
fio::increaseCutscenesWatchedIfFastForwardWasNotUsed(fioCut::wasFastForwardUsed);
endCutsceneIntro();
break;
}
}
void processCutsceneOutro(jjPLAYER@ play) {
switch(uint(fioCut::getElapsedCutscene())) {
case 1:
fioCut::startTextSliding();
break;
case CUTSCENE_SECOND * 4:
fioUtils::releasePlayer();
isPlayerRenderedInAir = false;
fio::increaseCutscenesWatchedIfFastForwardWasNotUsed(fioCut::wasFastForwardUsed);
fio::handleLevelCycle(NEXT_LEVEL_FILENAME, true);
break;
}
}
void processTickEvents(jjPLAYER@ play) {
switch (activeCutscene) {
case CUTSCENE_INTRO:
processCutsceneIntro(play);
break;
case CUTSCENE_BOSS:
processCutsceneBoss(play);
break;
case CUTSCENE_OUTRO:
processCutsceneOutro(play);
break;
}
}
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.