Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Mystery of the Four... | chandie | Single player | 6.6 |
const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, DefaultWeapons::Blaster(), DefaultWeapons::Blaster(), DefaultWeapons::Blaster(), null, DefaultWeapons::Blaster(), null, DefaultWeapons::Blaster()}); ///@MLLE-Generated
#include "MLLE-Include-1.5w.asc" ///@MLLE-Generated
#pragma require "mo4a_0.j2l" ///@MLLE-Generated
#include "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
#pragma require "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
#include "Jazz1Enemies v05.asc"
#include "Resize v11.asc"
#include "HH18savegems.asc"
int MovePlatform = 0; int ElevatorUp = 0;
bool keypicked = false;
void onLevelLoad() {
jjLevelName = ("@@@@@@@@@Throne Rooms");
jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
gem::restorePlayerGems();
jjWaterLighting = WATERLIGHT::GLOBAL;
jjObjectPresets[OBJECT::AIRBOARD].behavior = Key();
jjObjectPresets[OBJECT::AIRBOARD].scriptedCollisions = true;
jjObjectPresets[OBJECT::EXTRATIME].behavior = Key2();
jjObjectPresets[OBJECT::EXTRATIME].scriptedCollisions = true;
jjObjectPresets[OBJECT::FREEZEENEMIES].behavior = Key3();
jjObjectPresets[OBJECT::FREEZEENEMIES].scriptedCollisions = true;
jjObjectPresets[OBJECT::FASTFEET].behavior = Key4();
jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
jjObjectPresets[OBJECT::FRUITPLATFORM].scriptedCollisions = true;
jjObjectPresets[OBJECT::FRUITPLATFORM].behavior = PlatformV;
jjObjectPresets[OBJECT::SONICPLATFORM].scriptedCollisions = true;
jjObjectPresets[OBJECT::SONICPLATFORM].behavior = Elevator;
jjObjectPresets[OBJECT::SONICPLATFORM].deactivates = false;
Jazz1::MakeEnemy(OBJECT::BUMBEE, Jazz1::Enemies::Diamondus_BumblingBee).SetUsesJJ2StyleDeathAnimation(true);
Jazz1::MakeEnemy(OBJECT::DOGGYDOGG, Jazz1::Enemies::Holidaius_BlueDog).SetUsesJJ2StyleDeathAnimation(true);
jjObjectPresets[OBJECT::BIGBOX].behavior = TimeMachine;
jjObjectPresets[OBJECT::BIGBOX].determineCurAnim(ANIM::FLAG, 1);
jjObjectPresets[OBJECT::BIGBOX].putOnGround(false);
jjObjectPresets[OBJECT::BIGBOX].scriptedCollisions = true;
jjANIMATION@ tmAnim = jjAnimations[jjObjectPresets[OBJECT::BIGBOX].curAnim];
for (uint i = 0; i < tmAnim.frameCount; ++i)
jjAnimFrames[tmAnim.firstFrame + i].hotSpotY = -90;
for (uint i = 0; i < tmAnim.frameCount; ++i)
jjAnimFrames[tmAnim.firstFrame + i].hotSpotX = -54;
jjObjectPresets[OBJECT::FLYCARROT].determineCurAnim(ANIM::PLUS_WARP, 0);
jjObjectPresets[OBJECT::FLYCARROT].behavior = Bonus;
jjObjectPresets[OBJECT::FLYCARROT].scriptedCollisions = true;
jjANIMATION@ BAnim = jjAnimations[jjObjectPresets[OBJECT::FLYCARROT].curAnim];
for (uint i = 0; i < BAnim.frameCount; ++i)
jjAnimFrames[BAnim.firstFrame + i].hotSpotY = -85;
for (uint i = 0; i < BAnim.frameCount; ++i)
jjAnimFrames[BAnim.firstFrame + i].hotSpotX = 20;
jjObjectPresets[OBJECT::INVINCIBILITY].determineCurAnim(ANIM::PLUS_WARP, 1);
jjObjectPresets[OBJECT::INVINCIBILITY].behavior = Bonuseye;
jjObjectPresets[OBJECT::INVINCIBILITY].scriptedCollisions = true;
jjObjectPresets[OBJECT::INVINCIBILITY].bulletHandling = HANDLING::IGNOREBULLET;
jjObjectPresets[OBJECT::INVINCIBILITY].playerHandling = HANDLING::PLAYERBULLET;
jjANIMATION@ BeAnim = jjAnimations[jjObjectPresets[OBJECT::INVINCIBILITY].curAnim];
for (uint i = 0; i < BeAnim.frameCount; ++i)
jjAnimFrames[BeAnim.firstFrame + i].hotSpotY = 12;
for (uint i = 0; i < BeAnim.frameCount; ++i)
jjAnimFrames[BeAnim.firstFrame + i].hotSpotX = 26;
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::GEMBARREL].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP doorkey(0, 32*32, 1*32, 1*32, 4);
doorkey.save(frame);frame.hotSpotY = -17;
}
void Bonuseye(jjOBJ@ obj){
obj.direction = -1;
obj.behave(BEHAVIOR::PICKUP, false);
obj.draw();
}
void Bonus(jjOBJ@ obj){
obj.putOnGround();
obj.direction = -1;
obj.behave(BEHAVIOR::PICKUP, false);
obj.draw();
}
void TimeMachine(jjOBJ@ obj){
obj.behave(BEHAVIOR::EVA, false);
jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, 1, SPRITE::PALSHIFT, 8);
}
void PlatformV (jjOBJ@ obj) {
switch (obj.state) {
case STATE::START:
obj.direction = obj.ySpeed = -2;
obj.determineCurAnim(ANIM::PINKPLAT, 0);
obj.determineCurFrame();
obj.playerHandling = HANDLING::SPECIAL;
obj.state = STATE::FLY;
obj.beSolid();
case STATE::FLY:
obj.beSolid();
if(MovePlatform > jjGameTicks) {
obj.yPos = obj.yPos + obj.ySpeed;
obj.deactivates = true;
if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1)) {
obj.direction = obj.ySpeed = -obj.ySpeed;
} }
obj.draw();
break;
}
}
void Elevator (jjOBJ@ obj) {
switch (obj.state) {
case STATE::START:
obj.direction = obj.ySpeed = 2;
obj.determineCurAnim(ANIM::SONICPLAT, 0);
obj.determineCurFrame();
obj.playerHandling = HANDLING::SPECIAL;
obj.state = STATE::FLY;
obj.beSolid();
case STATE::FLY:
obj.beSolid();
if(p.keyUp && ElevatorUp > jjGameTicks && p.ySpeed == 0) {
obj.yPos = obj.yPos + obj.ySpeed;
obj.direction = obj.ySpeed = -2;
}
if(p.keyDown && ElevatorUp > jjGameTicks && p.ySpeed == 0) {
obj.yPos = obj.yPos + obj.ySpeed;
p.buttstomp = 90;
p.ySpeed=3;
obj.direction = obj.ySpeed = 2;
if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 36 : obj.xPos - 16, obj.yPos, 1)) {
obj.ySpeed = 0;
}
}
//jjDrawTile(obj.xPos - 17, obj.yPos - 22, 167);
obj.draw();
break;
}
}
class Key : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(jjTriggers[1]==false) {
obj.behave(BEHAVIOR::PICKUP, false);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
jjTriggers[1] = true;
keypicked = true;
control = false;
p.cameraFreeze(22*32, 17*32, true, false);
obj.behavior = BEHAVIOR::EXPLOSION2;
jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
return true;
}
}
class Key2 : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(jjTriggers[2]==true)
{obj.delete();}
obj.behave(BEHAVIOR::PICKUP, false);
obj.determineCurAnim(ANIM::MENU, 5);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -40);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
jjTriggers[2] = true;
keypicked = true;
control = false;
obj.behavior = BEHAVIOR::EXPLOSION2;
jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
return true;
}
}
class Key3 : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(jjTriggers[8]==true)
{obj.delete();}
obj.behave(BEHAVIOR::PICKUP, false);
obj.determineCurAnim(ANIM::MENU, 5);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -40);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
jjTriggers[8] = true;
keypicked = true;
control = false;
obj.behavior = BEHAVIOR::EXPLOSION2;
jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
p.cameraFreeze(138*32, 26*32, true, false);
return true;
}
}
class Key4 : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(jjTriggers[7]==true)
{obj.delete();}
obj.behave(BEHAVIOR::PICKUP, false);
obj.determineCurAnim(ANIM::MENU, 5);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -40);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
jjTriggers[7] = true;
keypicked = true;
control = false;
obj.behavior = BEHAVIOR::EXPLOSION2;
jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
p.cameraFreeze(212*32, 26*32, true, false);
return true;
}
}
bool startrush = false, readytorush = false, soundon = true, control = true, keytext = false, keytext2 = false;
void onPlayer(jjPLAYER@ p) {
if(p.idle > 100 && MovePlatform == 0)
{p.cameraUnfreeze(true);
control=true;}
else if (control == false && p.idle > 30 && (p.keyLeft || p.keyRight || p.keyJump || p.keyFire))
{p.cameraUnfreeze(true);
control = true;}
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::AIRBOARD].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP doorkey(0, 31*32, 1*32, 1*32, 4);
doorkey.save(frame);frame.hotSpotY = -17;
if(MovePlatform > 0 || control==false)
{p.keyLeft = false;
p.keyRight = false;
p.keyJump = false;
p.keyFire = false;}
if((p.idle > 100 || p.keyLeft || p.keyRight || p.keyJump || p.keyFire) && MovePlatform == 0)
{p.cameraUnfreeze(true);}
p.lightType = LIGHT::NONE;
gem::trackPlayerGems(p);
gem::upgradeHealth(p);
if(p.yPos > jjWaterLevel)
{p.health = 0;}
if(p.food == 100 && jjKey[0x52] == false && startrush == false)
{p.showText("@@@@@@@@@@@@@@@@Press 'R' when you need to use Sugar Rush!", STRING::MEDIUM);
p.startSugarRush(0);
startrush = true;
readytorush = true;}
if(readytorush == true)
{p.food = 100;}
if(p.food == 100 && jjKey[0x52])
{p.startSugarRush(1400);
p.food = 0;
readytorush = false;
startrush = false;
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::SEEKERAMMO3 && p.ammo[WEAPON::SEEKER] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::RFAMMO3 && p.ammo[WEAPON::RF] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::TNTAMMO3 && p.ammo[WEAPON::TNT] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::GUN9AMMO3 && p.ammo[WEAPON::GUN9] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::SEEKERPOWERUP && p.ammo[WEAPON::SEEKER] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::RFPOWERUP && p.ammo[WEAPON::RF] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::TNTPOWERUP && p.ammo[WEAPON::TNT] < 1) {
o.state = STATE::KILL;}
}
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::GUN9POWERUP && p.ammo[WEAPON::GUN9] < 1) {
o.state = STATE::KILL;}
}
if(p.keyUp && p.xPos > 101*32 && p.yPos > 23*32 && p.yPos < 25*32 && p.xPos <105*32 && jjTriggers[3] == false) {
p.showText("@@There you go!");
jjTriggers[3] = true;
p.cameraFreeze(106*32, 3*32, true, false);
jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);
}
if(p.keyUp == true && p.xPos < 124*32 && p.xPos > 122*32 && p.yPos > 25*32) {
p.cameraFreeze(132*32, 11*32, true, false);
MovePlatform = jjGameTicks + 55 * 61;
jjTriggers[5] = true;
if(soundon==true)
{jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
soundon = false;
}
if(p.keyDown && p.xPos < 124*32 && p.xPos > 122*32 && p.yPos > 25*32) {
jjTriggers[5] = false;
MovePlatform = 0;
if(soundon==false)
{jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
soundon = true;
}
}
void onFunction0(jjPLAYER@ p) {
p.cameraUnfreeze();
MovePlatform = 0;
}
void onFunction1(jjPLAYER@ p) {
ElevatorUp = jjGameTicks + 55 * 61;
}
void onFunction2(jjPLAYER@ p) {
ElevatorUp = 0;
}
void onFunction3(jjPLAYER@ p) {
p.cameraFreeze(104*32, 2*32, true, false);
}
void onFunction4(jjPLAYER@ p) {
gem::saveGemData();
jjNxt(false, true);
}
void onFunction5(jjPLAYER@ p) {
p.showText("@@@@@@@@@@@@@@@@@@@@@@@Royal Gardens", STRING::MEDIUM);}
void onFunction6(jjPLAYER@ p) {
p.showText("@@@@@@@@@@@@@@@@@@@@@@@Great Balconies", STRING::MEDIUM);}
void onFunction7(jjPLAYER@ p) {
keypicked = false;
keytext = true;}
void onFunction8(jjPLAYER@ p) {
if(keypicked == false && keytext == false)
p.showText("@@Locked.");
keytext = true;}
void onFunction9(jjPLAYER@ p) {
if(keypicked == false && keytext2 == false)
p.showText("@@Locked... Again.");
keytext2 = true;}
void onMain() {
gem::deleteCollectedGems();
if(jjKey[9] && jjKey[0x51]) {
p.morphTo(CHAR::JAZZ, false);
}
if(jjKey[9] && jjKey[0x57]) {
p.morphTo(CHAR::SPAZ, false);
}
if(jjKey[9] && jjKey[0x45]) {
p.morphTo(CHAR::LORI, false);
}
}
bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
if(keypicked == true && (jjTriggers[1]==true || jjTriggers[7]==true || jjTriggers[8]==true || jjTriggers[2]==true))
{canvas.drawSprite(20, 585, ANIM::PICKUPS, 36, jjGameTicks>>2, -1, SPRITE::NORMAL);}
return false;
}
bool onDrawLives(jjPLAYER@ player, jjCANVAS@ screen) { return true;}
void onLevelReload() {
for (uint i = 0; i < 32; ++i)
jjTriggers[i] = SavedTriggers[i];
gem::restorePlayerGems();
jjLocalPlayers[0].lives++;
jjWaterLighting = WATERLIGHT::GLOBAL;
}
array<bool> SavedTriggers(32, false);
//Extendable Checkpoints by VioletCLM
void CheckpointWrapper(jjOBJ@ obj) {
if (obj.state == STATE::STOP) { //don't do anything anymore
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
} else if (obj.state == STATE::DEACTIVATE) { //due to death
obj.deactivate();
} else {
obj.behave(BEHAVIOR::CHECKPOINT);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
if (obj.state == STATE::DONE) { //triggered by the player hitting it
obj.state = STATE::STOP;
//save the current state of some properties
for (uint i = 0; i < 32; ++i)
SavedTriggers[i] = jjTriggers[i];
//OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
for (int i = jjObjectCount; --i > 0;) {
jjOBJ@ obj2 = jjObjects[i];
if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
obj2.state = STATE::SLEEP;
obj2.var[0] = 0;
}
}
}
}
}
jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
class Sign {
private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
private string text;
private uint widthOfText;
Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
Sign(int xTile, int yTile, const string &in t) {
xPos = xTile * 32; //Since this is a constant operation, it could strictly be performed in the draw method instead of the constructor, but this way involves fewer multiplication instructions
yPos = yTile * 32; //
text = t;
SignTextAppearance.newline = STRING::SPECIALSIGN; //Causes the drawString method to interpret instances of the \n character as signals to drop down to a new line, similar to the special effect of the @ character in the STRING::SPIN appearance.
SignTextAppearance.spacing = -2; //int jjTEXTAPPEARANCE::spacing is new in 5.2, and this particular value is equivalent to prefixing the string with "ยง2". Make sure to check out bool jjTEXTAPPEARANCE::monospace too, though it didn't end up getting used in this level.
widthOfText = jjGetStringWidth(text, STRING::SMALL, SignTextAppearance); //Used for determining how large of a dark rectangle should be drawn behind the text. A matching heightOfText value could of course be generated by counting the number of newline characters--for example, "heightOfText = text.split("\n").length * 20;"--but here the rectangles are constant height instead to limit the temptation to ramble on and on.
}
void draw(jjCANVAS@ layer, uint8 textIntensity) const { //Because this method will be called from an onDraw method, it's important to have a jjCANVAS@ passed among the arguments.
layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
}
}
const array<Sign> Signs = {
Sign(9, 16, "Good luck honey.\nBring back my daughter!"),
Sign(28, 7, "Vases might contain\nvaluable items."),
Sign(123, 2, "Merlin's ward is waiting for you\nin Royal Gardens."),
Sign(159, 26, "Since your last quest you experience some kind\nof amnesia. As a part of it you forgot how to swim..."),
};
void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
if(jjKey[0x54]){
const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
for (uint signID = 0; signID < Signs.length; ++signID)
Signs[signID].draw(layer, textIntensity);
}
}
bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
return MLLE::WeaponHook.drawAmmo(player, canvas);
}
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.