Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Mystery of the Four... | chandie | Single player | 6.6 |
const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, SzmolWeaponPack::MeleeSword::Weapon(), DefaultWeapons::Blaster(), WeaponVMega::Backfire::Weapon(), null, DefaultWeapons::Blaster(), null, ArcaneWeapons::MortarLauncher::Weapon()}); ///@MLLE-Generated
#include "MLLE-Include-1.5w.asc" ///@MLLE-Generated
#pragma require "mo4a_2-3-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "mo4a_2-3.j2l" ///@MLLE-Generated
#include "ArcaneWeapon4.asc" ///@MLLE-Generated
#pragma require "ArcaneWeapon4.asc" ///@MLLE-Generated
#include "WeaponVMega5.asc" ///@MLLE-Generated
#pragma require "WeaponVMega5.asc" ///@MLLE-Generated
#include "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
#pragma require "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
#include "meleeSword.asc" ///@MLLE-Generated
#pragma require "meleeSword.asc" ///@MLLE-Generated
#include "Jazz1Enemies v05.asc"
#include "Resize v11.asc"
#include "TrueColor v13.asc"
int CountlessDoubleJumps = 0;
void onLevelLoad() {
jjSetWaterGradient(0, 10, 10, 0, 20, 20);
jjSetWaterLevel(2020, true);
jjWaterLighting = WATERLIGHT::GLOBAL;
gem::restorePlayerGems();
jjLevelName = ("@@@@@@@@@Castle");
jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
jjObjectPresets[OBJECT::SONICPLATFORM].behavior = SpikeBump();
jjObjectPresets[OBJECT::SONICPLATFORM].deactivates = false;
jjObjectPresets[OBJECT::SILVERCOIN].behavior = PlatinCoin();
jjObjectPresets[OBJECT::SILVERCOIN].scriptedCollisions = true;
jjObjectPresets[OBJECT::MOTH].behavior = Magic;
jjObjectPresets[OBJECT::FRUITPLATFORM].behavior = HeavyObjectHanging();
jjObjectPresets[OBJECT::BIGROCK].behavior = HeavyObjectFallen;
jjObjectPresets[OBJECT::BIGROCK].state = STATE::FALL;
jjObjectPresets[OBJECT::FENCER].behavior = Thief();
jjObjectPresets[OBJECT::FENCER].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::FENCER].scriptedCollisions = true;
jjObjectPresets[OBJECT::FENCER].energy=1;
jjObjectPresets[OBJECT::FATCHICK].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::FATCHICK].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::FATCHICK].behavior = Thief2;
jjObjectPresets[OBJECT::FATCHICK].scriptedCollisions = true;
jjObjectPresets[OBJECT::FATCHICK].energy=2;
jjObjectPresets[OBJECT::WEENIE].behavior = Lamp();
jjObjectPresets[OBJECT::WEENIE].scriptedCollisions = true;
jjObjectPresets[OBJECT::FREEZEENEMIES].behavior = Key();
jjObjectPresets[OBJECT::FREEZEENEMIES].scriptedCollisions = true;
jjObjectPresets[OBJECT::APPLE].behavior = Carpet();
jjObjectPresets[OBJECT::APPLE].scriptedCollisions = true;
jjObjectPresets[OBJECT::FASTFEET].behavior = CountlessJumps();
jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::GEMBARREL].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP vase(0, 6*32, 1*32, 1*32, 4);
vase.save(frame);
}
class Carpet : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP, true);
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::APPLE].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP vase(0, 14*32, 2*32, 1*32, 4);
vase.save(frame);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
}
}
class Thief : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::FENCER, false);
obj.determineCurAnim(ANIM::FENCER, 0);
obj.determineCurFrame();
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 48);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if(play !is null && bullet is null)
{obj.playerHandling = HANDLING::ENEMY;}
else if(bullet !is null)
{jjAddObject(OBJECT::FATCHICK, obj.xPos, obj.yPos-32);}
if(force == -1 || force == 1)
{obj.playerHandling = HANDLING::ENEMY;}
return true;
}
}
void Thief2(jjOBJ@ obj) {
obj.putOnGround();
obj.behave(BEHAVIOR::WALKINGENEMY, false);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 48);
obj.determineCurAnim(ANIM::FENCER, 0);
obj.determineCurFrame();
obj.xSpeed = 5*obj.direction;
if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1))
{obj.direction = obj.xSpeed = -obj.xSpeed;}
if(obj.justHit==0)
{jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 48);}
else obj.draw();
}
int spring = 0;
class SpikeBump : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
switch (obj.state) {
case STATE::START:
obj.determineCurFrame();
obj.direction = obj.xSpeed = 2;
obj.playerHandling = HANDLING::SPECIAL;
obj.beSolid();
obj.state = STATE::FLY;
case STATE::FLY:
obj.yPos = jjSin(obj.counter*3 + 5)*2 + obj.yOrg;
obj.beSolid();
obj.deactivates = false;
if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1)) {
obj.direction = obj.xSpeed = -obj.xSpeed;
}
if(obj.xPos > p.xPos + 64 || obj.xPos < p.xPos - 64 || obj.yPos > p.yPos + 64 || obj.yPos < p.yPos - 64)
{obj.determineCurAnim(ANIM::BOLLPLAT, 0);
jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, 1, SPRITE::PALSHIFT, -8);
obj.determineCurFrame();}
else {jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, 1, SPRITE::PALSHIFT, -24);}
break;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if(bullet is null && play !is null && (force == -1 || force == 1))
{obj.behave(BEHAVIOR::PLATFORM, false);
obj.determineCurAnim(ANIM::BOLLPLAT, 0);
jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 2, 1, SPRITE::PALSHIFT, -24);
obj.determineCurFrame();
obj.frameID = obj.counter/5;
obj.beSolid();
spring = jjGameTicks + 1*61;
obj.determineCurFrame();
jjSample(obj.xPos, obj.yPos, SOUND::PINBALL_BELL, 1000);}
if(play !is null && force == 0)
{play.hurt();
obj.determineCurAnim(ANIM::SPIKEBOLL, 0);
obj.determineCurFrame();
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_METALHIT, 1000);}
if(play is null && force > -2) {
obj.determineCurAnim(ANIM::BOLLPLAT, 0);
obj.determineCurFrame();}
return true;
}
}
class HeavyObjectHanging : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::FRUITPLATFORM].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP rope(0, 7*32, 2*32, 4*32, 4);
rope.save(frame);
frame.hotSpotX = -30;
obj.behave(BEHAVIOR::PLATFORM);
if(obj.xPos > p.xPos+64 || obj.xPos < p.xPos -64)
{obj.scriptedCollisions = false;}
else obj.scriptedCollisions = true;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if(play !is null && bullet !is null && bullet.var[3]==WEAPON::ICE)
{obj.delete();
jjAddObject(OBJECT::BIGROCK, 162*32, 51*32);}
else if(p !is null && bullet !is null)
{obj.scriptedCollisions = false;
p.showText("@@Clever! But maybe something sharper...");}
return true;
}
}
void onLevelReload() {
gem::restorePlayerGems();
jjLocalPlayers[0].lives++;
jjSetWaterGradient(0, 10, 10, 0, 20, 20);
jjSetWaterLevel(2020, true);
jjWaterLighting = WATERLIGHT::GLOBAL;
p.jumpStrength = -10;
for (uint i = 0; i < 32; ++i)
jjTriggers[i] = SavedTriggers[i];
}
void HeavyObjectFallen(jjOBJ@ obj) {
obj.behave(BEHAVIOR::BIGOBJECT);
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BIGROCK].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP rope(0, 11*32, 4*32, 2*32, 4);
rope.save(frame);
if(obj.yPos >= 55*32)
{jjTriggers[0]=true;
jjAddObject(OBJECT::ELECTROBULLET, 162*32, 56*32);
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.counter = 0;
if(obj.behavior == BEHAVIOR::EXPLOSION2 && obj.counter > 10)
{obj.delete();}
}
}
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);
}
}
int killWitch = 0;
class RedPotion : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.determineCurFrame();
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::PALSHIFT, -40);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
play.jumpStrength = -10;
jjCharacters[CHAR::JAZZ].groundJump=GROUND::JAZZ;
jjCharacters[CHAR::SPAZ].groundJump=GROUND::SPAZ;
jjCharacters[CHAR::LORI].groundJump=GROUND::LORI;
jjSample(obj.xPos, obj.yPos, SOUND::WITCH_MAGIC, 3000);
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_DRINKSPAZZ2, 1000);
obj.frameID = 0;
killWitch = 1;
obj.behavior = BEHAVIOR::EXPLOSION2;
return true;
}
}
class CountlessJumps : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP, false);
obj.determineCurAnim(ANIM::PICKUPS, 33);
++obj.counter;
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 16);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
play.timerStart(1500);
p.morphTo(CHAR::SPAZ);
CountlessDoubleJumps = jjGameTicks + 25 * 61;
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.frameID = 0;
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
return true;
}
}
bool textdisplayed = false, rubtextdisplayed = false, swimtext = false, lockdisplay = false;
void onFunction0(jjPLAYER@ p) {
if(jjTriggers[4]==false && lockdisplay == false)
{p.showText("@@Locked.");
lockdisplay = true;}
}
void onFunction1(jjPLAYER@ p) {
if(jjTriggers[17]==false && textdisplayed == false)
{p.showText("@@Place all 4 coloured stones to the@alcoves above to unlock the gate.");
textdisplayed = true;}
}
void Magic(jjOBJ@ obj) {
obj.behave(BEHAVIOR::MOTH,false);
jjPARTICLE@ particle = jjAddParticle(PARTICLE::SPARK);
particle.xPos = obj.xPos;
particle.yPos = obj.yPos;
}
class Lamp : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.lightType = LIGHT::LASER;
obj.light = 10;
obj.deactivates = false;
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::WEENIE].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP lamp(0, 5*32, 2*32, 1*32, 4);
lamp.save(frame);
frame.hotSpotY = -17;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
if(jjTriggers[13]==false)
{jjAddObject(OBJECT::MOTH, obj.xPos, obj.yPos);
if(rubtextdisplayed == false)
{p.showText("@@@@@@@@@@@Press UP to rub.");
rubtextdisplayed = true;}
if(p.keyUp==true)
{p.warpToID(0);
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_HARP1, 1000);
}
}
if (jjTriggers[13]==true && swimtext == false)
{p.showText("@@I really feel like I can swim.");
swimtext = true;}
return true;
}
}
bool keylock = false;
class Key: jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(jjTriggers[4] == 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, 8);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
jjTriggers[4] = true;
obj.behavior = BEHAVIOR::EXPLOSION2;
p.cameraFreeze(231*32, 54*32, true, true);
keylock= true;
control = false;
jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
return true;
}
}
bool startrush = false, readytorush = false, control = true, coin =false;
void onPlayer(jjPLAYER@ p) {
if(control==false)
{p.keyLeft = false;
p.keyRight = false;
p.keyDown = false;}
if(p.xPos < 240*32) {
if(p.idle > 100)
{p.cameraUnfreeze(true);
control=true;}
else if ((p.idle > 5 && (p.keyLeft || p.keyRight || p.keyJump || p.keyFire)) || (p.curAnim - jjAnimSets[p.setID].firstAnim == RABBIT::LEDGEWIGGLE))
{p.cameraUnfreeze(true);
control=true;}
}
if(coin==false && jjTriggers[5] == true && jjTriggers[7] == true && jjTriggers[8] == true && jjTriggers[15] == true)
{p.cameraFreeze(107*32, 58*32,true, false);
p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Coin unlocked.");
coin = true;}
gem::trackPlayerGems(p);
gem::upgradeHealth(p);
p.lightType = LIGHT::NONE;
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BURGER].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP stone(0, 13*32, 1*32, 1*32, 4);
stone.save(frame);
frame.hotSpotY = -17;
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::SILVERCOIN && p.coins >= 3) {
o.state = STATE::KILL;
}
}
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;
}
if(p.xPos > 17*32 && p.xPos <20*32 && p.yPos > 58*32){
if(p.coins < 3)
p.testForCoins(3);
else {
jjNxt(false, true);
gem::saveGemData();}
}
exit = 0;
if(jjTriggers[5] == true)
{exit += 1;}
if(jjTriggers[7] == true)
{exit += 1;}
if(jjTriggers[8] == true)
{exit += 1;}
if(jjTriggers[15] == true)
{exit += 1;}
if(p.xPos < 158*32 && p.xPos > 155*32 && p.yPos > 42*32 && p.yPos <44*32 && jjTriggers[5] == false)
{jjTriggers[5] = true;
exit += 1;
jjSample(p.xPos, p.yPos, SOUND::COMMON_PICKUP1, 1000);}
if(p.xPos < 164 *32 && p.xPos > 161*32 && p.yPos > 60*32 && p.yPos <62*32 && jjTriggers[7] == false)
{jjTriggers[7] = true;
exit += 1;
jjSample(p.xPos, p.yPos, SOUND::COMMON_PICKUP1, 1000);}
if(p.xPos < 236 *32 && p.xPos > 233*32 && p.yPos > 13*32 && p.yPos <15*32 && jjTriggers[8] == false)
{jjTriggers[8] = true;
exit += 1;
jjSample(p.xPos, p.yPos, SOUND::COMMON_PICKUP1, 1000);}
if(p.xPos < 64 *32 && p.xPos > 61*32 && p.yPos > 4*32 && p.yPos <6*32 && jjTriggers[15] == false)
{jjTriggers[15] = true;
exit += 1;
jjSample(p.xPos, p.yPos, SOUND::COMMON_PICKUP1, 1000);}
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(spring > jjGameTicks)
{p.ySpeed = -10;}
if(jjTriggers[5]==true && jjTriggers[7]==true && jjTriggers[8]==true && jjTriggers[15]==true)
{jjTriggers[17]=true;}
p.invisibility = false;
if(p.keyFire && p.currWeapon == WEAPON::ICE)
{p.invisibility = true;
jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::QUIT, p.curFrame, p.direction, SPRITE::PLAYER);
}
if(p.xPos > 256*32){
jjTriggers[13]=true;
p.idle = 100;
p.cameraFreeze(261*32, 52*32, true, true);
p.lighting = 1;
p.noFire = true;
if(p.keyJump || p.keyFire)
{p.warpToID(5);}
}
if(p.coins == 0)
{p.coins += 2;}
MLLE::WeaponHook.processPlayer(p);
if(p.jumpStrength==-2){
p.keyUp = false;
}
if (CountlessDoubleJumps > jjGameTicks && p.keyJump) {
p.doubleJumpCount = 0;}
if (p.health == 0){
CountlessDoubleJumps = 0;
}
if (p.yPos > jjWaterLevel && jjTriggers[13]==false) {
p.health = 0;
}
}
void onFunction2(jjPLAYER@ play) {
p.cameraUnfreeze();
p.noFire = false;}
void onFunction3(jjPLAYER@ play) {
CountlessDoubleJumps = 0;
play.timerStop();}
void onFunction4(jjPLAYER@ play) {
if(jjTriggers[13]==false)
{p.showText("@@Learn how to swim first.");}
}
void onFunction6(jjPLAYER@ play) {
keylock = false;}
class PlatinCoin : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if(p.coins >= 3)
{obj.delete();}
obj.behave(BEHAVIOR::PICKUP, false);
++obj.counter;
obj.deactivates = false;
if(obj.xPos > 108*32)
{obj.xPos = obj.xPos - 8;}
obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -8);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
p.coins += 1;
obj.behavior = BEHAVIOR::EXPLOSION2;
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_COIN, 1000);
return true;
}
}
bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
return MLLE::WeaponHook.drawAmmo(player, canvas);
}
int exit = 0;
bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
if(p.xPos < 256*32){
canvas.drawString(30, 585, formatInt(exit%5, "1") + "/4", STRING::SMALL, STRING::NORMAL);
canvas.drawSprite(20, 585, ANIM::PICKUPS, 11, jjGameTicks>>2, -1, SPRITE::NORMAL);
if(keylock == true && jjTriggers[4]==true)
{canvas.drawSprite(90, 580, ANIM::MENU,5, jjGameTicks>>2, -1, SPRITE::PALSHIFT, 8);}
return false;}
else return true;
}
bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) { return true;}
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(58, 55, "The 40 Thieves killed the Sultan.\nThey're still here, looking for something."),
Sign(92, 51, "The Sultan is murdered, but his crown's\nstill lingering in the throne room."),
Sign(250, 56, "YOU: Hey what's going on?\nGENIE: Grand your three wishes,\nI shall make them come true!\nYOU: Hmm...I want Devan Shell captured.\nGENIE: No Devan Shell exist in this world.\nYOU: B-but...\nGEENIE: Grant your second wish."),
Sign(260, 56, "YOU:Then I'd like to locate the second Time Freezer.\nIt does exist in this timeline, right?\nGENIE: Look for it in the Magical Cave.\nYOU: Hey! Won't you bring it here?\nGENIE:You said locate, stranger. Grand your last wish!\nYOU:Oh well. At least you could teach me how to swim.\n\nHit |||||FIRE |to learn how to swim."),
Sign(202, 12, "Thieves are looking for the magic lamp.\nThankfully I am good at hiding stuff."),
};
void onDrawLayer1(jjPLAYER@, jjCANVAS@ layer) {
if(jjKey[0x54] || p.xPos > 256*32){
const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
for (uint signID = 0; signID < Signs.length; ++signID)
Signs[signID].draw(layer, textIntensity);
}
}
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;
}
}
}
}
}
//HH18.savegems.asc
// Had to copy the contents in here so that I could return DrawScore true during the cutscene.
namespace gem {
int gemsCollected, nextHealth, currAmount;
int maxHealth() {
return ((jjMaxHealth+1) - (jjDifficulty < 3? 5:3));
}
array<int> gemTotals(4);
bool restoreGems;
bool draw = true;
void upgradeHealth(jjPLAYER@ play) { //onPlayer
switch (maxHealth()) {
case 1: currAmount = 100; break;
case 2: currAmount = 275; break;
case 3: currAmount = 450; break;
case 4: currAmount = 625; break;
case 5: currAmount = 800; break;
}
if (gemsCollected >= currAmount && nextHealth != maxHealth() && maxHealth() < 6) {
jjChat("/smhealth " + (jjMaxHealth + 1));
for (int i = 0; i < 8; ++i) {
jjAlert("");
}
nextHealth = jjMaxHealth;
if (jjGameTicks > 7) {
jjSample(play.xPos, play.yPos, SOUND::COMMON_HARP1, 0, 0);
jjAlert("||||By the power of gems, your maximum health is increased!", false, STRING::MEDIUM);
if (maxHealth() == 6) jjAlert("|||Congratulations, your health is maximised!", false, STRING::MEDIUM);
}
}
}
void trackPlayerGems(jjPLAYER@ play) { //onPlayer
if (!restoreGems) {
gemTotals[0] = play.gems[GEM::RED];
gemTotals[1] = play.gems[GEM::GREEN] * 5;
gemTotals[2] = play.gems[GEM::BLUE] * 10;
gemTotals[3] = play.gems[GEM::PURPLE] * 20;
gemsCollected = gemTotals[0] + gemTotals[1] + gemTotals[2] + gemTotals[3];
} else {
play.gems[GEM::RED] = jjGameTicks > 1? gemTotals[0] : play.lives;
play.gems[GEM::GREEN] = gemTotals[1] / 5;
play.gems[GEM::BLUE] = gemTotals[2] / 10;
play.gems[GEM::PURPLE] = gemTotals[3] / 20;
restoreGems = false;
}
}
void restorePlayerGems() { //onLevelLoad and onLevelReload
restoreGems = true;
}
void saveGemData() { //this needs to go in an AS function that also acts as the level exit
jjLocalPlayers[0].lives = gemsCollected;
}
void deleteCollectedGems() {
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ obj = jjObjects[i];
int playerID = obj.findNearestPlayer(200000);
jjPLAYER@ play = jjPlayers[playerID];
if (playerID > -1 &&
(obj.eventID == OBJECT::REDGEM ||
obj.eventID == OBJECT::GREENGEM ||
obj.eventID == OBJECT::BLUEGEM ||
obj.eventID == OBJECT::PURPLEGEM ||
obj.eventID == OBJECT::RECTREDGEM ||
obj.eventID == OBJECT::RECTGREENGEM ||
obj.eventID == OBJECT::RECTBLUEGEM)) {
if (obj.creatorType == CREATOR::LEVEL) {
if (play.doesCollide(obj, true)) {
jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
}
} else {
if (obj.creatorID == 0 && obj.state != STATE::FLOATFALL) {
obj.playerHandling = HANDLING::PARTICLE;
obj.delete();
}
}
}
if (obj.eventID == OBJECT::GEMBARREL || obj.eventID == OBJECT::GEMCRATE) {
if (obj.state == STATE::EXPLODE) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
}
if (obj.eventID == OBJECT::GEMRING) {
if (obj.state == STATE::HIT) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
}
if (obj.eventID == OBJECT::SUPERGEM) {
if (obj.state == STATE::ACTION) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
}
if (obj.eventID == OBJECT::BOMBCRATE || obj.eventID == OBJECT::ONEUPCRATE) {
if (obj.state == STATE::FALL && (obj.var[0] == OBJECT::REDGEM ||
obj.var[0] == OBJECT::GREENGEM ||
obj.var[0] == OBJECT::BLUEGEM ||
obj.var[0] == OBJECT::PURPLEGEM ||
obj.var[0] == OBJECT::RECTREDGEM ||
obj.var[0] == OBJECT::RECTGREENGEM ||
obj.var[0] == OBJECT::RECTBLUEGEM)) {
jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
}
}
}
}
}
bool onCheat(string &in cheat) {
if (cheat == "jjnxt" || cheat == "jjnext") {
gem::saveGemData();
jjNxt(true, true);
} else if (cheat == "jjgems") {
jjLocalPlayers[0].gems[GEM::RED] = jjLocalPlayers[0].gems[GEM::RED] + 100;
} else
return false;
jjAlert(cheat, false, STRING::MEDIUM);
return true;
}
bool onDrawScore(jjPLAYER@ play, jjCANVAS@ canvas) {
if (gem::draw && p.xPos < 256*32) {
canvas.drawSprite(20, 42, ANIM::PICKUPS, 22, jjGameTicks>>2, 0, SPRITE::GEM, 0);
canvas.drawString(36, 42, "x " + gem::gemsCollected, STRING::MEDIUM, STRING::NORMAL);
if (gem::maxHealth() < 6) {
canvas.drawString(8, 70, "|" + gem::currAmount + " |||||for upgrade", STRING::SMALL, STRING::NORMAL);
} else {
canvas.drawString(8, 70, "||||Max!", STRING::SMALL, STRING::NORMAL);
}
return false;}
else return true;
}
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.