Downloads containing mo4a_3-1_revisited1.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, ArcaneWeapons::FusionCannon::Weapon(), 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-1_revisited1-MLLE-Data-1.j2l" ///@MLLE-Generated
  4. #pragma require "mo4a_3-1_revisited1.j2l" ///@MLLE-Generated
  5. #include "ArcaneWeapon4.asc" ///@MLLE-Generated
  6. #pragma require "ArcaneWeapon4.asc" ///@MLLE-Generated
  7. #include "WeaponVMega5.asc" ///@MLLE-Generated
  8. #pragma require "WeaponVMega5.asc" ///@MLLE-Generated
  9. #include "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  10. #pragma require "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  11. #include "ArcaneWeapon9.asc" ///@MLLE-Generated
  12. #pragma require "ArcaneWeapon9.asc" ///@MLLE-Generated
  13. #include "Jazz1Enemies v05.asc"
  14. #include "Resize v11.asc"
  15. #include "TrueColor v13.asc"
  16. #include "HH18savegems.asc"
  17.  
  18. bool pass = false;
  19.  
  20. bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
  21.  
  22. if(jjTriggers[10]==true)
  23.     {canvas.drawSprite(100, 581, ANIM::PICKUPS,80, jjGameTicks>>2, 1, SPRITE::NORMAL);}
  24.  
  25. if(pass==false)
  26.     {canvas.drawSprite(100, 585, ANIM::PICKUPS, 0, jjGameTicks>>2, 1, SPRITE::NORMAL);}
  27.     canvas.drawSprite(20, 585, ANIM::PICKUPS, 84, jjGameTicks>>2, -1, SPRITE::PALSHIFT, -8);
  28.     canvas.drawString(30, 585, formatInt(player.coins%4, "1") + "/3", STRING::SMALL, STRING::NORMAL);
  29.     return false;
  30. }
  31.  
  32. bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {return true;}
  33.  
  34.  
  35. void onLevelLoad() {
  36.         gem::restorePlayerGems();
  37.         jjLevelName = ("@@@@@@@@@Central Area");
  38.         jjWaterLighting = WATERLIGHT::GLOBAL;
  39.         jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
  40.         jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
  41.  
  42.         Jazz1::MakeEnemy(OBJECT::HATTER, Jazz1::Enemies::Marbelara_Schwarzenguard, true).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::INTRO_SHOT1).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  43.         Jazz1::MakeEnemy(OBJECT::DRAGONFLY, Jazz1::Enemies::Marbelara_Drageen).SetUsesJJ2StyleDeathAnimation(true);
  44.         Jazz1::MakeEnemy(OBJECT::FLOATSUCKER, Jazz1::Enemies::Marbelara_Firebomb).SetUsesJJ2StyleDeathAnimation(true);
  45.         Jazz1::MakeEnemy(OBJECT::NORMTURTLE, Jazz1::Enemies::Dreempipes_TerrapinSwimmer).SetUsesJJ2StyleDeathAnimation(true);
  46.         Jazz1::MakeEnemy(OBJECT::SUCKER, Jazz1::Enemies::Megairbase_Doofusguard).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::INTRO_SHOTGRN).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  47.  
  48.         jjObjectPresets[OBJECT::EVA].behavior = TimeMachine;
  49.         jjObjectPresets[OBJECT::EVA].determineCurAnim(ANIM::FLAG, 1);
  50.         jjObjectPresets[OBJECT::EVA].putOnGround(false);
  51.         jjObjectPresets[OBJECT::EVA].scriptedCollisions = true;
  52.         jjANIMATION@ tmAnim = jjAnimations[jjObjectPresets[OBJECT::EVA].curAnim];
  53.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  54.                 jjAnimFrames[tmAnim.firstFrame + i].coldSpotY = -44;
  55.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  56.                 jjAnimFrames[tmAnim.firstFrame + i].hotSpotY = -64;
  57.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  58.                 jjAnimFrames[tmAnim.firstFrame + i].hotSpotX = -54;
  59.  
  60.         jjObjectPresets[OBJECT::AIRBOARD].behavior = Key();
  61.         jjObjectPresets[OBJECT::AIRBOARD].scriptedCollisions = true;
  62.  
  63.         jjObjectPresets[OBJECT::SANDWICH].behavior = Key2();
  64.         jjObjectPresets[OBJECT::SANDWICH].scriptedCollisions = true;
  65.         jjObjectPresets[OBJECT::SANDWICH].deactivates = false;
  66.  
  67.         jjObjectPresets[OBJECT::WEENIE].behavior = RedSphere();
  68.         jjObjectPresets[OBJECT::WEENIE].scriptedCollisions = true;
  69.         jjObjectPresets[OBJECT::CHICKENLEG].behavior = BlueSphere();
  70.         jjObjectPresets[OBJECT::CHICKENLEG].scriptedCollisions = true;
  71.         jjObjectPresets[OBJECT::BURGER].behavior = YellowSphere();
  72.         jjObjectPresets[OBJECT::BURGER].scriptedCollisions = true;
  73.         jjObjectPresets[OBJECT::HAM].behavior = GreenSphere();
  74.         jjObjectPresets[OBJECT::HAM].scriptedCollisions = true;
  75.         jjObjectPresets[OBJECT::FRIES].behavior = PurpleSphere();
  76.         jjObjectPresets[OBJECT::FRIES].scriptedCollisions = true;
  77.  
  78.         jjObjectPresets[OBJECT::ICEAMMO15].behavior = FCannon();
  79.         jjObjectPresets[OBJECT::ICEAMMO15].scriptedCollisions = true;
  80.         jjObjectPresets[OBJECT::ICEAMMO15].playerHandling = HANDLING::SPECIAL;
  81.  
  82.         jjObjectPresets[OBJECT::TNTAMMO3].deactivates = false;
  83.  
  84.         jjObjectPresets[OBJECT::STOPWATCH].behavior = Fastrun();
  85.         jjObjectPresets[OBJECT::STOPWATCH].scriptedCollisions = true;
  86.  
  87.         jjObjectPresets[OBJECT::BUTTERFLY].behavior = ButterThief();
  88.         jjObjectPresets[OBJECT::BUTTERFLY].scriptedCollisions = true;
  89.         jjObjectPresets[OBJECT::BUTTERFLY].playerHandling = HANDLING::SPECIAL;
  90.         jjObjectPresets[OBJECT::BUTTERFLY].energy = 10;
  91.  
  92.         jjObjectPresets[OBJECT::BEEBOY].behavior = Tree;
  93.         jjObjectPresets[OBJECT::BEEBOY].scriptedCollisions = true;
  94.         jjObjectPresets[OBJECT::BEEBOY].bulletHandling = HANDLING::IGNOREBULLET;
  95.         jjObjectPresets[OBJECT::BEEBOY].playerHandling = HANDLING::ENEMY;
  96.  
  97.         jjObjectPresets[OBJECT::GOLDCOIN].behavior = Coin();
  98.         jjObjectPresets[OBJECT::GOLDCOIN].scriptedCollisions = true;
  99.         jjPIXELMAP pole(0, 26*32, 1*32, 3*32, 5);
  100.         jjANIMFRAME@ frame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::CARROTPOLE].firstAnim].firstFrame];
  101.         pole.save(frame);
  102.         frame.hotSpotX = -frame.width/2;
  103.         frame.hotSpotY = -frame.height;
  104.  
  105.         jjObjectPresets[OBJECT::FLYCARROT].determineCurAnim(ANIM::PLUS_WARP, 0);
  106.         jjObjectPresets[OBJECT::FLYCARROT].behavior = Bonus;
  107.         jjObjectPresets[OBJECT::FLYCARROT].scriptedCollisions = true;
  108.         jjANIMATION@ BAnim = jjAnimations[jjObjectPresets[OBJECT::FLYCARROT].curAnim];
  109.         for (uint i = 0; i < BAnim.frameCount; ++i)
  110.                 jjAnimFrames[BAnim.firstFrame + i].hotSpotY = -85;
  111.         for (uint i = 0; i < BAnim.frameCount; ++i)
  112.                 jjAnimFrames[BAnim.firstFrame + i].hotSpotX = 20;
  113.  
  114.         jjObjectPresets[OBJECT::INVINCIBILITY].determineCurAnim(ANIM::PLUS_WARP, 1);
  115.         jjObjectPresets[OBJECT::INVINCIBILITY].behavior = Bonuseye;
  116.         jjObjectPresets[OBJECT::INVINCIBILITY].scriptedCollisions = true;
  117.         jjObjectPresets[OBJECT::INVINCIBILITY].bulletHandling = HANDLING::IGNOREBULLET;
  118.         jjObjectPresets[OBJECT::INVINCIBILITY].playerHandling = HANDLING::PLAYERBULLET;
  119.         jjANIMATION@ BeAnim = jjAnimations[jjObjectPresets[OBJECT::INVINCIBILITY].curAnim];
  120.  
  121.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  122.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotY = 16;
  123.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  124.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotX = 26;
  125.  
  126. }
  127.  
  128. void Bonuseye(jjOBJ@ obj){
  129.         obj.direction = -1;
  130.         obj.behave(BEHAVIOR::PICKUP, false);
  131.         obj.draw();
  132. }
  133. void Bonus(jjOBJ@ obj){
  134.         obj.putOnGround();
  135.         obj.direction = -1;
  136.         obj.behave(BEHAVIOR::PICKUP, false);
  137.         obj.draw();
  138. }
  139.  
  140. int slope = 0;
  141. int SpeedUpUntil = 0;
  142.  
  143. class FCannon : jjBEHAVIORINTERFACE {
  144.  
  145.         void onBehave(jjOBJ@ obj) {
  146.                 if(p.ammo[WEAPON::TNT] > 1)
  147.                 {obj.delete();}
  148.                 obj.behave(BEHAVIOR::MONITOR); 
  149.         }
  150.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  151.                 if(bullet !is null && play !is null)
  152.                         {obj.behave(BEHAVIOR::EXPLOSION2);
  153.                         jjAddObject(OBJECT::TNTAMMO3, 186*32, 13*32);
  154.                         jjAddObject(OBJECT::TNTAMMO3, 187*32, 13*32);
  155.                         jjAddObject(OBJECT::TNTAMMO3, 188*32, 13*32);
  156.                         jjAddObject(OBJECT::TNTAMMO3, 186*32, 12*32);                  
  157.                         jjAddObject(OBJECT::TNTAMMO3, 187*32, 12*32);
  158.                         jjAddObject(OBJECT::TNTAMMO3, 188*32, 12*32);
  159.                         jjSample(p.xPos, p.yPos, SOUND::COMMON_HARP1, 1000);}
  160.                 return true;
  161.         }
  162.        
  163. }
  164.  
  165. void onFunction0(jjPLAYER@ play) {
  166.         jjTriggers[26] = true;
  167.         jjSetWaterLevel(1984, false);
  168.         jjSample(p.xPos, p.yPos, SOUND::ROBOT_HYDROPUF);}
  169.  
  170. void onFunction1(jjPLAYER@ p) {
  171.         slope = jjGameTicks + 2*61;}
  172.  
  173. void onFunction2(jjPLAYER@ p) {
  174.         slope = 0;}
  175.  
  176. void onFunction3(jjPLAYER@ p) {
  177.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@Atlantius Harbour", STRING::MEDIUM);
  178.         jjEnabledASFunctions[3] = false;}
  179.  
  180. void onFunction4(jjPLAYER@ p) {
  181.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@The Grand Library", STRING::MEDIUM);
  182.         jjTriggers[11] = false;
  183.         jjEnabledASFunctions[4] = false;
  184.         pass = true;
  185.         jjMusicLoad("mo4a_Rock and Lava.ogg");}
  186.  
  187. void onFunction5(jjPLAYER@ p) {
  188.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@Underwater City", STRING::MEDIUM);
  189.         jjEnabledASFunctions[5] = false;}
  190.  
  191. void onFunction6(jjPLAYER@ p) {
  192.         if(thieffly == false)
  193.         {p.showText("@@A key must be somewhere@around here...");}
  194.         thieffly = true;}
  195.  
  196. void onMain() {
  197. gem::deleteCollectedGems();
  198. if(jjKey[9] && jjKey[0x51]) {
  199. p.morphTo(CHAR::JAZZ, false);
  200. }
  201. if(jjKey[9] && jjKey[0x57]) {
  202. p.morphTo(CHAR::SPAZ, false);
  203. }
  204. if(jjKey[9] && jjKey[0x45]) {
  205. p.morphTo(CHAR::LORI, false);
  206. }
  207.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::EXTRALIFE].curAnim];
  208.         anim.frameCount = 1;
  209.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  210.         jjPIXELMAP pass(0*32, 20*32, 1*32, 1*32, 5);
  211.         pass.save(frame);
  212.         frame.hotSpotY = -17;
  213. }
  214. bool buyammo = false, doorunblocked = false, startrush = false, readytorush = false;
  215. void onPlayer(jjPLAYER@ p) {
  216.         gem::trackPlayerGems(p);
  217.         gem::upgradeHealth(p);
  218.         p.lightType = LIGHT::NONE;
  219.         if(p.coins == 0)
  220.         {p.coins += 3;}
  221.                
  222.         if (doorunblocked == false && jjTriggers[1]==true && jjTriggers[2]==true && jjTriggers[3]==true && jjTriggers[4]==true && jjTriggers[4]==true) {
  223.                 p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Spheres collected.");
  224.                 doorunblocked = true;}
  225.  
  226.         if(p.food == 100 && jjKey[0x52] == false && startrush == false)
  227.                 {p.showText("@@@@@@@@@@@@@@@@Press 'R' when you need to use Sugar Rush!", STRING::MEDIUM);
  228.                 p.startSugarRush(0);
  229.                 startrush = true;
  230.                 readytorush = true;}
  231.  
  232.         if(readytorush == true)
  233.                 {p.food = 100;}
  234.  
  235.         if(p.food == 100 && jjKey[0x52])
  236.                 {p.startSugarRush(1400);
  237.                 p.food = 0;
  238.                 readytorush = false;
  239.                 startrush = false;
  240.         }
  241.  
  242.  
  243.         if(leveldone == true && p.xPos > 188*32 && p.yPos >= 40*32 && p.coins <3)
  244.         {p.testForCoins(3);
  245.         p.yPos = p.yPos - 63;
  246.         p.xPos = p.xPos - 63;}
  247.         if(leveldone == true && p.xPos > 188*32 && p.yPos >= 40*32 && p.coins >=3)
  248.         {jjNxt("mo4a_3-4_save", false, true);
  249.         gem::saveGemData();}
  250.  
  251.         if(p.ammo[WEAPON::TNT] < 1 && p.xPos>168*32 && p.xPos<171*32 && p.yPos<16*32 && p.yPos>13*32 && jjKey[0x50] && p.gems[GEM::RED]<50 && buyammo == false)
  252.                 {p.testForGems(50, GEM::RED);}
  253.         if(p.ammo[WEAPON::TNT] < 1 && p.xPos>168*32 && p.xPos<171*32 && p.yPos<16*32 && p.yPos>13*32 && jjKey[0x50] && p.gems[GEM::RED]>=50 && buyammo == false)
  254.         {p.testForGems(50, GEM::RED);
  255.         jjTriggers[9]=true;
  256.         buyammo = true;}
  257.         if(p.ammo[WEAPON::TNT] >= 1 && p.xPos>168*32 && p.xPos<171*32 && p.yPos<16*32 && p.yPos>13*32 && jjKey[0x50] && buyammo == false)
  258.                 {p.showText("@@You already have the weapon.");}
  259. if(p.keyUp && slope > jjGameTicks){
  260.         p.yPos = p.yPos - 4;
  261.         p.invisibility = true;
  262.         jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::HPOLE, p.curFrame, p.direction, SPRITE::PLAYER);
  263.         }
  264. if(p.keyUp == false && slope > jjGameTicks){
  265.         p.invisibility = false;
  266. }
  267. if(slope < jjGameTicks){
  268.         p.invisibility = false;
  269. }
  270.  
  271.   if (SpeedUpUntil > jjGameTicks) {
  272.         p.invincibility = 10;
  273.         p.keyRun = true;
  274.         if(p.keyRight)
  275.         p.xSpeed = 30;
  276.         if(p.keyLeft)
  277.         p.xSpeed = -30;
  278.   }
  279.  
  280. }
  281. bool thieffly= false;
  282.  
  283. class ButterThief : jjBEHAVIORINTERFACE {
  284.         void onBehave(jjOBJ@ obj) {
  285.                 if(thieffly == false)
  286.                 {obj.playerHandling = HANDLING::PLAYERBULLET;}
  287.                 if(thieffly == true && jjTriggers[10]==false)
  288.                 {obj.behave(BEHAVIOR::BUTTERFLY);
  289.                 obj.lightType = LIGHT::LASER;
  290.                 obj.light = 100;
  291.                 obj.playerHandling = HANDLING::ENEMY;
  292.                 jjDrawTile(obj.xPos - 17, obj.yPos + 2, 870);
  293.                                 if(obj.energy == 0)
  294.                                 {obj.state = STATE::KILL;
  295.                                 obj.behavior = BEHAVIOR::EXPLOSION;
  296.                                 jjAddObject(OBJECT::SANDWICH, obj.xPos, obj.yPos-32);
  297.                                 }
  298.                 }
  299.         }
  300.        
  301. }
  302.  
  303. class Fastrun : jjBEHAVIORINTERFACE {
  304.         void onBehave(jjOBJ@ obj) {
  305.  
  306. obj.behave(BEHAVIOR::PICKUP, false);
  307. obj.determineCurAnim(ANIM::PICKUPS, 33);
  308. ++obj.counter;
  309.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  310.  
  311.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -24);
  312.  
  313. }
  314.  
  315.         bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
  316.         play.timerStart(800);
  317.                 SpeedUpUntil = jjGameTicks + 13 * 61;
  318.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  319.                 obj.frameID = 0;
  320.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
  321.  
  322.                 return true;
  323.         }
  324.  
  325. }
  326.  
  327. class Coin : jjBEHAVIORINTERFACE {
  328.  
  329.         void onBehave(jjOBJ@ obj) {
  330.         obj.behave(BEHAVIOR::PICKUP, false);
  331.         if(jjTriggers[1] == true && jjTriggers[2] == true && jjTriggers[3] == true && jjTriggers[4] == true && jjTriggers[5] == true)
  332.         {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);}
  333.         else    {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENT);}
  334.         }
  335.  
  336.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  337.         if(jjTriggers[1] == true && jjTriggers[2] == true && jjTriggers[3] == true && jjTriggers[4] == true && jjTriggers[5] == true)
  338.         {obj.scriptedCollisions = false;}
  339.         else {p.showText("@@Collect 5 Spheres first.");}
  340.         return true;
  341.         }
  342.  
  343. }
  344.  
  345.  
  346. void TimeMachine(jjOBJ@ obj){
  347.         obj.behave(BEHAVIOR::EVA, false);
  348.                         jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, 1, SPRITE::PALSHIFT, 8);
  349.  
  350. }
  351.  
  352. void Tree(jjOBJ@ enemy) {
  353. jjPLAYER@ play = jjLocalPlayers[0];
  354.                 if (enemy.xPos > play.xPos)
  355.                                 enemy.xPos = enemy.xPos - (2+jjDifficulty/4);
  356.                 else if (enemy.xPos < play.xPos)
  357.                                 enemy.xPos = enemy.xPos + (2+jjDifficulty/4);
  358.                 if (enemy.yPos > play.yPos)
  359.                                 enemy.yPos = enemy.yPos - (2+jjDifficulty/4);
  360.                 else if (enemy.yPos < play.yPos)
  361.                                 enemy.yPos = enemy.yPos + (2+jjDifficulty/4);
  362. if (jjMaskedVLine(enemy.xSpeed > 0 ? enemy.xPos + 16 : enemy.xPos - 16, enemy.yPos, 1)) {
  363.                                 enemy.delete();
  364.                   int explosionID = jjAddObject(OBJECT::BLASTERBULLET, enemy.xPos, enemy.yPos, enemy.creator, CREATOR::OBJECT);
  365.                 jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 4, true);
  366.                 jjObjects[explosionID].state = STATE::EXPLODE;
  367.                         }
  368.                 enemy.determineCurAnim(ANIM::WITCH, 3);
  369.                 enemy.determineCurFrame();
  370.                 enemy.frameID = enemy.counter/8;
  371.                 //enemy.draw();
  372.                 ++enemy.counter;
  373.                 enemy.counter += 1;
  374.                  if (enemy.counter >200)
  375.                 {enemy.delete();
  376.                   int explosionID = jjAddObject(OBJECT::BLASTERBULLET, enemy.xPos, enemy.yPos, enemy.creator, CREATOR::OBJECT);
  377.                 jjObjects[explosionID].determineCurAnim(ANIM::AMMO, 4, true);
  378.                 jjObjects[explosionID].state = STATE::EXPLODE;
  379.                 }
  380.         jjDrawSpriteFromCurFrame(enemy.xPos, enemy.yPos, enemy.curFrame, enemy.direction, SPRITE::PALSHIFT, 24);
  381.  
  382. }
  383.  
  384.  
  385. class Key : jjBEHAVIORINTERFACE {
  386.  
  387.         void onBehave(jjOBJ@ obj) {
  388.                 obj.behave(BEHAVIOR::PICKUP, false);
  389.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::AIRBOARD].curAnim];
  390.         anim.frameCount = 1;
  391.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  392.         jjPIXELMAP doorkey(0, 29*32, 1*32, 1*32, 5);
  393.         doorkey.save(frame);
  394.                 ++obj.counter;
  395.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  396.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  397. }
  398.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  399.                 jjTriggers[0] = true;
  400.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  401.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  402.  
  403.                 return true;
  404.         }
  405. }
  406. bool leveldone = false;
  407. class Key2 : jjBEHAVIORINTERFACE {
  408.  
  409.         void onBehave(jjOBJ@ obj) {
  410.                 obj.behave(BEHAVIOR::PICKUP, false);
  411.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::SANDWICH].curAnim];
  412.         anim.frameCount = 1;
  413.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  414.         jjPIXELMAP doorkey(0, 29*32, 1*32, 1*32, 5);
  415.         doorkey.save(frame);
  416.                 ++obj.counter;
  417.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  418.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  419. }
  420.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  421.                 jjTriggers[10] = true;
  422.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  423.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  424.                 leveldone = true;
  425.                 return true;
  426.         }
  427. }
  428.  
  429. class RedSphere : jjBEHAVIORINTERFACE {
  430.  
  431.         void onBehave(jjOBJ@ obj) {
  432.                 obj.behave(BEHAVIOR::PICKUP, false);
  433.                 obj.lightType = LIGHT::FLICKER;
  434.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::WEENIE].curAnim];
  435.         anim.frameCount = 1;
  436.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  437.         jjPIXELMAP sphere(0, 21*32, 1*32, 1*32, 5);
  438.         sphere.save(frame);
  439.                 ++obj.counter;
  440.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  441.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  442. }
  443.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  444.                 jjTriggers[1] = true;
  445.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  446.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  447.  
  448.                 return true;
  449.         }
  450. }
  451.  
  452. class BlueSphere : jjBEHAVIORINTERFACE {
  453.  
  454.         void onBehave(jjOBJ@ obj) {
  455.                 obj.behave(BEHAVIOR::PICKUP, false);
  456.                 obj.lightType = LIGHT::FLICKER;
  457.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::CHICKENLEG].curAnim];
  458.         anim.frameCount = 1;
  459.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  460.         jjPIXELMAP sphere(0, 22*32, 1*32, 1*32, 5);
  461.         sphere.save(frame);
  462.                 ++obj.counter;
  463.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  464.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  465. }
  466.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  467.                 jjTriggers[2] = true;
  468.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  469.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  470.  
  471.                 return true;
  472.         }
  473. }
  474.  
  475. class YellowSphere : jjBEHAVIORINTERFACE {
  476.  
  477.         void onBehave(jjOBJ@ obj) {
  478.                 obj.behave(BEHAVIOR::PICKUP, false);
  479.                 obj.lightType = LIGHT::FLICKER;
  480.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BURGER].curAnim];
  481.         anim.frameCount = 1;
  482.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  483.         jjPIXELMAP sphere(0, 23*32, 1*32, 1*32, 5);
  484.         sphere.save(frame);
  485.                 ++obj.counter;
  486.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  487.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  488. }
  489.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  490.                 jjTriggers[3] = true;
  491.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  492.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  493.  
  494.                 return true;
  495.         }
  496. }
  497.  
  498. class GreenSphere : jjBEHAVIORINTERFACE {
  499.  
  500.         void onBehave(jjOBJ@ obj) {
  501.                 obj.behave(BEHAVIOR::PICKUP, false);
  502.                 obj.lightType = LIGHT::FLICKER;
  503.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::HAM].curAnim];
  504.         anim.frameCount = 1;
  505.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  506.         jjPIXELMAP sphere(0, 24*32, 1*32, 1*32, 5);
  507.         sphere.save(frame);
  508.                 ++obj.counter;
  509.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  510.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  511. }
  512.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  513.                 jjTriggers[4] = true;
  514.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  515.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  516.  
  517.                 return true;
  518.         }
  519. }
  520.  
  521. class PurpleSphere : jjBEHAVIORINTERFACE {
  522.  
  523.         void onBehave(jjOBJ@ obj) {
  524.                 obj.behave(BEHAVIOR::PICKUP, false);
  525.                 obj.lightType = LIGHT::FLICKER;
  526.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::FRIES].curAnim];
  527.         anim.frameCount = 1;
  528.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  529.         jjPIXELMAP sphere(0, 25*32, 1*32, 1*32, 5);
  530.         sphere.save(frame);
  531.                 ++obj.counter;
  532.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  533.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  534. }
  535.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  536.                 jjTriggers[5] = true;
  537.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  538.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  539.  
  540.                 return true;
  541.         }
  542. }
  543.  
  544. void onLevelReload()  {
  545.         gem::restorePlayerGems();
  546.         jjLocalPlayers[0].lives++;
  547.         jjWaterLighting = WATERLIGHT::GLOBAL;
  548.         buyammo == false;
  549.         jjTriggers[9] = false;
  550.         for (uint i = 0; i < 32; ++i)
  551.                 jjTriggers[i] = SavedTriggers[i];
  552. }
  553.  
  554. jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
  555. class Sign {
  556.         private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
  557.         private string text;
  558.         private uint widthOfText;
  559.         Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
  560.         Sign(int xTile, int yTile, const string &in t) {
  561.                 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
  562.                 yPos = yTile * 32; //
  563.                 text = t;
  564.                 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.
  565.                 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.
  566.                 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.
  567.         }
  568.         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.
  569.                 layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
  570.                 layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
  571.         }
  572. }
  573. const array<Sign> Signs = {
  574.         Sign(54, 19, "Have you seen my\nLibrary Pass yet?"),
  575.         Sign(146, 22, "What? You have a PASS?\nOh... well... Anyway..."),
  576.         Sign(117, 37, "No sign of the\nFreezer I guess..."),
  577.         Sign(132, 11, "No entrance to the\nbuildings with powerups..."),       
  578.         Sign(189, 27, "The portrait upstairs belongs to Thrasymakhos,\nour ex leader who has gone missing lately."),
  579.         Sign(171, 13, "Press P if you'd like to\nbuy Fusion Cannon for 50 Gems."),
  580.  
  581. };
  582.  
  583. void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
  584.         if(jjKey[0x54]){
  585.         const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
  586.         for (uint signID = 0; signID < Signs.length; ++signID)
  587.                 Signs[signID].draw(layer, textIntensity);
  588. }
  589. }
  590.  
  591. array<bool> SavedTriggers(32, false);
  592. //Extendable Checkpoints by VioletCLM
  593. void CheckpointWrapper(jjOBJ@ obj) {
  594.   if (obj.state == STATE::STOP) { //don't do anything anymore
  595.     jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  596.   } else if (obj.state == STATE::DEACTIVATE) { //due to death
  597.     obj.deactivate();
  598.   } else {
  599.     obj.behave(BEHAVIOR::CHECKPOINT);
  600.         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  601.     if (obj.state == STATE::DONE) { //triggered by the player hitting it
  602.       obj.state = STATE::STOP;
  603.       //save the current state of some properties
  604.       for (uint i = 0; i < 32; ++i)
  605.         SavedTriggers[i] = jjTriggers[i];
  606.  
  607.       //OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
  608.       for (int i = jjObjectCount; --i > 0;) {
  609.         jjOBJ@ obj2 = jjObjects[i];
  610.         if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
  611.           obj2.state = STATE::SLEEP;
  612.           obj2.var[0] = 0;
  613.         }
  614.       }
  615.     }
  616.   }
  617. }
  618. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  619.         return MLLE::WeaponHook.drawAmmo(player, canvas);
  620. }
  621.  
  622.