Downloads containing mo4a_3-2.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Mystery of the Four... chandie Single player 6.6 Download file

File preview

  1. const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, DefaultWeapons::Blaster(), DefaultWeapons::Blaster(), WeaponVMega::Backfire::Weapon(), null, ArcaneWeapons::FusionCannon::Weapon(), null, ArcaneWeapons::MortarLauncher::Weapon()}); ///@MLLE-Generated
  2. #include "MLLE-Include-1.5w.asc" ///@MLLE-Generated
  3. #pragma require "mo4a_3-2.j2l" ///@MLLE-Generated
  4. #include "ArcaneWeapon4.asc" ///@MLLE-Generated
  5. #pragma require "ArcaneWeapon4.asc" ///@MLLE-Generated
  6. #include "ArcaneWeapon9.asc" ///@MLLE-Generated
  7. #pragma require "ArcaneWeapon9.asc" ///@MLLE-Generated
  8. #include "WeaponVMega5.asc" ///@MLLE-Generated
  9. #pragma require "WeaponVMega5.asc" ///@MLLE-Generated
  10. #include "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  11. #pragma require "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  12. #include "Jazz1Enemies v05.asc"
  13. #include "Resize v11.asc"
  14. #include "TrueColor v13.asc"
  15. #include "HH18savegems.asc"
  16.  
  17. bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
  18.     canvas.drawString(30, 585, formatInt(exit%100, "1") + "/50", STRING::SMALL, STRING::NORMAL);
  19.     canvas.drawSprite(20, 585, ANIM::PICKUPS, 22, jjGameTicks>>2, -1, SPRITE::GEM, 6);
  20.     return false;
  21. }
  22.  
  23. bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {return true;}
  24.  
  25.  
  26. void onLevelLoad() {
  27. jjSetWaterLevel(2032, true);
  28.   jjPIXELMAP rain(32,32);
  29.   for (uint x = 0; x < rain.width; ++x) {
  30.     for (uint y = 0; y < rain.height; ++y) {
  31.       if (x == 16) { //draw in the middle of the tile, xPixel 16
  32.         if (y <= 24) rain[x,y] = 75; //if at yPixel 24 or less, use color 75
  33.         else rain[x,y] = 74; //use color 74 for yPixels 25-32
  34.       } else {
  35.         rain[x,y] = 0;
  36.       }
  37.     }
  38.   }
  39.  
  40.   jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::COMMON].firstAnim + 2];
  41.   for (uint frameID = 0; frameID < anim.frameCount; ++frameID) {
  42.     jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame + frameID];
  43.     rain.save(frame);
  44.     frame.hotSpotX = -frame.width/2;
  45.     frame.hotSpotY = -frame.height;
  46.   }
  47.  
  48.         gem::restorePlayerGems();
  49.        
  50.         jjLevelName = ("@@@@@@@@@Rebellius");
  51.         jjWaterLighting = WATERLIGHT::GLOBAL;
  52.         jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
  53.         jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
  54.  
  55.         Jazz1::MakeEnemy(OBJECT::HATTER, Jazz1::Enemies::Marbelara_Schwarzenguard, true).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::INTRO_SHOT1).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  56.         Jazz1::MakeEnemy(OBJECT::DRAGONFLY, Jazz1::Enemies::Marbelara_Drageen).SetUsesJJ2StyleDeathAnimation(true);
  57.         Jazz1::MakeEnemy(OBJECT::FLOATSUCKER, Jazz1::Enemies::Marbelara_Firebomb).SetUsesJJ2StyleDeathAnimation(true);
  58.         Jazz1::MakeEnemy(OBJECT::NORMTURTLE, Jazz1::Enemies::Dreempipes_TerrapinSwimmer).SetUsesJJ2StyleDeathAnimation(true);
  59.  
  60.         jjObjectPresets[OBJECT::BIGROCK].behavior = Cannon();
  61.         jjObjectPresets[OBJECT::BIGROCK].scriptedCollisions = true;
  62.         jjObjectPresets[OBJECT::BIGROCK].bulletHandling = HANDLING::IGNOREBULLET;
  63.  
  64.         jjObjectPresets[OBJECT::FATCHICK].behavior = Pirate2();
  65.         jjObjectPresets[OBJECT::FATCHICK].scriptedCollisions = true;
  66.         jjObjectPresets[OBJECT::FATCHICK].deactivates = false;
  67.  
  68.         jjObjectPresets[OBJECT::STOPWATCH].behavior = Gem();
  69.         jjObjectPresets[OBJECT::STOPWATCH].scriptedCollisions = true;
  70.         jjObjectPresets[OBJECT::STOPWATCH].deactivates = false;
  71.  
  72.         jjObjectPresets[OBJECT::SILVERCOIN].behavior = PlatinCoin();
  73.         jjObjectPresets[OBJECT::SILVERCOIN].scriptedCollisions = true;
  74.  
  75.         jjObjectPresets[OBJECT::FENCER].behavior = Pirate();
  76.         jjObjectPresets[OBJECT::FENCER].playerHandling = HANDLING::SPECIAL;
  77.         jjObjectPresets[OBJECT::FENCER].scriptedCollisions = true;
  78.         jjObjectPresets[OBJECT::FENCER].energy = 1;
  79.  
  80.         jjObjectPresets[OBJECT::FIREBALLBULLET].scriptedCollisions = true;             
  81.         jjObjectPresets[OBJECT::FIREBALLBULLET].behavior = CannonBall; 
  82.         jjObjectPresets[OBJECT::FIREBALLBULLET].state = STATE::ACTION;
  83.         jjObjectPresets[OBJECT::FIREBALLBULLET].playerHandling = HANDLING::PLAYERBULLET;
  84.         jjObjectPresets[OBJECT::FIREBALLBULLET].bulletHandling = HANDLING::HURTBYBULLET;
  85.  
  86.         jjObjectPresets[OBJECT::STANDMONKEY].behavior = PirateBoss;
  87.         jjObjectPresets[OBJECT::STANDMONKEY].playerHandling = HANDLING::ENEMY;
  88.         jjObjectPresets[OBJECT::STANDMONKEY].bulletHandling = HANDLING::HURTBYBULLET;
  89.         jjObjectPresets[OBJECT::STANDMONKEY].determineCurAnim(ANIM::FENCER, 0);
  90.         jjObjectPresets[OBJECT::STANDMONKEY].determineCurFrame();
  91.         jjObjectPresets[OBJECT::STANDMONKEY].energy = 100;
  92.         jjObjectPresets[OBJECT::STANDMONKEY].deactivates = false;
  93.  
  94.         jjObjectPresets[OBJECT::BLUESPRING].deactivates = false;
  95. }
  96.  
  97. int exit = 0;
  98. class Gem: jjBEHAVIORINTERFACE {
  99.         void onBehave(jjOBJ@ obj) {
  100.                 obj.behave(BEHAVIOR::PICKUP, false);
  101.                 obj.determineCurAnim(ANIM::PICKUPS, 22);
  102.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::GEM, 6);     
  103.                 ++obj.counter;
  104.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;     
  105. }
  106.  
  107.  
  108.                 bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  109.                 exit += 1;
  110.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  111.                 if(exit==50)
  112.                 {p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Treasure collected.");}
  113.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1);
  114.                 return true;
  115.         }
  116.  
  117. }
  118.  
  119. bool cointext = false;
  120. class PlatinCoin : jjBEHAVIORINTERFACE {
  121.  
  122.         void onBehave(jjOBJ@ obj) {
  123.                 obj.behave(BEHAVIOR::PICKUP, false);
  124.                 ++obj.counter;
  125.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  126.                 if(exit >= 50)
  127.                 {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -8);}
  128.                 else jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTPALSHIFT, -8);
  129. }
  130.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  131.                 if(exit < 50 && cointext == false)
  132.                 {p.showText("@@Collect the treasure first.");
  133.                 cointext = true;}
  134.                 if(exit >= 50)
  135.                 {p.coins += 1;
  136.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  137.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_COIN, 1000);}
  138.  
  139.                 return true;
  140.         }
  141. }
  142.  
  143. class Pirate : jjBEHAVIORINTERFACE {
  144.         void onBehave(jjOBJ@ obj) {
  145.  
  146.                 obj.behave(BEHAVIOR::FENCER, false);
  147.                         obj.determineCurAnim(ANIM::FENCER, 0);
  148.                         obj.determineCurFrame();
  149.                         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -24);
  150.         if(obj.energy <= 0)
  151.         {                       jjAddObject(OBJECT::STOPWATCH, obj.xPos, obj.yPos-32);}
  152.  
  153.         }
  154. bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  155.         if(play !is null && bullet is null)
  156.                 {obj.playerHandling = HANDLING::ENEMY;}
  157.         else if(bullet !is null)
  158.                         {jjAddObject(OBJECT::FATCHICK, obj.xPos, obj.yPos-32);}
  159.                
  160.         if(force == -1 || force == 1)
  161.                 {obj.playerHandling = HANDLING::ENEMY;}
  162.  
  163.         return true;
  164.         }
  165.  
  166. }
  167.  
  168. bool startrush = false;
  169. bool readytorush = false;
  170.  
  171. void onPlayer(jjPLAYER@ p) {
  172.  
  173. for (int i = 0; i < 1024; i++) { //loop through the global array jjParticles[1024]
  174.     jjPARTICLE@ particle = jjParticles[i];
  175.     if (particle.type == PARTICLE::RAIN) {
  176.       particle.xSpeed = 0; //make rain fall straight down
  177.       particle.ySpeed = p.ySpeed < 0? 10 : int(10 + p.ySpeed); //the rain speed accounts for differences in the player speed, and so won't appear to fall more slowly when the player is falling
  178.     }
  179.   }
  180.  
  181.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BOLLPLATFORM].curAnim];
  182.         anim.frameCount = 1;
  183.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  184.         jjPIXELMAP lamp(0, 34*32, 2*32, 2*32, 5);
  185.         lamp.save(frame);
  186.         frame.hotSpotX = -32;
  187.  
  188.  
  189.         if(p.food == 100 && jjKey[0x52] == false && startrush == false)
  190.                 {p.showText("@@@@@@@@@@@@@@@@Press 'R' when you need to use Sugar Rush!", STRING::MEDIUM);
  191.                 p.startSugarRush(0);
  192.                 startrush = true;
  193.                 readytorush = true;}
  194.  
  195.         if(readytorush == true)
  196.                 {p.food = 100;}
  197.  
  198.         if(p.food == 100 && jjKey[0x52])
  199.                 {p.startSugarRush(1400);
  200.                 p.food = 0;
  201.                 readytorush = false;
  202.                 startrush = false;
  203.         }
  204.  
  205.         for (int i = 1; i < jjObjectCount; i++) {
  206.         jjOBJ@ o = jjObjects[i];
  207.                 if (o.isActive && o.eventID == OBJECT::SILVERCOIN && p.coins >= 2) {
  208.                 o.state = STATE::KILL;
  209.                 }
  210.  
  211.         }
  212.  
  213.  
  214.         if(p.yPos > jjWaterLevel && p.xPos > 43*32)
  215.         {p.xPos = p.xPos - 4;}
  216.  
  217.         if(p.xPos > 186*32 && p.direction == 1 && p.xSpeed < 1)
  218.                 {p.keyJump = false;}
  219.  
  220.         if(p.coins == 2 && ((p.xPos > 177*32 && p.yPos < 23*32 && p.yPos >16*32) || (p.xPos > 187*32 && p.yPos < 34*32)))
  221.         {jjNxt("mo4a_3-3_save",false, true);
  222.         gem::saveGemData();}
  223.  
  224.         if(p.coins < 2 && ((p.xPos > 177*32 && p.yPos < 23*32 && p.yPos >16*32) || (p.xPos > 187*32 && p.yPos < 34*32)))
  225.         {p.testForCoins(2);}
  226.  
  227.         if(p.xPos < 23*32 && p.yPos <34*32 && bossdefeated == false)
  228.         {jjMusicLoad("mo4a_Umber's Sacrifice.ogg");}
  229.         if(p.xPos > 23*32 || p.yPos >34*32)
  230.         {jjMusicLoad("mo4a_Riding the Shell.ogg");
  231.         p.bossActivated = false;}      
  232.  
  233.         p.lightType = LIGHT::NONE;
  234.         gem::trackPlayerGems(p);
  235.         gem::upgradeHealth(p);
  236.         if(p.coins == 0)
  237.                 {p.coins +=1;}
  238.  
  239.         for (int i = 1; i < jjObjectCount; i++) {
  240.                 jjOBJ@ o = jjObjects[i];
  241.                 if (o.isActive && o.eventID == OBJECT::SEEKERAMMO3 && p.ammo[WEAPON::SEEKER] < 1) {
  242.                         o.state = STATE::KILL;}
  243.         }
  244.         for (int i = 1; i < jjObjectCount; i++) {
  245.                 jjOBJ@ o = jjObjects[i];
  246.                 if (o.isActive && o.eventID == OBJECT::RFAMMO3 && p.ammo[WEAPON::RF] < 1) {
  247.                         o.state = STATE::KILL;}
  248.         }
  249.         for (int i = 1; i < jjObjectCount; i++) {
  250.                 jjOBJ@ o = jjObjects[i];
  251.                 if (o.isActive && o.eventID == OBJECT::TNTAMMO3 && p.ammo[WEAPON::TNT] < 1) {
  252.                         o.state = STATE::KILL;}
  253.         }
  254.         for (int i = 1; i < jjObjectCount; i++) {
  255.                 jjOBJ@ o = jjObjects[i];
  256.                 if (o.isActive && o.eventID == OBJECT::GUN9AMMO3 && p.ammo[WEAPON::GUN9] < 1) {
  257.                         o.state = STATE::KILL;}
  258.         }
  259.         for (int i = 1; i < jjObjectCount; i++) {
  260.                 jjOBJ@ o = jjObjects[i];
  261.                 if (o.isActive && o.eventID == OBJECT::SEEKERPOWERUP && p.ammo[WEAPON::SEEKER] < 1) {
  262.                         o.state = STATE::KILL;}
  263.         }
  264.         for (int i = 1; i < jjObjectCount; i++) {
  265.                 jjOBJ@ o = jjObjects[i];
  266.                 if (o.isActive && o.eventID == OBJECT::RFPOWERUP && p.ammo[WEAPON::RF] < 1) {
  267.                         o.state = STATE::KILL;}
  268.         }
  269.         for (int i = 1; i < jjObjectCount; i++) {
  270.                 jjOBJ@ o = jjObjects[i];
  271.                 if (o.isActive && o.eventID == OBJECT::TNTPOWERUP && p.ammo[WEAPON::TNT] < 1) {
  272.                         o.state = STATE::KILL;}
  273.         }
  274.         for (int i = 1; i < jjObjectCount; i++) {
  275.                 jjOBJ@ o = jjObjects[i];
  276.                 if (o.isActive && o.eventID == OBJECT::GUN9POWERUP && p.ammo[WEAPON::GUN9] < 1) {
  277.                         o.state = STATE::KILL;}
  278.         }
  279.  
  280.  
  281. }
  282.  
  283. class Pirate2 : jjBEHAVIORINTERFACE {
  284.         void onBehave(jjOBJ@ obj) {    
  285.                 if(obj.energy <= 0) {
  286.                         obj.state = STATE::KILL;
  287.                         obj.scriptedCollisions = false;
  288.                         obj.delete();
  289.                 }
  290.                 else { 
  291.                 obj.putOnGround();
  292.                 obj.behave(BEHAVIOR::WALKINGENEMY, false);
  293.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -24);
  294.                 obj.determineCurAnim(ANIM::FENCER, 0);
  295.                 obj.determineCurFrame();
  296.                 obj.xSpeed = 5*obj.direction;
  297.                 if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1))
  298.                         {obj.direction = obj.xSpeed = -obj.xSpeed;}
  299.                 }
  300.                 if(obj.justHit==0)
  301.                         {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -24);}
  302.                 else obj.draw();
  303.  
  304.         }      
  305.        
  306. }
  307.  
  308. void onFunction3(jjPLAYER@ play) { exit = 50;}
  309.  
  310.  
  311.  
  312. void onFunction1(jjPLAYER@ play) {
  313.         if(bossdefeated == false && bossactivated == false) {
  314.         p.activateBoss();
  315.         jjTriggers[1] = true;
  316.         jjOBJ@ boss = jjObjects[p.boss];
  317.         p.boss=jjAddObject(OBJECT::STANDMONKEY, 13, 29*32);
  318.         bossactivated = true;
  319. }
  320. }
  321.  
  322. void onFunction2(jjPLAYER@ play) {
  323.         p.health = 0;
  324. }
  325.  
  326. bool bossdefeated = false, bossactivated = false;
  327. void PirateBoss(jjOBJ@ enemy) {
  328.         if(bossdefeated == true)
  329.                 {enemy.delete();}
  330.         if(enemy.energy>0 && p.xPos >20*32)
  331.         {p.cameraFreeze(6*32, 27*32, true, false);}
  332.         if(enemy.energy <= 0)
  333.         {p.cameraUnfreeze();
  334.         jjTriggers[1] = false;
  335.         bossdefeated = true;}  
  336.         switch (enemy.state) {
  337.                 case STATE::START:
  338.                         enemy.state = STATE::IDLE;
  339.                         break;
  340.                
  341.                 case STATE::IDLE:
  342.                 enemy.putOnGround(false);
  343.                                 if (jjLocalPlayers[0].xPos < enemy.xPos) enemy.direction = -1;
  344.                                 else enemy.direction = 1;
  345.                         if ((jjRandom() & 31) == 0) {
  346.                                 enemy.state = STATE::ATTACK;
  347.                                 enemy.determineCurAnim(ANIM::FENCER, 0);
  348.                                 enemy.frameID = 0;
  349.                                 enemy.counter = 0;
  350.                                 jjSample(enemy.xPos, enemy.yPos, SOUND::COMMON_SWISH8);
  351.                         } else {
  352.                                 if (++enemy.counter > 4) {
  353.                                         enemy.counter = 0;
  354.                                         if (++enemy.frameID >= 11)
  355.                                                 enemy.frameID = 0;
  356.  
  357.                                 }
  358.                         }
  359.                         break;
  360.                 case STATE::ATTACK:
  361.  
  362.                         if (++enemy.counter > 6) {
  363.                                 enemy.counter = 0;
  364.                                 if (++enemy.frameID >= 11) {
  365.                                         enemy.determineCurAnim(ANIM::FENCER, 0);
  366.                        
  367.                                         enemy.state = STATE::IDLE;
  368.                                         enemy.frameID = 0;
  369.                                 } else if (enemy.frameID >= 4 && enemy.frameID <= 36) {
  370.                                         jjOBJ@ obj = jjObjects[enemy.fireBullet(OBJECT::BLASTERBULLET)];
  371.                                         obj.behavior = BEHAVIOR::BULLET;
  372.                                         obj.determineCurAnim(ANIM::PINKPLAT, 1);
  373.                                         obj.killAnim = jjObjectPresets[OBJECT::BOUNCERBULLET].killAnim;
  374.                                         obj.playerHandling = HANDLING::ENEMYBULLET;
  375.                                         obj.bulletHandling = HANDLING::IGNOREBULLET;
  376.                                         obj.lightType = LIGHT::POINT;
  377.                                         obj.xPos = enemy.xPos+72;
  378.                                         obj.yPos = enemy.yPos-12;      
  379.                                         obj.xAcc = .12;
  380.                                         int xs = (jjRandom() & 3);
  381.                                         obj.xSpeed = 19;
  382.                                         int ys = (jjRandom() & 6);
  383.                                         obj.ySpeed = ys + 1;
  384.                                         obj.counterEnd = 155;
  385.                                 }
  386.                                 enemy.determineCurFrame();
  387.                         }
  388.                         break;
  389.                 case STATE::DEACTIVATE:
  390.                 case STATE::KILL:
  391.                         enemy.delete();
  392.                         jjAddObject(OBJECT::BLUESPRING, 1*32, 25*32);
  393.                         jjAddObject(OBJECT::FULLENERGY, 1*32, 24*32);
  394.                         break;
  395.         }
  396. if(enemy.justHit == 0)
  397. {jjDrawSpriteFromCurFrame(enemy.xPos, enemy.yPos, enemy.curFrame, 0, SPRITE::PALSHIFT, -24);}
  398. else enemy.draw();
  399.  
  400. }
  401. class Cannon : jjBEHAVIORINTERFACE {
  402.  
  403.         void onBehave(jjOBJ@ obj) {
  404.                 obj.behave(BEHAVIOR::BIGOBJECT, false);
  405.                 obj.draw();
  406.                 jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BIGROCK].curAnim];
  407.                 anim.frameCount = 1;
  408.                 jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  409.                 jjPIXELMAP rock(0, 32*32, 2*32, 2*32, 5);
  410.                 rock.save(frame);
  411.                 frame.hotSpotY = -26;
  412. }
  413.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ p, int force) {  
  414.                 if(p.charCurr!=CHAR::JAZZ)
  415.                 {p.morphTo(CHAR::JAZZ, true);}
  416.                 if (p.charCurr==CHAR::JAZZ && p.keyUp == true && p.direction == -1 && p.keyRight == false && p.keyLeft == false && p.keyFire == false && p.keyDown == false) {
  417.                         //p.yPos = p.yPos -5;
  418.                         jjObjects[obj.fireBullet(OBJECT::FIREBALLBULLET)];
  419.                         //jjAddObject(OBJECT::RFBULLET, obj.xPos, obj.yPos -20);
  420.                         jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BENZIN1, 1000);     
  421.                 }
  422.                 if(p.charCurr==CHAR::JAZZ && p.keyDown == true && p.keyLeft == false)
  423.                 {p.blink = 5;}
  424.                 return true;
  425.         }
  426.  
  427. }
  428.  
  429.         void CannonBall(jjOBJ@ bullet) {
  430.                 bullet.xPos = bullet.xPos -5;
  431.                 bullet.determineCurAnim(ANIM::PINKPLAT, 1);
  432.                 bullet.determineCurFrame();
  433.                 bullet.frameID = 19;
  434.                 ++bullet.counter;
  435.                 bullet.counter += 4;
  436.                 int xs = (jjRandom() & 8);
  437.                 bullet.xPos = bullet.xPos - xs -28;
  438.                 int ys = (jjRandom() & 12);
  439.                 bullet.yPos = bullet.yPos - ys -13;
  440.                  if (bullet.counter >200) {
  441.                         bullet.delete();
  442.                         int explosionID = jjAddObject(OBJECT::BLASTERBULLET, bullet.xPos, bullet.yPos, bullet.creator, CREATOR::OBJECT);
  443.                         jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 4, true);
  444.                         jjObjects[explosionID].state = STATE::EXPLODE;
  445.                         }
  446.                 bullet.draw();
  447.  
  448.         }
  449.  
  450.  
  451.  
  452. void onFunction10(jjPLAYER@ p){
  453. if(p.gems[GEM::PURPLE] == 50) {
  454.         p.showText("@@@@@You made it!");}
  455. if(p.gems[GEM::PURPLE] < 50) {
  456.         p.showText("@@@@@@@Kill the pirates, collect the treasure@and come back here!");}
  457.  
  458. }
  459.  
  460.  
  461. void onMain() {
  462. gem::deleteCollectedGems();
  463.  
  464. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BANANA].curAnim];
  465.         anim.frameCount = 1;
  466.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  467.         jjPIXELMAP pgem(0, 37*32, 2*32, 2*32, 5);
  468.         pgem.save(frame);
  469.         frame.hotSpotX = -32;
  470.  
  471. if(jjKey[9] && jjKey[0x51]) {
  472. p.morphTo(CHAR::JAZZ, false);
  473. }
  474. if(jjKey[9] && jjKey[0x57]) {
  475. p.morphTo(CHAR::SPAZ, false);
  476. }
  477. if(jjKey[9] && jjKey[0x45]) {
  478. p.morphTo(CHAR::LORI, false);
  479. }
  480. }
  481.  
  482. void onLevelReload()  {
  483.         if(bossdefeated == true)
  484.                 {jjAddObject(OBJECT::BLUESPRING, 1*32, 25*32);}
  485.         gem::restorePlayerGems();
  486.         jjLocalPlayers[0].lives++;
  487.         jjSetWaterLevel(2027, true);
  488.         jjWaterLighting = WATERLIGHT::GLOBAL;
  489.         exit = 0;
  490.         for (uint i = 0; i < 32; ++i)
  491.                 jjTriggers[i] = SavedTriggers[i];
  492. }
  493.  
  494. array<bool> SavedTriggers(32, false);
  495. //Extendable Checkpoints by VioletCLM
  496. void CheckpointWrapper(jjOBJ@ obj) {
  497.   if (obj.state == STATE::STOP) {
  498.     jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  499.   } else if (obj.state == STATE::DEACTIVATE) { //due to death
  500.     obj.deactivate();
  501.   } else {
  502.     obj.behave(BEHAVIOR::CHECKPOINT);
  503.         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  504.     if (obj.state == STATE::DONE) { //triggered by the player hitting it
  505.       obj.state = STATE::STOP;
  506.       //save the current state of some properties
  507.       for (uint i = 0; i < 32; ++i)
  508.         SavedTriggers[i] = jjTriggers[i];
  509.  
  510.  
  511.  
  512.       //OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
  513.       for (int i = jjObjectCount; --i > 0;) {
  514.         jjOBJ@ obj2 = jjObjects[i];
  515.         if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
  516.           obj2.state = STATE::SLEEP;
  517.           obj2.var[0] = 0;
  518.         }
  519.       }
  520.     }
  521.   }
  522. }
  523.  
  524. jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
  525. class Sign {
  526.         private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
  527.         private string text;
  528.         private uint widthOfText;
  529.         Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
  530.         Sign(int xTile, int yTile, const string &in t) {
  531.                 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
  532.                 yPos = yTile * 32; //
  533.                 text = t;
  534.                 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.
  535.                 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.
  536.                 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.
  537.         }
  538.         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.
  539.                 layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
  540.                 layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
  541.         }
  542. }
  543. const array<Sign> Signs = {
  544.         Sign(115, 52, "The ship's under attack\nby the pirate turtles!"),
  545.         Sign(91, 52, "Pirates have looted our treasure.\nPlease help us!"),
  546.         Sign(180, 21, "We'll be visiting Poseidon once you kill\nthe pirates and save our gems."),
  547.         Sign(138, 59, "Rumours say our lost leader Thrasymakhos is\nliving underwater, working on an evil plan!"),
  548.  
  549. };
  550.  
  551. void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
  552.         if(jjKey[0x54] && exit <50){
  553.         const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
  554.         for (uint signID = 0; signID < Signs.length; ++signID)
  555.                 Signs[signID].draw(layer, textIntensity);
  556. }
  557. }
  558. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  559.         return MLLE::WeaponHook.drawAmmo(player, canvas);
  560. }
  561.